closes #35
diff --git a/weinre.build/.gitignore b/weinre.build/.gitignore
index b1713a9..cdd5de8 100644
--- a/weinre.build/.gitignore
+++ b/weinre.build/.gitignore
@@ -3,5 +3,6 @@
out
tmp
vendor
+node_modules
personal.properties
\ No newline at end of file
diff --git a/weinre.build/build.xml b/weinre.build/build.xml
index 1826ebd..290139a 100644
--- a/weinre.build/build.xml
+++ b/weinre.build/build.xml
@@ -1,27 +1,27 @@
<!--
* 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
-->
-<project name="build" default="build" basedir=".">
+<project name="build" default="build" basedir=".">
<!-- ============================================================
set properties
============================================================ -->
-
+
<property file="personal.properties" />
<property file="build.properties" />
<property file="vendor.properties" />
<!-- hint: override in your personal.properties -->
<property name="BUILDER" value="The Unknown Builder"/>
-
+
<basename property="ant.file.basename" file="${ant.file}"/>
<available property="VENDOR_FOUND" file="${VENDOR}"/>
-
+
<tstamp>
<format property="TSTAMP_STARTED" pattern="HH:mm:ss"/>
</tstamp>
@@ -29,14 +29,14 @@
<tstamp>
<format property="BUILD_NUMBER_DATE" pattern="yyyy-MM-dd--HH-mm-ss" timezone="GMT"/>
</tstamp>
-
+
<property name="BUILD_NUMBER" value="${WEINRE_VERSION}build-${BUILD_NUMBER_DATE}"/>
-
-
+
+
<!-- ============================================================
main entry point
============================================================ -->
-
+
<target name="build" depends="build-dev">
<antcall target="build-jar"/>
<antcall target="build-ui-jar"/>
@@ -53,12 +53,12 @@
<target name="clean">
<delete dir="${OUT}"/>
<mkdir dir="${OUT}"/> <!-- this is an Eclipse source folder! -->
-
+
<delete dir="${TMP}"/>
<delete dir="${CACHED}"/>
<delete dir="${VENDOR}"/>
</target>
-
+
<!-- ============================================================
development-time build
============================================================ -->
@@ -66,14 +66,14 @@
<target name="build-dev">
<delete dir="${OUT}"/>
<mkdir dir="${OUT}"/>
-
- <property
+
+ <property
name = "build-info-text"
value = "weinre build ${BUILD_NUMBER} by ${BUILDER}"
/>
-
+
<echo file="${OUT}/build-info.txt" message="${build-info-text}"/>
-
+
<antcall target="build-vendor"/>
<antcall target="compile-java"/>
<antcall target="build-web"/>
@@ -85,7 +85,7 @@
<tstamp>
<format property="TSTAMP_FINISHED" pattern="HH:mm:ss"/>
</tstamp>
-
+
<property name="MESSAGE_FINISHED" value="at ${TSTAMP_FINISHED} for ${ant.file}:build-dev"/>
<antcall target="finished"/>
@@ -100,7 +100,7 @@
<delete dir="../${PROJECT_SERVER}/bin"/>
<mkdir dir="../${PROJECT_SERVER}/bin"/>
- <javac
+ <javac
srcdir = "../${PROJECT_SERVER}/src"
destdir = "../${PROJECT_SERVER}/bin"
debug = "true"
@@ -113,11 +113,11 @@
<classpath path="../${PROJECT_BUILD}/vendor/jetty/servlet-api.jar"/>
<compilerarg value="-Xlint"/>
</javac>
-
+
<delete dir="../${PROJECT_APPLICATION}/bin"/>
<mkdir dir="../${PROJECT_APPLICATION}/bin"/>
-
- <javac
+
+ <javac
srcdir = "../${PROJECT_APPLICATION}/src"
destdir = "../${PROJECT_APPLICATION}/bin"
debug = "true"
@@ -129,9 +129,9 @@
<classpath path="../${PROJECT_BUILD}/vendor/swt/cocoa-macosx-x86_64/swt.jar"/>
<compilerarg value="-Xlint"/>
</javac>
-
+
</target>
-
+
<!-- ============================================================
build vendor libs
============================================================ -->
@@ -139,7 +139,7 @@
<target name="build-vendor" unless="VENDOR_FOUND">
<ant antfile="get-vendor.xml"/>
</target>
-
+
<!-- ============================================================
basic web resources
============================================================ -->
@@ -147,22 +147,50 @@
<target name="build-web">
<delete dir="${WEB}" />
<mkdir dir="${WEB}" />
-
+
<delete dir="${TMP}" />
<mkdir dir="${TMP}" />
+<!--
<echo message="compiling scoop modules"/>
<exec executable="python" failonerror="true" failifexecutionfails="true">
<arg file="vendor/scooj/scoopc.py"/>
- <arg value="--out"/>
+ <arg value="-o"/>
<arg file="${TMP}/modules"/>
<arg file="../${PROJECT_WEB}/modules"/>
</exec>
-
+-->
+
+ <echo message="compiling CoffeeScript modules"/>
+ <mkdir dir="${TMP}/modules/weinre/client" />
+ <mkdir dir="${TMP}/modules/weinre/common" />
+ <mkdir dir="${TMP}/modules/weinre/target" />
+
+ <echo message="compiling CoffeeScript files in: ${PROJECT_WEB}/modules/weinre/client"/>
+ <exec executable="sh" failonerror="true" failifexecutionfails="true">
+ <arg value="-c"/>
+ <arg value="node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/client ../${PROJECT_WEB}/modules/weinre/client/*.coffee"/>
+ </exec>
+
+ <echo message="compiling CoffeeScript files in: ${PROJECT_WEB}/modules/weinre/common"/>
+ <exec executable="sh" failonerror="true" failifexecutionfails="true">
+ <arg value="-c"/>
+ <arg value="node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/common ../${PROJECT_WEB}/modules/weinre/common/*.coffee"/>
+ </exec>
+
+ <echo message="compiling CoffeeScript files in: ${PROJECT_WEB}/modules/weinre/target"/>
+ <exec executable="sh" failonerror="true" failifexecutionfails="true">
+ <arg value="-c"/>
+ <arg value="node_modules/.bin/coffee --compile --bare --output ${TMP}/modules/weinre/target ../${PROJECT_WEB}/modules/weinre/target/*.coffee"/>
+ </exec>
+
+
+<!--
<copy todir="${TMP}/modules">
<fileset file="${VENDOR}/scooj/scooj.js"/>
</copy>
-
+-->
+
<echo message="transportd-izing modules"/>
<exec executable="python" failonerror="true" failifexecutionfails="true">
<arg file="vendor/modjewel/module2transportd.py"/>
@@ -175,11 +203,11 @@
<copy todir="${WEB}">
<fileset file="${VENDOR}/modjewel/modjewel-require.js"/>
</copy>
-
+
<copy todir="${WEB}">
<fileset file="${VENDOR}/json2/json2.js"/>
</copy>
-
+
<copy todir="${WEB}">
<fileset dir="../${PROJECT_WEB}">
<exclude name="versions.js"/>
@@ -193,23 +221,23 @@
</copy>
<echo message="building InjectedScript.js"/>
- <echo
+ <echo
file = "${WEB}/weinre/target/InjectedScript.js"
message = "var injectedScriptConstructor = ${line.separator}"
/>
- <concat
+ <concat
destfile = "${WEB}/weinre/target/InjectedScript.js"
append = "true"
>
<fileset file="${VENDOR}/webkit/WebCore/inspector/InjectedScriptSource.js"/>
</concat>
-
+
<echo message="building versions.js"/>
<copy todir="${WEB}">
<fileset dir="../${PROJECT_WEB}">
<include name="versions.js"/>
</fileset>
-
+
<filterset>
<filter token="WEINRE_VERSION" value="${WEINRE_VERSION}"/>
<filter token="BUILD_NUMBER" value="${BUILD_NUMBER}"/>
@@ -233,7 +261,7 @@
<arg value="vendor/webkit/WebCore/CSSPropertyNames.in"/>
<arg value="${WEB}/add-css-properties.js"/>
</exec>
-
+
</target>
<!-- ============================================================
@@ -243,9 +271,9 @@
<target name="build-doc">
<mkdir dir="${WEB}/doc" />
-
+
<copy todir="${WEB}/doc" file="${OUT}/build-info.txt"/>
-
+
<build-html name="Building" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
<build-html name="Home" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
<build-html name="Installing" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
@@ -255,17 +283,17 @@
<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}"/>
-
+
<copy file="${WEB}/doc/Home.html" tofile="${WEB}/doc/index.html"/>
-
+
<copy todir="${WEB}/doc/images" file="../${PROJECT_WEB}/images/weinre-icon-64x64.png"/>
<copy todir="${WEB}/doc/css"> <fileset dir="../${PROJECT_DOC}/css"/> </copy>
<copy todir="${WEB}/doc/images"> <fileset dir="../${PROJECT_DOC}/images"/> </copy>
<copy todir="${WEB}/doc/scripts"> <fileset dir="../${PROJECT_DOC}/scripts"/> </copy>
-
+
</target>
-
+
<!-- ============================================================
convert IDL to JSON (cached)
============================================================ -->
@@ -275,21 +303,21 @@
<srcfiles dir="../${PROJECT_SERVER}/interfaces" includes="*.idl"/>
<srcfiles dir="${VENDOR}/webkit/WebCore/inspector" includes="*.idl"/>
</uptodate>
-
+
<antcall target="build-json-idl-fresh"/>
-
+
<copy todir="${WEB}/interfaces"> <fileset dir="${CACHED}/json-idl"/></copy>
</target>
-
+
<!-- ============================================================
convert IDL to JSON (slow part)
============================================================ -->
-
+
<target name="build-json-idl-fresh" unless="JSON_IDL_UPTODATE">
<delete dir="${CACHED}/json-idl"/>
<mkdir dir="${CACHED}/json-idl"/>
-
+
<simple-idl2json name="WeinreClientCommands" oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
<simple-idl2json name="WeinreClientEvents" oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
<simple-idl2json name="WeinreTargetCommands" oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
@@ -298,12 +326,12 @@
<simple-idl2json name="WeinreExtraTargetEvents" oDir="${CACHED}/json-idl" iDir="../${PROJECT_SERVER}/interfaces"/>
<simple-idl2json name="InjectedScriptHost" oDir="${CACHED}/json-idl" iDir="${VENDOR}/webkit/WebCore/inspector"/>
-
+
<simple-idl2json name="Inspector" oDir="${CACHED}/json-idl" iDir="${VENDOR}/webkit/WebCore/inspector">
<arg value="--anyType"/>
<arg value="Value"/>
</simple-idl2json>
-
+
<simple-idl2json name="InspectorFrontendHost" oDir="${CACHED}/json-idl" iDir="${VENDOR}/webkit/WebCore/inspector">
<arg value="--anyType"/>
<arg value="MouseEvent"/>
@@ -329,24 +357,24 @@
============================================================ -->
<target name="build-target">
-
+
<mkdir dir="${WEB}/target"/>
-
+
<exec executable="python" failonerror="true" failifexecutionfails="true">
<arg file="scripts/build-target-scripts.py"/>
<arg file="../${PROJECT_WEB}/demo/weinre-demo-pieces.html"/>
<arg file="${WEB}"/>
<arg file="${WEB}/target"/>
</exec>
-
+
</target>
<!-- ============================================================
build the web/client files
============================================================ -->
-
+
<target name="build-client">
-
+
<copy todir="${WEB}/client/nls/English.lproj">
<fileset file="${VENDOR}/webkit/WebCore/English.lproj/localizedStrings.js"/>
</copy>
@@ -359,51 +387,51 @@
<arg file="scripts/build-client-html.py"/>
<arg file="${WEB}"/>
</exec>
-
+
</target>
-
+
<!-- ============================================================
build the main jar
============================================================ -->
-
+
<target name="build-jar">
-
+
<jar destfile="${OUT}/weinre.jar">
<manifest>
<attribute name="Built-By" value="${ant.file.basename} - ${ant.project.name}"/>
<attribute name="Main-Class" value="weinre.server.Main"/>
</manifest>
-
+
<fileset file="${OUT}/build-info.txt"/>
<zipfileset src="${VENDOR}/jetty/jetty.jar">
<exclude name="about*.html"/>
<exclude name="META-INF/**/*"/>
</zipfileset>
-
+
<zipfileset src="${VENDOR}/jetty/servlet-api.jar">
<exclude name="META-INF/**/*"/>
</zipfileset>
-
+
<zipfileset src="${VENDOR}/cli/commons-cli.jar">
<exclude name="META-INF/**/*"/>
</zipfileset>
-
+
<zipfileset src="${VENDOR}/json4j/json4j.jar">
<exclude name="META-INF/**/*"/>
</zipfileset>
-
+
<fileset dir="../${PROJECT_SERVER}/bin"/>
-
+
<zipfileset dir="${WEB}" prefix="web"/>
</jar>
-
+
</target>
<!-- ============================================================
build the ui jar
============================================================ -->
-
+
<target name="build-ui-jar">
<fileset dir="../${PROJECT_APPLICATION}/bin"/>
@@ -413,22 +441,22 @@
<attribute name="Built-By" value="${ant.file.basename} - ${ant.project.name}"/>
<attribute name="Main-Class" value="weinre.application.GUIMain"/>
</manifest>
-
+
<fileset file="${OUT}/build-info.txt"/>
-
+
<fileset dir="../${PROJECT_APPLICATION}/bin"/>
-
+
<zipfileset src="${VENDOR}/swt/cocoa-macosx-x86_64/swt.jar">
<exclude name="META-INF/**/*"/>
</zipfileset>
</jar>
-
+
</target>
<!-- ============================================================
build the mac application
============================================================ -->
-
+
<target name="build-application-mac">
<delete dir="${OUT}/applications/mac"/>
<mkdir dir="${OUT}/applications/mac/weinre.app"/>
@@ -438,7 +466,7 @@
<exclude name="**/Info.plist"/>
</fileset>
</copy>
-
+
<copy todir="${OUT}/applications/mac/weinre.app">
<fileset dir="../${PROJECT_APPLICATION}/resources/macosx/weinre.app">
<include name="**/Info.plist"/>
@@ -447,25 +475,25 @@
<filter token="VERSION" value="${WEINRE_VERSION}"/>
</filterset>
</copy>
-
+
<chmod file="${OUT}/applications/mac/weinre.app/Contents/MacOS/launcher" perm="+x"/>
<copy todir="${OUT}/applications/mac/weinre.app/Contents/MacOS" file="${OUT}/weinre.jar" />
<copy todir="${OUT}/applications/mac/weinre.app/Contents/MacOS" file="${OUT}/weinre-ui.jar"/>
<copy todir="${OUT}/applications/mac/weinre.app/Contents/Resources" file="${OUT}/build-info.txt"/>
-
+
</target>
<!-- ============================================================
build the archives
============================================================ -->
<target name="build-archives">
-
+
<!-- =================================== -->
<delete dir="${OUT}/archives"/>
<mkdir dir="${OUT}/archives"/>
-
+
<delete dir="${OUT}/files"/>
-
+
<delete dir="${OUT}/files/weinre-jar"/>
<mkdir dir="${OUT}/files/weinre-jar"/>
<copy todir="${OUT}/files/weinre-jar" file="${OUT}/build-info.txt"/>
@@ -487,7 +515,7 @@
<fileset dir="${OUT}/applications/mac"/>
</copy>
<chmod file="${OUT}/files/weinre-mac/weinre.app/Contents/MacOS/launcher" perm="+x"/>
-
+
<!-- ant's zip task doesn't preserve permission bits -->
<exec executable="zip" dir="${OUT}/files">
<arg value="-q"/>
@@ -503,7 +531,7 @@
<copy todir="${OUT}/files/weinre-doc">
<fileset dir="${OUT}/web/doc"/>
</copy>
-
+
<!-- ant's zip task doesn't preserve permission bits -->
<exec executable="zip" dir="${OUT}/files">
<arg value="-q"/>
@@ -521,7 +549,7 @@
<copy todir="${OUT}/files/weinre-src/weinre.doc"> <fileset dir="../weinre.doc" excludes="**/bin/"/></copy>
<copy todir="${OUT}/files/weinre-src/weinre.server"> <fileset dir="../weinre.server" excludes="**/bin/"/></copy>
<copy todir="${OUT}/files/weinre-src/weinre.web"> <fileset dir="../weinre.web" excludes="**/bin/"/></copy>
-
+
<!-- ant's zip task doesn't preserve permission bits -->
<exec executable="zip" dir="${OUT}/files">
<arg value="-q"/>
@@ -529,25 +557,25 @@
<arg value="../archives/weinre-src-${BUILD_NUMBER}.zip"/>
<arg value="weinre-src"/>
</exec>
-
+
<!-- =================================== -->
<delete dir="${OUT}/files"/>
-
+
</target>
-
-
+
+
<!-- ============================================================
done!
============================================================ -->
-
+
<target name="finished">
<echo>ant completed successfully ${MESSAGE_FINISHED}</echo>
</target>
-
+
<!-- ============================================================
done! via growl
============================================================ -->
-
+
<target name="finished-growl" if="USE_GROWL">
<exec os="Mac OS X" executable="growlnotify">
<arg value="-m"/>
@@ -559,7 +587,7 @@
<!-- ============================================================
macro to compile IDL to JSON
============================================================ -->
-
+
<macrodef name="simple-idl2json">
<attribute name="name"/>
<attribute name="iDir"/>
@@ -575,11 +603,11 @@
</exec>
</sequential>
</macrodef>
-
+
<!-- ============================================================
macro to compile HTML
============================================================ -->
-
+
<macrodef name="build-html">
<attribute name="name"/>
<attribute name="iDir"/>
@@ -600,6 +628,6 @@
<echo>generated @{oDir}/@{name}.html</echo>
</sequential>
</macrodef>
-
+
<!-- ============================================================ -->
</project>
diff --git a/weinre.build/get-vendor.xml b/weinre.build/get-vendor.xml
index 4e2b477..1984cf9 100644
--- a/weinre.build/get-vendor.xml
+++ b/weinre.build/get-vendor.xml
@@ -1,23 +1,23 @@
<!--
* 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
-->
<project name="get-vendor" default="get-vendor" basedir=".">
-
+
<property file="personal.properties"/>
<property file="build.properties"/>
<property file="vendor.properties"/>
-
+
<!-- ============================================================ -->
<target name="get-vendor">
<echo>Go get some coffee, this is going to take a while</echo>
-
+
<delete dir="${TMP}"/>
-
+
<delete dir="${VENDOR}"/>
<mkdir dir="${VENDOR}"/>
@@ -26,20 +26,21 @@
<antcall target="get-json4j"/>
<antcall target="get-jetty"/>
<antcall target="get-scooj"/>
+ <antcall target="get-coffeescript"/>
<antcall target="get-modjewel"/>
<antcall target="get-web-inspector"/>
<antcall target="get-swt-mac"/>
</target>
-
+
<!-- ============================================================ -->
<target name="get-cli">
<delete dir="${VENDOR}/cli"/>
<mkdir dir="${VENDOR}/cli"/>
-
+
<delete dir="${TMP}"/>
<mkdir dir="${TMP}"/>
-
+
<get src="${CLI_URL}" dest="${TMP}/commons-cli.zip" verbose="false"/>
<unzip src="${TMP}/commons-cli.zip" dest="${TMP}">
<patternset>
@@ -47,20 +48,20 @@
<include name="${CLI_BASENAME}.jar"/>
</patternset>
</unzip>
-
-
+
+
<copy file="${TMP}/${CLI_BASENAME}.jar" tofile="${VENDOR}/cli/commons-cli.jar"/>
<copy file="${TMP}/${CLI_BASENAME}-sources.jar" tofile="${VENDOR}/cli/commons-cli-src.jar"/>
-
+
<delete dir="${TMP}"/>
</target>
-
+
<!-- ============================================================ -->
<target name="get-json4j">
<delete dir="${VENDOR}/json4j"/>
<mkdir dir="${VENDOR}/json4j"/>
-
+
<delete dir="${TMP}"/>
<mkdir dir="${TMP}"/>
@@ -72,7 +73,7 @@
</unzip>
<copy file="${TMP}/apache-wink-${JSON4J_VERSION}/ext/wink-json4j-provider/lib/wink-json4j-${JSON4J_VERSION}.jar" tofile="${VENDOR}/json4j/json4j.jar"/>
-
+
<delete dir="${TMP}"/>
<mkdir dir="${TMP}"/>
<get src="${JSON4J_SRC_URL}" dest="${TMP}/json4j-src.zip" verbose="false"/>
@@ -81,99 +82,109 @@
<include name="**/wink-json4j/src/main/java/org/apache/wink/json4j/**/*"/>
</patternset>
</unzip>
-
+
<zip destfile="${VENDOR}/json4j/json4j-src.jar" basedir="${TMP}/src"/>
<delete dir="${TMP}"/>
</target>
-
+
<!-- ============================================================ -->
<target name="get-jetty">
<delete dir="${VENDOR}/jetty"/>
<mkdir dir="${VENDOR}/jetty"/>
-
+
<get src="${JETTY_SRC_URL}" dest="${VENDOR}/jetty/jetty-src.jar" verbose="false"/>
<get src="${JETTY_BIN_URL}" dest="${VENDOR}/jetty/jetty.jar" verbose="false"/>
<get src="${JAVAX_SERVLET_URL}" dest="${VENDOR}/jetty/servlet-api.jar" verbose="false"/>
</target>
-
+
<!-- ============================================================ -->
<target name="get-scooj">
<delete dir="${VENDOR}/scooj"/>
<mkdir dir="${VENDOR}/scooj"/>
-
+
<get src="${SCOOJ_URL_PREFIX}/scooj.js" dest="${VENDOR}/scooj/scooj.js" verbose="false"/>
<get src="${SCOOJ_URL_PREFIX}/scoopc.py" dest="${VENDOR}/scooj/scoopc.py" verbose="false"/>
</target>
-
+
+ <!-- ============================================================ -->
+
+ <target name="get-coffeescript">
+ <echo message="coffee-script@${COFFEESCRIPT_VERSION}"/>
+ <exec executable="npm">
+ <arg value="install"/>
+ <arg value="coffee-script@${COFFEESCRIPT_VERSION}"/>
+ </exec>
+ </target>
+
<!-- ============================================================ -->
<target name="get-modjewel">
<delete dir="${VENDOR}/modjewel"/>
<mkdir dir="${VENDOR}/modjewel"/>
-
+
<get src="${MODJEWEL_URL_PREFIX}/modjewel-require.js" dest="${VENDOR}/modjewel/modjewel-require.js" verbose="false"/>
<get src="${MODJEWEL_URL_PREFIX}/module2transportd.py" dest="${VENDOR}/modjewel/module2transportd.py" verbose="false"/>
</target>
-
+
<!-- ============================================================ -->
<target name="get-web-inspector">
<delete dir="${VENDOR}/webkit"/>
<mkdir dir="${VENDOR}/webkit/WebCore"/>
-
+
<exec executable="svn" dir="${VENDOR}/webkit/WebCore">
<arg value="export"/>
<arg value="-r"/>
<arg value="${WEBKIT_VERSION}"/>
<arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/inspector"/>
</exec>
-
+
<exec executable="svn" dir="${VENDOR}/webkit/WebCore">
<arg value="export"/>
<arg value="-r"/>
<arg value="${WEBKIT_VERSION}"/>
<arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/English.lproj"/>
</exec>
-
+
<exec executable="svn" dir="${VENDOR}/webkit/WebCore">
<arg value="export"/>
<arg value="-r"/>
<arg value="${WEBKIT_VERSION}"/>
<arg value="${WEBKIT_URL_PREFIX}/Source/WebCore/css/CSSPropertyNames.in"/>
</exec>
-
+
<exec executable="grep" outputproperty="gpl-grep-results" dir="${VENDOR}/webkit/WebCore">
- <arg value="-r"/>
- <arg value="GPL"/>
- <arg value="."/>
+ <arg value="-r"/>
+ <arg value="GPL"/>
+ <arg value="."/>
</exec>
-
+
<condition property="found-no-gpl-files">
<equals arg1="" arg2="${gpl-grep-results}"/>
</condition>
-
+
<fail unless="found-no-gpl-files" message="The string GPL was found in the WebKit files"/>
-
+
</target>
-
+
<!-- ============================================================ -->
<target name="get-swt-mac">
<delete dir="${VENDOR}/swt"/>
<mkdir dir="${VENDOR}/swt"/>
-
+
<delete dir="${TMP}"/>
<mkdir dir="${TMP}"/>
-
+
<get src="${SWT_URL_PREFIX}/swt-${SWT_VERSION_MAJOR}-cocoa-macosx-x86_64.zip" dest="${TMP}/swt.zip" verbose="false"/>
<unzip src="${TMP}/swt.zip" dest="${TMP}"/>
-
+
<copy file="${TMP}/src.zip" tofile="${VENDOR}/swt/cocoa-macosx-x86_64/swt-src.jar"/>
<copy file="${TMP}/swt-debug.jar" tofile="${VENDOR}/swt/cocoa-macosx-x86_64/swt.jar"/>
-
+
<delete dir="${TMP}"/>
</target>
@@ -182,7 +193,7 @@
<target name="get-json2">
<delete dir="${VENDOR}/json2"/>
<mkdir dir="${VENDOR}/json2"/>
-
+
<get src="${JSON2_URL_PREFIX}/json2.js" dest="${VENDOR}/json2/json2.js" verbose="false"/>
</target>
diff --git a/weinre.build/scripts/build-client-html.py b/weinre.build/scripts/build-client-html.py
index 690572a..5186010 100644
--- a/weinre.build/scripts/build-client-html.py
+++ b/weinre.build/scripts/build-client-html.py
@@ -3,7 +3,7 @@
# ---
# 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
# ---
@@ -19,24 +19,24 @@
error("expecting parameters [web directory]")
webDir = sys.argv[1]
-
+
iFileName = os.path.join(webDir, "client/inspector.html")
oFileName = os.path.join(webDir, "client/index.html")
moduleDir = os.path.join(webDir, "weinre")
-
+
if not os.path.exists(iFileName): error("file does not exist: %s" % iFileName)
if not os.path.exists(moduleDir): error("module directory does not exist: %s" % moduleDir)
if not os.path.isdir(moduleDir): error("module directory is not a directory: %s" % moduleDir)
-
+
createIndexFile(iFileName, oFileName, moduleDir)
#--------------------------------------------------------------------
def createIndexFile(iFileName, oFileName, moduleDir):
with open(iFileName) as iFile: lines = iFile.readlines()
-
+
pattern_head_start = re.compile(r"^\s*<meta http-equiv=\"content-type\".*$")
pattern_head_end = re.compile(r"^\s*</head>\s$")
-
+
newLines = []
foundStart = False
foundEnd = False
@@ -44,7 +44,7 @@
if pattern_head_start.match(line):
foundStart = True
newLines.append(line)
-
+
newLines.append("<!-- ========== weinre additions: starting ========== -->\n")
newLines.extend([
'<meta http-equiv="X-UA-Compatible" content="chrome=1">\n'
@@ -56,27 +56,27 @@
'<script type="text/javascript">require("modjewel").warnOnRecursiveRequire(true)</script>\n',
'<script type="text/javascript" src="../scooj.transportd.js"></script>\n',
])
-
+
for module in getModules(moduleDir):
newLines.append('<script type="text/javascript" src="../%s"></script>\n' % module)
-
+
newLines.append("<!-- ========== weinre additions: done ========== -->\n")
-
+
elif pattern_head_end.match(line):
foundEnd = True
newLines.append("<!-- ========== weinre additions: starting ========== -->\n")
newLines.append('<link rel="stylesheet" type="text/css" href="weinre/client.css">\n')
newLines.append('<script type="text/javascript" src="../interfaces/all-json-idls-min.js"></script>\n')
- newLines.append('<script type="text/javascript">require("weinre/client/Client").getClass().main()</script>\n')
+ newLines.append('<script type="text/javascript">require("weinre/client/Client").main()</script>\n')
newLines.append("<!-- ========== weinre additions: done ========== -->\n")
newLines.append(line)
-
+
else:
newLines.append(line)
-
+
if not foundStart: error("didn't find the location to start writing")
if not foundEnd: error("didn't find the location to finish writing")
-
+
with open(oFileName, "w") as oFile: oFile.writelines(newLines)
log("created %s" % oFileName)
@@ -84,15 +84,15 @@
#--------------------------------------------------------------------
def getModules(moduleDir):
modules = []
-
+
for module in os.listdir(os.path.join(moduleDir, "common")):
modules.append("weinre/common/%s" % module)
-
+
for module in os.listdir(os.path.join(moduleDir, "client")):
modules.append("weinre/client/%s" % module)
return modules
-
+
#--------------------------------------------------------------------
def log(message):
message = "%s: %s" % (PROGRAM_NAME, message)
diff --git a/weinre.build/scripts/build-css-properties.py b/weinre.build/scripts/build-css-properties.py
index 596e461..c6fde75 100644
--- a/weinre.build/scripts/build-css-properties.py
+++ b/weinre.build/scripts/build-css-properties.py
@@ -3,7 +3,7 @@
# ---
# 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
# ---
@@ -14,34 +14,34 @@
import optparse
#--------------------------------------------------------------------
-# reads:
+# reads:
# http://svn.webkit.org/repository/webkit/trunk/WebCore/css/CSSPropertyNames.in
# writes:
-# json array
+# json array
#--------------------------------------------------------------------
def main():
if len(sys.argv) < 3:
error("expecting parameters inputFile outputFile")
-
+
iFileName = sys.argv[1]
oFileName = sys.argv[2]
-
+
if not os.path.exists(iFileName): error("input file not found: '" + iFileName + "'")
-
+
with open(iFileName, "r") as iFile:
lines = iFile.readlines()
properties = [line.strip() for line in lines if not line.strip().startswith("#")]
properties = [property for property in properties if property != ""]
properties.sort()
-
+
jsonString = json.dumps(properties, indent=4)
- jsString = 'require("weinre/common/Weinre").getClass().addCSSProperties(%s)' % jsonString
+ jsString = 'require("weinre/common/Weinre").addCSSProperties(%s)' % jsonString
oFile = open(oFileName, "w")
oFile.write(jsString)
oFile.close()
-
+
log("generated css properties in: " + oFileName)
#--------------------------------------------------------------------
diff --git a/weinre.build/scripts/collect-all-json-idl.py b/weinre.build/scripts/collect-all-json-idl.py
index c9c6281..2d1d912 100644
--- a/weinre.build/scripts/collect-all-json-idl.py
+++ b/weinre.build/scripts/collect-all-json-idl.py
@@ -3,7 +3,7 @@
# ---
# 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
# ---
@@ -17,17 +17,17 @@
def main():
if len(sys.argv) < 3:
error("expecting parameters outputFile inputDir")
-
+
min = False
if sys.argv[1] == "-min":
min = True
oFileName = sys.argv[2]
iDirName = sys.argv[3]
-
+
else:
oFileName = sys.argv[1]
iDirName = sys.argv[2]
-
+
entries = os.listdir(iDirName)
if 0 == len(entries): error("no files found in '" + iDirName + "'")
@@ -38,26 +38,26 @@
for entry in entries:
iFileName = os.path.join(iDirName, entry)
if not os.path.exists(iFileName): error("File not found: '" + iFileName + "'")
-
+
iFile = open(iFileName, "r")
contents = iFile.read()
iFile.close()
-
+
result.append(json.loads(contents))
-
+
if min:
result = minimize(result)
jsonString = json.dumps(result)
-
+
else:
jsonString = json.dumps(result, indent=4)
-
- jsString = "require('weinre/common/Weinre').getClass().addIDLs(%s)" % jsonString
+
+ jsString = "require('weinre/common/Weinre').addIDLs(%s)" % jsonString
oFile = open(oFileName, "w")
oFile.write(jsString)
oFile.close()
-
+
log("generated collected json idls in: " + oFileName)
#--------------------------------------------------------------------
@@ -66,7 +66,7 @@
for interface in module["interfaces"]:
if "extendedAttributes" in interface:
del interface["extendedAttributes"]
-
+
if "methods" in interface:
for method in interface["methods"]:
if "returns" in method:
@@ -75,12 +75,12 @@
del method["callbackParameters"]
if "extendedAttributes" in method:
del method["extendedAttributes"]
-
+
if "parameters" in method:
for parameter in method["parameters"]:
if "type" in parameter:
del parameter["type"]
-
+
return idl
#--------------------------------------------------------------------
diff --git a/weinre.build/vendor.properties b/weinre.build/vendor.properties
index 8cad8e0..bdb8f72 100644
--- a/weinre.build/vendor.properties
+++ b/weinre.build/vendor.properties
@@ -1,7 +1,7 @@
# ---
# 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) 2011 IBM Corporation
# ---
@@ -28,7 +28,7 @@
CLI_BASENAME: commons-cli-${CLI_VERSION}/commons-cli-${CLI_VERSION}
#-----------------------------------------------------------
-# location of JSON4J
+# location of JSON4J
#-----------------------------------------------------------
JSON4J_VERSION: 1.1.2-incubating
@@ -51,7 +51,7 @@
JETTY_BIN_URL: ${JETTY_URL_PREFIX}/aggregate/jetty-all-server/${JETTY_VERSION}/${JETTY_BIN_JAR_NAME}
#-----------------------------------------------------------
-# location of servlet API
+# location of servlet API
#-----------------------------------------------------------
JAVAX_SERVLET_VERSION: 2.5-20110124
@@ -77,6 +77,12 @@
SCOOJ_URL_PREFIX: https://github.com/pmuellr/scooj/raw/${SCOOJ_VERSION}
#-----------------------------------------------------------
+# location of CoffeeScript
+#-----------------------------------------------------------
+
+COFFEESCRIPT_VERSION: 1.1.2
+
+#-----------------------------------------------------------
# location of json2
#-----------------------------------------------------------
diff --git a/weinre.web/client/ExtensionRegistryStub.js b/weinre.web/client/ExtensionRegistryStub.js
index 8e30a7e..396f3f1 100644
--- a/weinre.web/client/ExtensionRegistryStub.js
+++ b/weinre.web/client/ExtensionRegistryStub.js
@@ -1,11 +1,11 @@
/*
* 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) 2011 IBM Corporation
*/
(function() {
- var ExtensionRegistryImpl = require("weinre/client/ExtensionRegistryImpl").getClass()
+ var ExtensionRegistryImpl = require("weinre/client/ExtensionRegistryImpl")
window.InspectorExtensionRegistry = new ExtensionRegistryImpl()
})()
diff --git a/weinre.web/client/InspectorBackendStub.js b/weinre.web/client/InspectorBackendStub.js
index 091c2a4..f8d41f2 100644
--- a/weinre.web/client/InspectorBackendStub.js
+++ b/weinre.web/client/InspectorBackendStub.js
@@ -1,11 +1,11 @@
/*
* 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
*/
(function() {
- var InspectorBackendImpl = require("weinre/client/InspectorBackendImpl").getClass()
+ var InspectorBackendImpl = require("weinre/client/InspectorBackendImpl")
window.InspectorBackend = new InspectorBackendImpl()
})()
diff --git a/weinre.web/client/InspectorFrontendHostStub.js b/weinre.web/client/InspectorFrontendHostStub.js
index d964918..65f648b 100644
--- a/weinre.web/client/InspectorFrontendHostStub.js
+++ b/weinre.web/client/InspectorFrontendHostStub.js
@@ -1,11 +1,11 @@
/*
* 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
*/
(function() {
- var InspectorFrontEndHostImpl = require("weinre/client/InspectorFrontendHostImpl").getClass()
- window.InspectorFrontendHost = new InspectorFrontEndHostImpl()
+ var InspectorFrontEndHostImpl = require("weinre/client/InspectorFrontendHostImpl")
+ window.InspectorFrontendHost = new InspectorFrontEndHostImpl()
})()
diff --git a/weinre.web/demo/weinre-demo-pieces.html b/weinre.web/demo/weinre-demo-pieces.html
index 51b261f..bb38a17 100644
--- a/weinre.web/demo/weinre-demo-pieces.html
+++ b/weinre.web/demo/weinre-demo-pieces.html
@@ -1,7 +1,7 @@
<!--
* 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
-->
@@ -12,7 +12,6 @@
<script src="/modjewel-require.js"></script>
<script type="text/javascript">require("modjewel").warnOnRecursiveRequire(true)</script>
-<script src="/scooj.transportd.js"></script>
<script src="/weinre/common/Ex.transportd.js"></script>
<script src="/weinre/common/StackTrace.transportd.js"></script>
<script src="/weinre/common/Weinre.transportd.js"></script>
@@ -24,6 +23,7 @@
<script src="/weinre/common/EventListeners.transportd.js"></script>
<script src="/weinre/common/Native.transportd.js"></script>
<script src="/weinre/common/IDGenerator.transportd.js"></script>
+<script src="/weinre/common/MethodNamer.transportd.js"></script>
<script src="/weinre/target/Console.transportd.js"></script>
<script src="/add-css-properties.js"></script>
<script src="/weinre/target/CheckForProblems.transportd.js"></script>
@@ -47,8 +47,8 @@
<script src="/interfaces/all-json-idls-min.js"></script>
<script type="text/javascript">
- require("weinre/common/Weinre").getClass().showNotImplemented()
- require('weinre/target/Target').getClass().main()
+ require("weinre/common/Weinre").showNotImplemented()
+ require('weinre/target/Target').main()
</script>
<link rel="stylesheet" href="weinre-demo.css">
diff --git a/weinre.web/index.html b/weinre.web/index.html
index ed4f2a8..05f3e53 100644
--- a/weinre.web/index.html
+++ b/weinre.web/index.html
@@ -3,7 +3,7 @@
<!--
* 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
-->
@@ -20,9 +20,9 @@
h1, h2 {
padding: 0.25em 0.50em;
background-color: #DDD;
- border-radius: 0.5em;
- -moz-border-radius: 0.5em;
- -webkit-border-radius: 0.5em;
+ border-radius: 0.5em;
+ -moz-border-radius: 0.5em;
+ -webkit-border-radius: 0.5em;
}
td {
vertical-align: top;
@@ -64,21 +64,21 @@
<h2>Target Bookmarklet</h2>
-<p>You can use this bookmarklet to inject the weinre target code into any
+<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:
+<p>link you can drag to your bookmarks:
<div class="indent">
-<span id="url-target-bookmarklet">???</span>
+<span id="url-target-bookmarklet">???</span>
</div>
-<p>bookmarklet url in a pre:
+<p>bookmarklet url in a pre:
<pre id="target-bookmarklet-src-pre"></pre>
-<p>bookmarklet url in a textarea:
+<p>bookmarklet url in a textarea:
<div class="indent">
-<textarea id="target-bookmarklet-src-text-area"></textarea>
+<textarea id="target-bookmarklet-src-text-area"></textarea>
</div>
<h2>Development</h2>
@@ -100,7 +100,7 @@
<tr><td>modjewel: <td> <span id="version-modjewel">???</span>
</table>
-<img src="images/weinre-icon-128x128.png">
+<img src="images/weinre-icon-128x128.png">
<script src="index.js"></script>
diff --git a/weinre.web/modules/weinre/client/Client.scoop b/weinre.web/modules-scoop/weinre/client/Client.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/Client.scoop
rename to weinre.web/modules-scoop/weinre/client/Client.scoop
diff --git a/weinre.web/modules/weinre/client/ConnectorList.scoop b/weinre.web/modules-scoop/weinre/client/ConnectorList.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/ConnectorList.scoop
rename to weinre.web/modules-scoop/weinre/client/ConnectorList.scoop
diff --git a/weinre.web/modules/weinre/client/DOMTemplates.scoop b/weinre.web/modules-scoop/weinre/client/DOMTemplates.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/DOMTemplates.scoop
rename to weinre.web/modules-scoop/weinre/client/DOMTemplates.scoop
diff --git a/weinre.web/modules/weinre/client/ExtensionRegistryImpl.scoop b/weinre.web/modules-scoop/weinre/client/ExtensionRegistryImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/ExtensionRegistryImpl.scoop
rename to weinre.web/modules-scoop/weinre/client/ExtensionRegistryImpl.scoop
diff --git a/weinre.web/modules/weinre/client/InspectorBackendImpl.scoop b/weinre.web/modules-scoop/weinre/client/InspectorBackendImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/InspectorBackendImpl.scoop
rename to weinre.web/modules-scoop/weinre/client/InspectorBackendImpl.scoop
diff --git a/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.scoop b/weinre.web/modules-scoop/weinre/client/InspectorFrontendHostImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/InspectorFrontendHostImpl.scoop
rename to weinre.web/modules-scoop/weinre/client/InspectorFrontendHostImpl.scoop
diff --git a/weinre.web/modules/weinre/client/RemotePanel.scoop b/weinre.web/modules-scoop/weinre/client/RemotePanel.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/RemotePanel.scoop
rename to weinre.web/modules-scoop/weinre/client/RemotePanel.scoop
diff --git a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop b/weinre.web/modules-scoop/weinre/client/WeinreClientEventsImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
rename to weinre.web/modules-scoop/weinre/client/WeinreClientEventsImpl.scoop
diff --git a/weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.scoop b/weinre.web/modules-scoop/weinre/client/WeinreExtraTargetEventsImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.scoop
rename to weinre.web/modules-scoop/weinre/client/WeinreExtraTargetEventsImpl.scoop
diff --git a/weinre.web/modules/weinre/common/Binding.scoop b/weinre.web/modules-scoop/weinre/common/Binding.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/Binding.scoop
rename to weinre.web/modules-scoop/weinre/common/Binding.scoop
diff --git a/weinre.web/modules/weinre/common/Callback.scoop b/weinre.web/modules-scoop/weinre/common/Callback.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/Callback.scoop
rename to weinre.web/modules-scoop/weinre/common/Callback.scoop
diff --git a/weinre.web/modules/weinre/common/EventListeners.scoop b/weinre.web/modules-scoop/weinre/common/EventListeners.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/EventListeners.scoop
rename to weinre.web/modules-scoop/weinre/common/EventListeners.scoop
diff --git a/weinre.web/modules/weinre/common/Ex.scoop b/weinre.web/modules-scoop/weinre/common/Ex.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/Ex.scoop
rename to weinre.web/modules-scoop/weinre/common/Ex.scoop
diff --git a/weinre.web/modules/weinre/common/IDGenerator.scoop b/weinre.web/modules-scoop/weinre/common/IDGenerator.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/IDGenerator.scoop
rename to weinre.web/modules-scoop/weinre/common/IDGenerator.scoop
diff --git a/weinre.web/modules/weinre/common/IDLTools.scoop b/weinre.web/modules-scoop/weinre/common/IDLTools.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/IDLTools.scoop
rename to weinre.web/modules-scoop/weinre/common/IDLTools.scoop
diff --git a/weinre.web/modules/weinre/common/MessageDispatcher.scoop b/weinre.web/modules-scoop/weinre/common/MessageDispatcher.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/MessageDispatcher.scoop
rename to weinre.web/modules-scoop/weinre/common/MessageDispatcher.scoop
diff --git a/weinre.web/modules/weinre/common/Native.scoop b/weinre.web/modules-scoop/weinre/common/Native.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/Native.scoop
rename to weinre.web/modules-scoop/weinre/common/Native.scoop
diff --git a/weinre.web/modules/weinre/common/StackTrace.scoop b/weinre.web/modules-scoop/weinre/common/StackTrace.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/StackTrace.scoop
rename to weinre.web/modules-scoop/weinre/common/StackTrace.scoop
diff --git a/weinre.web/modules/weinre/common/WebSocketXhr.scoop b/weinre.web/modules-scoop/weinre/common/WebSocketXhr.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/WebSocketXhr.scoop
rename to weinre.web/modules-scoop/weinre/common/WebSocketXhr.scoop
diff --git a/weinre.web/modules/weinre/common/Weinre.scoop b/weinre.web/modules-scoop/weinre/common/Weinre.scoop
similarity index 100%
rename from weinre.web/modules/weinre/common/Weinre.scoop
rename to weinre.web/modules-scoop/weinre/common/Weinre.scoop
diff --git a/weinre.web/modules/weinre/target/CSSStore.scoop b/weinre.web/modules-scoop/weinre/target/CSSStore.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/CSSStore.scoop
rename to weinre.web/modules-scoop/weinre/target/CSSStore.scoop
diff --git a/weinre.web/modules/weinre/target/CheckForProblems.scoop b/weinre.web/modules-scoop/weinre/target/CheckForProblems.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/CheckForProblems.scoop
rename to weinre.web/modules-scoop/weinre/target/CheckForProblems.scoop
diff --git a/weinre.web/modules/weinre/target/Console.scoop b/weinre.web/modules-scoop/weinre/target/Console.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/Console.scoop
rename to weinre.web/modules-scoop/weinre/target/Console.scoop
diff --git a/weinre.web/modules/weinre/target/ElementHighlighter.scoop b/weinre.web/modules-scoop/weinre/target/ElementHighlighter.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/ElementHighlighter.scoop
rename to weinre.web/modules-scoop/weinre/target/ElementHighlighter.scoop
diff --git a/weinre.web/modules/weinre/target/InjectedScriptHostImpl.scoop b/weinre.web/modules-scoop/weinre/target/InjectedScriptHostImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/InjectedScriptHostImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/InjectedScriptHostImpl.scoop
diff --git a/weinre.web/modules/weinre/target/NodeStore.scoop b/weinre.web/modules-scoop/weinre/target/NodeStore.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/NodeStore.scoop
rename to weinre.web/modules-scoop/weinre/target/NodeStore.scoop
diff --git a/weinre.web/modules/weinre/target/SqlStepper.scoop b/weinre.web/modules-scoop/weinre/target/SqlStepper.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/SqlStepper.scoop
rename to weinre.web/modules-scoop/weinre/target/SqlStepper.scoop
diff --git a/weinre.web/modules/weinre/target/Target.scoop b/weinre.web/modules-scoop/weinre/target/Target.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/Target.scoop
rename to weinre.web/modules-scoop/weinre/target/Target.scoop
diff --git a/weinre.web/modules/weinre/target/Timeline.scoop b/weinre.web/modules-scoop/weinre/target/Timeline.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/Timeline.scoop
rename to weinre.web/modules-scoop/weinre/target/Timeline.scoop
diff --git a/weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.scoop b/weinre.web/modules-scoop/weinre/target/WeinreExtraClientCommandsImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WeinreExtraClientCommandsImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop b/weinre.web/modules-scoop/weinre/target/WeinreTargetEventsImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WeinreTargetEventsImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WiCSSImpl.scoop b/weinre.web/modules-scoop/weinre/target/WiCSSImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WiCSSImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WiCSSImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WiConsoleImpl.scoop b/weinre.web/modules-scoop/weinre/target/WiConsoleImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WiConsoleImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WiConsoleImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WiDOMImpl.scoop b/weinre.web/modules-scoop/weinre/target/WiDOMImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WiDOMImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WiDOMImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WiDOMStorageImpl.scoop b/weinre.web/modules-scoop/weinre/target/WiDOMStorageImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WiDOMStorageImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WiDOMStorageImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WiDatabaseImpl.scoop b/weinre.web/modules-scoop/weinre/target/WiDatabaseImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WiDatabaseImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WiDatabaseImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WiInspectorImpl.scoop b/weinre.web/modules-scoop/weinre/target/WiInspectorImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WiInspectorImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WiInspectorImpl.scoop
diff --git a/weinre.web/modules/weinre/target/WiRuntimeImpl.scoop b/weinre.web/modules-scoop/weinre/target/WiRuntimeImpl.scoop
similarity index 100%
rename from weinre.web/modules/weinre/target/WiRuntimeImpl.scoop
rename to weinre.web/modules-scoop/weinre/target/WiRuntimeImpl.scoop
diff --git a/weinre.web/modules/weinre/client/Client.coffee b/weinre.web/modules/weinre/client/Client.coffee
new file mode 100644
index 0000000..eecd963
--- /dev/null
+++ b/weinre.web/modules/weinre/client/Client.coffee
@@ -0,0 +1,140 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Native = require('../common/Native')
+IDLTools = require('../common/IDLTools')
+Callback = require('../common/Callback')
+Weinre = require('../common/Weinre')
+MessageDispatcher = require('../common/MessageDispatcher')
+Binding = require('../common/Binding')
+IDGenerator = require('../common/IDGenerator')
+
+InspectorBackendImpl = require('./InspectorBackendImpl')
+InspectorFrontendHostImpl = require('./InspectorFrontendHostImpl')
+WeinreClientEventsImpl = require('./WeinreClientEventsImpl')
+WeinreExtraTargetEventsImpl = require('./WeinreExtraTargetEventsImpl')
+RemotePanel = require('./RemotePanel')
+
+AutoConnect = true
+
+Weinre.showNotImplemented()
+
+#-------------------------------------------------------------------------------
+module.exports = class Client
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ initialize: ->
+ window.addEventListener 'load', Binding(this, 'onLoaded'), false
+
+ messageDispatcher = new MessageDispatcher('../ws/client', @_getId())
+ Weinre.messageDispatcher = messageDispatcher
+
+ InspectorBackendImpl.setupProxies()
+
+ Weinre.WeinreClientCommands = messageDispatcher.createProxy('WeinreClientCommands')
+ Weinre.WeinreExtraClientCommands = messageDispatcher.createProxy('WeinreExtraClientCommands')
+
+ messageDispatcher.registerInterface(
+ 'WeinreExtraTargetEvents', new WeinreExtraTargetEventsImpl(), false
+ )
+
+ messageDispatcher.registerInterface(
+ 'WebInspector', WebInspector, false
+ )
+
+ WebInspector.mainResource = {}
+ WebInspector.mainResource.url = location.href
+
+ #---------------------------------------------------------------------------
+ _getId: ->
+ hash = location.href.split('#')[1]
+ return hash if hash
+ 'anonymous'
+
+ #---------------------------------------------------------------------------
+ uiAvailable: ->
+ WebInspector.panels and WebInspector.panels.remote
+
+ #---------------------------------------------------------------------------
+ autoConnect: (value) ->
+ AutoConnect = not not value if arguments.length >= 1
+ AutoConnect
+
+ #---------------------------------------------------------------------------
+ _installRemotePanel: ->
+ WebInspector.panels.remote = new RemotePanel()
+
+ panel = WebInspector.panels.remote
+ toolbar = document.getElementById('toolbar')
+
+ WebInspector.addPanelToolbarIcon toolbar, panel, toolbar.childNodes[1]
+ WebInspector.panelOrder.unshift WebInspector.panelOrder.pop()
+ WebInspector.currentPanel = panel
+
+ toolButtonsToHide = [ 'scripts' ]
+ for toolButtonToHide in toolButtonsToHide
+ continue unless WebInspector.panels[toolButtonToHide]
+ continue unless WebInspector.panels[toolButtonToHide].toolbarItem
+
+ WebInspector.panels[toolButtonToHide].toolbarItem.style.display = 'none'
+
+ button = document.getElementById('dock-status-bar-item')
+ button.style.display = 'none' if button
+
+ #---------------------------------------------------------------------------
+ onLoaded: ->
+ Weinre.WeinreClientCommands.registerClient Binding(this, @cb_registerClient)
+
+ @_installRemotePanel()
+
+ messageDispatcher = Weinre.messageDispatcher
+ messageDispatcher.registerInterface 'WeinreClientEvents', new WeinreClientEventsImpl(this), false
+ messageDispatcher.registerInterface 'InspectorFrontendHost', InspectorFrontendHost, false
+
+ #---------------------------------------------------------------------------
+ cb_registerClient: (clientDescription) ->
+ Weinre.clientDescription = clientDescription
+
+ if @uiAvailable()
+ WebInspector.panels.remote.setCurrentClient clientDescription.channel
+ WebInspector.panels.remote.afterInitialConnection()
+
+ Weinre.messageDispatcher.getWebSocket().addEventListener 'close', Binding(this, @cb_webSocketClosed)
+
+ #---------------------------------------------------------------------------
+ cb_webSocketClosed: ->
+ Native.setTimeout (->
+ WebInspector.panels.remote.connectionClosed()
+ WebInspector.currentPanel = WebInspector.panels.remote
+ ), 1000
+
+ #---------------------------------------------------------------------------
+ @main: ->
+ Weinre.client = new Client()
+ Weinre.client.initialize()
+
+ window.installWebInspectorAPIsource = installWebInspectorAPIsource
+
+#-------------------------------------------------------------------------------
+installWebInspectorAPIsource = () ->
+ return if 'webInspector' of window
+
+ extensionAPI = window.parent.InspectorFrontendHost.getExtensionAPI()
+ extensionAPI = extensionAPI.replace('location.hostname + location.port', "location.hostname + ':' + location.port")
+
+ id = IDGenerator.next()
+
+ console.log "installing webInspector with injectedScriptId: #{id}"
+
+ extensionAPI += "(null, null, #{id})"
+ extensionAPI
+
+#-------------------------------------------------------------------------------
+require('../common/MethodNamer').setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/client/ConnectorList.coffee b/weinre.web/modules/weinre/client/ConnectorList.coffee
new file mode 100644
index 0000000..065787a
--- /dev/null
+++ b/weinre.web/modules/weinre/client/ConnectorList.coffee
@@ -0,0 +1,138 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+dt = require('./DOMTemplates')
+
+#-------------------------------------------------------------------------------
+module.exports = class ConnectorList
+
+ constructor: (title) ->
+ @connectors = {}
+
+ @noneItem = dt.LI("none")
+ @ulConnectors = dt.UL(@noneItem)
+ @div = dt.DIV(dt.H1(title), @ulConnectors)
+
+ @noneItem.addStyleClass "weinre-connector-item"
+
+ #---------------------------------------------------------------------------
+ getElement: ->
+ @div
+
+ #---------------------------------------------------------------------------
+ add: (connector) ->
+ return if @connectors[connector.channel]
+
+ @connectors[connector.channel] = connector
+
+ li = @getListItem(connector)
+ li.addStyleClass "weinre-fadeable"
+
+ @noneItem.style.display = "none"
+
+ insertionPoint = @getConnectorInsertionPoint(connector)
+ unless insertionPoint
+ @ulConnectors.appendChild li
+ else
+ @ulConnectors.insertBefore li, insertionPoint
+
+ #---------------------------------------------------------------------------
+ get: (channel) ->
+ @connectors[channel]
+
+ #---------------------------------------------------------------------------
+ getNewestConnectorChannel: (ignoring) ->
+ newest = 0
+ for connectorChannel of @connectors
+ continue if connectorChannel == ignoring
+ newest = connectorChannel if connectorChannel > newest
+
+ return null if newest == 0
+ newest
+
+ #---------------------------------------------------------------------------
+ getConnectorInsertionPoint: (connector) ->
+ i = 0
+
+ for childNode in @ulConnectors.childNodes
+ continue if null == childNode.connectorChannel
+ return childNode if childNode.connectorChannel < connector.channel
+
+ null
+
+ #---------------------------------------------------------------------------
+ remove: (channel, fast) ->
+ self = this
+
+ element = @getConnectorElement(channel)
+ return unless element
+
+ connector = @connectors[channel]
+ connector.closed = true if connector
+ delete @connectors[channel]
+
+ if fast
+ @_remove element
+ else
+ @setState element, "closed"
+ element.addStyleClass "weinre-fade"
+ window.setTimeout (->
+ self._remove element
+ ), 5000
+
+ #---------------------------------------------------------------------------
+ _remove: (element) ->
+ @ulConnectors.removeChild element
+ @noneItem.style.display = "list-item" if @getConnectors().length == 0
+
+ #---------------------------------------------------------------------------
+ removeAll: () ->
+ for connector in @getConnectors()
+ @remove connector.channel, true
+
+ #---------------------------------------------------------------------------
+ getConnectors: () ->
+ result = []
+
+ for channel of @connectors
+ continue unless @connectors.hasOwnProperty(channel)
+ result.push @connectors[channel]
+
+ result
+
+ #---------------------------------------------------------------------------
+ getConnectorElement: (channel) ->
+ connector = @connectors[channel]
+ return null unless connector
+ connector.element
+
+ #---------------------------------------------------------------------------
+ setCurrent: (channel) ->
+ for connector in @getConnectors()
+ connector.element.removeStyleClass "current"
+
+ element = @getConnectorElement(channel)
+ return if null == element
+ element.addStyleClass "current"
+
+ #---------------------------------------------------------------------------
+ setState: (channel, state) ->
+ if typeof channel == "string"
+ element = @getConnectorElement(channel)
+ else
+ element = channel
+
+ return unless element
+ element.removeStyleClass "error"
+ element.removeStyleClass "closed"
+ element.removeStyleClass "connected"
+ element.removeStyleClass "not-connected"
+ element.addStyleClass state
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/client/DOMTemplates.coffee b/weinre.web/modules/weinre/client/DOMTemplates.coffee
new file mode 100644
index 0000000..a3db299
--- /dev/null
+++ b/weinre.web/modules/weinre/client/DOMTemplates.coffee
@@ -0,0 +1,57 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('../common/Ex')
+
+#-------------------------------------------------------------------------------
+getElementFunction = (elementName) ->
+ ->
+ element = document.createElement(elementName)
+
+ args = [].slice.call(arguments)
+ for argument in args
+ if argument.nodeType
+ addToElement_Node element, argument
+ else if typeof argument == "string"
+ addToElement_String element, argument
+ else if typeof argument == "object"
+ addToElement_Object element, argument
+ else
+ throw new Ex(arguments, "invalid value passed to DOMTemplates.#{elementName}(): " + argument)
+
+ element
+
+#-------------------------------------------------------------------------------
+addToElement_String = (element, aString) ->
+ addToElement_Node element, document.createTextNode(aString)
+
+#-------------------------------------------------------------------------------
+addToElement_Node = (element, anElement) ->
+ element.appendChild anElement
+
+#-------------------------------------------------------------------------------
+addToElement_Object = (element, anObject) ->
+ for key of anObject
+ continue unless anObject.hasOwnProperty(key)
+
+ val = anObject[key]
+ if key.substr(0, 1) == "$"
+ actualKey = key.substr(1)
+ element[actualKey] = val
+ else
+ element.setAttribute key, val
+
+#-------------------------------------------------------------------------------
+elementNames = 'H1 H2 H3 H4 H5 H6 UL OL DL LI DT DD SPAN DIV A B I TT P HR BR PRE IMG CANVAS TABLE TR TD FORM INPUT BUTTON SELECT OPTGROUP OPTION TEXTAREA'
+elementNames = elementNames.split(' ')
+
+for elementName in elementNames
+ exports[elementName] = getElementFunction(elementName)
+ exports[elementName].name = "#{elementName}"
+ exports[elementName].displayName = "#{elementName}"
+ exports[elementName].signature = "DOMTemplates.#{elementName}"
diff --git a/weinre.web/modules/weinre/client/ExtensionRegistryImpl.coffee b/weinre.web/modules/weinre/client/ExtensionRegistryImpl.coffee
new file mode 100644
index 0000000..4303d2d
--- /dev/null
+++ b/weinre.web/modules/weinre/client/ExtensionRegistryImpl.coffee
@@ -0,0 +1,35 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('../common/Ex')
+Binding = require('../common/Binding')
+Weinre = require('../common/Weinre')
+
+extensions = []
+
+#-------------------------------------------------------------------------------
+module.exports = class ExtensionRegistryImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ getExtensionsAsync: ->
+ return if extensions.length
+ Weinre.WeinreClientCommands.getExtensions Binding(this, @_cb_getExtensions)
+
+ #---------------------------------------------------------------------------
+ _cb_getExtensions: (extensionsResult) ->
+ extensions = extensionsResult
+ @_installExtensions()
+
+ #---------------------------------------------------------------------------
+ _installExtensions: ->
+ WebInspector.addExtensions extensions
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/client/InspectorBackendImpl.coffee b/weinre.web/modules/weinre/client/InspectorBackendImpl.coffee
new file mode 100644
index 0000000..1dcf45e
--- /dev/null
+++ b/weinre.web/modules/weinre/client/InspectorBackendImpl.coffee
@@ -0,0 +1,70 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('../common/Ex')
+IDLTools = require('../common/IDLTools')
+MessageDispatcher = require('../common/MessageDispatcher')
+Weinre = require('../common/Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class InspectorBackendImpl
+
+ constructor: ->
+ @registeredDomainDispatchers = {}
+ MessageDispatcher.setInspectorBackend this
+
+ #---------------------------------------------------------------------------
+ @setupProxies: ->
+ intfNames = [
+ "ApplicationCache"
+ "BrowserDebugger"
+ "CSS"
+ "Console"
+ "DOM"
+ "DOMStorage"
+ "Database"
+ "Debugger"
+ "InjectedScript"
+ "Inspector"
+ "Network"
+ "Profiler"
+ "Runtime"
+ ]
+
+ for intfName in intfNames
+ proxy = Weinre.messageDispatcher.createProxy(intfName)
+
+ if window[intfName]
+ throw new Ex(arguments, "backend interface '#{intfName}' already created")
+
+ intf = IDLTools.getIDL(intfName)
+ unless intf
+ throw new Ex(arguments, "interface not registered: '#{intfName}'")
+
+ window[intfName] = {}
+ for method in intf.methods
+ proxyMethod = InspectorBackendImpl.getProxyMethod(proxy, method)
+ InspectorBackendImpl::[method.name] = proxyMethod
+ window[intfName][method.name] = proxyMethod
+
+ #---------------------------------------------------------------------------
+ @getProxyMethod: (proxy, method) ->
+ ->
+ proxy[method.name].apply proxy, arguments
+
+ #---------------------------------------------------------------------------
+ registerDomainDispatcher: (name, intf) ->
+ @registeredDomainDispatchers[name] = intf
+
+ #---------------------------------------------------------------------------
+ getRegisteredDomainDispatcher: (name) ->
+ return null unless @registeredDomainDispatchers.hasOwnProperty(name)
+ @registeredDomainDispatchers[name]
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.coffee b/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.coffee
new file mode 100644
index 0000000..0c71e63
--- /dev/null
+++ b/weinre.web/modules/weinre/client/InspectorFrontendHostImpl.coffee
@@ -0,0 +1,87 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+IDLTools = require('../common/IDLTools')
+
+_extensionAPI = null
+
+#-------------------------------------------------------------------------------
+module.exports = class InspectorFrontendHostImpl
+
+ constructor: ->
+ @_getPlatformAndPort()
+
+ #---------------------------------------------------------------------------
+ loaded: ->
+
+ #---------------------------------------------------------------------------
+ localizedStringsURL: ->
+ "nls/English.lproj/localizedStrings.js"
+
+ #---------------------------------------------------------------------------
+ hiddenPanels: ->
+ "audits,profiles,network"
+
+ #---------------------------------------------------------------------------
+ platform: ->
+ "weinre"
+
+ #---------------------------------------------------------------------------
+ port: ->
+ "weinre"
+
+ #---------------------------------------------------------------------------
+ sendMessageToBackend: (message) ->
+ object = JSON.parse(message)
+ object[1] = "<long script elided>" if object[0] == "setInjectedScriptSource"
+ Weinre.logInfo arguments.callee.name + "(#{JSON.stringify(object, null, 4)})"
+
+ #---------------------------------------------------------------------------
+ setExtensionAPI: (extensionAPI) ->
+ _extensionAPI = extensionAPI
+
+ #---------------------------------------------------------------------------
+ getExtensionAPI: ->
+ _extensionAPI
+
+ #---------------------------------------------------------------------------
+ inspectedURLChanged: ->
+
+ #---------------------------------------------------------------------------
+ _getPlatformAndPort: ->
+ @_platform = "weinre"
+ @_platformFlavor = "weinre"
+ @_port = "weinre"
+ return if true
+ uas = navigator.userAgent
+ if uas.match(/mac os x/i)
+ @_platform = "mac"
+ else if uas.match(/macintosh/i)
+ @_platform = "mac"
+ else if uas.match(/linux/i)
+ @_platform = "linux"
+ else @_platform = "windows" if uas.match(/windows/i)
+ url = window.location.href
+ splits = url.split("#", 2)
+ if splits.length > 1
+ properties = splits[1]
+ properties = properties.split("&")
+ for property in properties
+ pieces = property.split("=")
+ if pieces.length > 1
+ key = pieces[0]
+ val = pieces[1]
+ if key == "platform"
+ @_platform = val
+ else if key == "platformFlavor"
+ @_platformFlavor = val
+ else @_port = val if key == "port"
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/client/RemotePanel.coffee b/weinre.web/modules/weinre/client/RemotePanel.coffee
new file mode 100644
index 0000000..a6c6110
--- /dev/null
+++ b/weinre.web/modules/weinre/client/RemotePanel.coffee
@@ -0,0 +1,211 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Binding = require('../common/Binding')
+Weinre = require('../common/Weinre')
+
+ConnectorList = require('./ConnectorList')
+DT = require('./DOMTemplates')
+
+# fix WebInspector.Panel's prototype so our super call works
+WebInspector.Panel.prototype.constructor = WebInspector.Panel
+
+#-------------------------------------------------------------------------------
+module.exports = class RemotePanel extends WebInspector.Panel
+
+ RemotePanel::__defineGetter__("toolbarItemClass", -> "remote")
+ RemotePanel::__defineGetter__("toolbarItemLabel", -> "Remote")
+ RemotePanel::__defineGetter__("statusBarItems", -> [])
+ RemotePanel::__defineGetter__("defaultFocusedElement", -> @contentElement)
+
+ constructor: ->
+ super "remote"
+ @initialize()
+
+ #---------------------------------------------------------------------------
+ initialize: () ->
+ div = DT.DIV()
+ div.style.position = "absolute"
+ div.style.top = "1em"
+ div.style.right = "1em"
+ div.style.left = "1em"
+ div.style.bottom = "1em"
+ div.style.overflow = "auto"
+ icon = DT.IMG(src: "../images/weinre-icon-128x128.png")
+ icon.style.float = "right"
+ div.appendChild icon
+ @targetList = new TargetList()
+ @clientList = new ClientList()
+ div.appendChild @targetList.getElement()
+ div.appendChild @clientList.getElement()
+ @serverProperties = DT.DIV($className: "weinreServerProperties")
+ div.appendChild DT.H1("Server Properties")
+ div.appendChild @serverProperties
+ @element.appendChild div
+ @reset()
+
+ #---------------------------------------------------------------------------
+ addClient: (client) ->
+ @clientList.add client
+
+
+ addTarget: (target) ->
+ @targetList.add target
+
+
+ getTarget: (channel) ->
+ @targetList.get channel
+
+
+ removeClient: (channel) ->
+ @clientList.remove channel
+
+
+ removeTarget: (channel) ->
+ @targetList.remove channel
+
+
+ setCurrentClient: (channel) ->
+ @clientList.setCurrent channel
+
+
+ setCurrentTarget: (channel) ->
+ @targetList.setCurrent channel
+
+
+ setClientState: (channel, state) ->
+ @clientList.setState channel, state
+
+
+ setTargetState: (channel, state) ->
+ @targetList.setState channel, state
+
+ #---------------------------------------------------------------------------
+ getNewestTargetChannel: (ignoring) ->
+ @targetList.getNewestConnectorChannel ignoring
+
+ #---------------------------------------------------------------------------
+ afterInitialConnection: ->
+ @clientList.afterInitialConnection()
+
+ #---------------------------------------------------------------------------
+ reset: ->
+ @clientList.removeAll()
+ @targetList.removeAll()
+ Weinre.WeinreClientCommands.getTargets Binding(this, "cb_getTargets")
+ Weinre.WeinreClientCommands.getClients Binding(this, "cb_getClients")
+
+ #---------------------------------------------------------------------------
+ connectionClosed: ->
+ @clientList.removeAll()
+ @targetList.removeAll()
+
+ #---------------------------------------------------------------------------
+ cb_getTargets: (targets) ->
+ for target in targets
+ @addTarget target
+
+ return unless Weinre.client.autoConnect()
+ newestTargetChannel = @getNewestTargetChannel()
+ return unless newestTargetChannel
+ return unless Weinre.messageDispatcher
+ Weinre.WeinreClientCommands.connectTarget Weinre.messageDispatcher.channel, newestTargetChannel
+
+ #---------------------------------------------------------------------------
+ cb_getClients: (clients) ->
+ for client in clients
+ @addClient client
+
+ #---------------------------------------------------------------------------
+ show: ->
+ super()
+
+ #---------------------------------------------------------------------------
+ hide: () ->
+ super()
+
+ #---------------------------------------------------------------------------
+ setServerProperties: (properties) ->
+ table = "<table>"
+ keys = []
+ for key of properties
+ keys.push key
+ keys = keys.sort()
+ for key in keys
+ val = properties[key]
+ if typeof val == "string"
+ val = val.escapeHTML()
+ else
+ finalVal = ""
+ for aVal in val
+ finalVal += "<li>" + aVal.escapeHTML()
+
+ val = "<ul>#{finalVal}</ul>"
+ table += "<tr class='weinre-normal-text-size'><td valign='top'>#{key.escapeHTML()}: <td>" + val
+
+ table += "</table>"
+ @serverProperties.innerHTML = table
+
+#-------------------------------------------------------------------------------
+class TargetList extends ConnectorList
+
+ constructor: ->
+ super "Targets"
+
+ #---------------------------------------------------------------------------
+ getListItem: (target) ->
+ self = this
+ text = target.hostName + " [channel: #{target.channel} id: #{target.id}]" + " - " + target.url
+ item = DT.LI($connectorChannel: target.channel, text)
+ item.addStyleClass "weinre-connector-item"
+ item.addStyleClass "target"
+ item.addEventListener "click", ((e) ->
+ self.connectToTarget target.channel, e
+ ), false
+ target.element = item
+ item
+
+ #---------------------------------------------------------------------------
+ connectToTarget: (targetChannel, event) ->
+ if event
+ event.preventDefault()
+ event.stopPropagation()
+ target = @connectors[targetChannel]
+ return false unless target
+ return false if target.closed
+ Weinre.WeinreClientCommands.connectTarget Weinre.messageDispatcher.channel, targetChannel
+ false
+
+#-------------------------------------------------------------------------------
+class ClientList extends ConnectorList
+
+ constructor: ->
+ super "Clients"
+ @noneItem.innerHTML = "Waiting for connection..."
+
+ #---------------------------------------------------------------------------
+ afterInitialConnection: () ->
+ @noneItem.innerHTML = "Connection lost, reload this page to reconnect."
+ @noneItem.addStyleClass "error"
+
+ #---------------------------------------------------------------------------
+ getListItem: (client) ->
+ text = client.hostName + " [channel: #{client.channel} id: #{client.id}]"
+ item = DT.LI($connectorChannel: client.channel, text)
+ item.addStyleClass "weinre-connector-item"
+ item.addStyleClass "client"
+
+ if Weinre.messageDispatcher
+ if client.channel == Weinre.messageDispatcher.channel
+ item.addStyleClass "current"
+
+ client.element = item
+ item
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.coffee b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.coffee
new file mode 100644
index 0000000..a3e4038
--- /dev/null
+++ b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.coffee
@@ -0,0 +1,91 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Callback = require('../common/Callback')
+Weinre = require('../common/Weinre')
+
+WeinreExtraTargetEventsImpl = require('./WeinreExtraTargetEventsImpl')
+
+titleNotConnected = "weinre: target not connected"
+titleConnectedPrefix = "weinre: "
+
+document.title = titleNotConnected
+
+#-------------------------------------------------------------------------------
+module.exports = class WeinreClientEventsImpl
+
+ constructor: (client) ->
+ @client = client
+
+ #---------------------------------------------------------------------------
+ clientRegistered: (clientDescription) ->
+ WebInspector.panels.remote.addClient clientDescription if @client.uiAvailable()
+
+ #---------------------------------------------------------------------------
+ targetRegistered: (targetDescription) ->
+ WebInspector.panels.remote.addTarget targetDescription if @client.uiAvailable()
+ return unless Weinre.client.autoConnect()
+ return unless Weinre.messageDispatcher
+
+ Weinre.WeinreClientCommands.connectTarget Weinre.messageDispatcher.channel, targetDescription.channel
+
+ #---------------------------------------------------------------------------
+ clientUnregistered: (clientChannel) ->
+ WebInspector.panels.remote.removeClient clientChannel if @client.uiAvailable()
+
+ #---------------------------------------------------------------------------
+ targetUnregistered: (targetChannel) ->
+ WebInspector.panels.remote.removeTarget targetChannel if @client.uiAvailable()
+
+ #---------------------------------------------------------------------------
+ connectionCreated: (clientChannel, targetChannel) ->
+ if @client.uiAvailable()
+ WebInspector.panels.remote.setClientState clientChannel, "connected"
+ WebInspector.panels.remote.setTargetState targetChannel, "connected"
+
+ return unless clientChannel == Weinre.messageDispatcher.channel
+
+ WebInspector.panels.elements.reset()
+ WebInspector.panels.timeline._clearPanel()
+ WebInspector.panels.resources.reset()
+
+ target = WebInspector.panels.remote.getTarget(targetChannel)
+ document.title = titleConnectedPrefix + target.url
+ WebInspector.inspectedURLChanged target.url
+
+ Weinre.WeinreExtraClientCommands.getDatabases (databaseRecords) ->
+ WeinreExtraTargetEventsImpl.addDatabaseRecords databaseRecords
+
+ #---------------------------------------------------------------------------
+ connectionDestroyed: (clientChannel, targetChannel) ->
+ if @client.uiAvailable()
+ WebInspector.panels.remote.setClientState clientChannel, "not-connected"
+ WebInspector.panels.remote.setTargetState targetChannel, "not-connected"
+
+ return unless clientChannel == Weinre.messageDispatcher.channel
+
+ document.title = titleNotConnected
+ return unless Weinre.client.autoConnect()
+ return unless @client.uiAvailable()
+
+ nextTargetChannel = WebInspector.panels.remote.getNewestTargetChannel(targetChannel)
+ return unless nextTargetChannel
+
+ Weinre.WeinreClientCommands.connectTarget Weinre.messageDispatcher.channel, nextTargetChannel
+ Weinre.logInfo "autoconnecting to " + nextTargetChannel
+
+ #---------------------------------------------------------------------------
+ sendCallback: (callbackId, result) ->
+ Callback.invoke callbackId, result
+
+ #---------------------------------------------------------------------------
+ serverProperties: (properties) ->
+ WebInspector.panels.remote.setServerProperties properties if @client.uiAvailable()
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.coffee b/weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.coffee
new file mode 100644
index 0000000..66c88d3
--- /dev/null
+++ b/weinre.web/modules/weinre/client/WeinreExtraTargetEventsImpl.coffee
@@ -0,0 +1,35 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+module.exports = class WeinreExtraTargetEventsImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ databaseOpened: (databaseRecord) ->
+ WeinreExtraTargetEventsImpl.addDatabaseRecords [ databaseRecord ]
+
+ #---------------------------------------------------------------------------
+ @addDatabaseRecords: (databaseRecords) ->
+ return unless WebInspector.panels
+ return unless WebInspector.panels.resources
+ return unless WebInspector.panels.resources._databases
+
+ existingDbs = WebInspector.panels.resources._databases
+ existingDbNames = {}
+
+ for existingDb in existingDbs
+ existingDbNames[existingDb.name] = existingDb
+
+ for databaseRecord in databaseRecords
+ continue if existingDbNames[databaseRecord.name]
+ database = new WebInspector.Database(databaseRecord.id, databaseRecord.domain, databaseRecord.name, databaseRecord.version)
+ WebInspector.panels.resources.addDatabase database
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/Binding.coffee b/weinre.web/modules/weinre/common/Binding.coffee
new file mode 100644
index 0000000..ad7ab14
--- /dev/null
+++ b/weinre.web/modules/weinre/common/Binding.coffee
@@ -0,0 +1,26 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('./Ex')
+
+#-------------------------------------------------------------------------------
+module.exports = class Binding
+
+ constructor: (receiver, method) ->
+ if not receiver
+ throw new Ex(arguments, "receiver argument for Binding constructor was null")
+
+ method = receiver[method] if typeof (method) == "string"
+
+ if typeof (method) is not "function"
+ throw new Ex(arguments, "method argument didn't specify a function")
+
+ return -> method.apply(receiver, [].slice.call(arguments))
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/Callback.coffee b/weinre.web/modules/weinre/common/Callback.coffee
new file mode 100644
index 0000000..ee2baf2
--- /dev/null
+++ b/weinre.web/modules/weinre/common/Callback.coffee
@@ -0,0 +1,72 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('./Ex')
+
+CallbackTable = {}
+CallbackIndex = 1
+ConnectorChannel = "???"
+
+#-------------------------------------------------------------------------------
+module.exports = class Callback
+
+ constructor: ->
+ throw new Ex(arguments, "this class is not intended to be instantiated")
+
+ #---------------------------------------------------------------------------
+ @setConnectorChannel: (connectorChannel) ->
+ ConnectorChannel = "" + connectorChannel
+
+ #---------------------------------------------------------------------------
+ @register: (callback) ->
+ callback = [ null, callback ] if typeof callback == "function"
+ unless typeof callback.slice == "function"
+ throw new Ex(arguments, "callback must be an array or function")
+
+ receiver = callback[0]
+ func = callback[1]
+ data = callback.slice(2)
+ func = receiver[func] if typeof func == "string"
+
+ unless typeof func == "function"
+ throw new Ex(arguments, "callback function was null or not found")
+
+ index = ConnectorChannel + "::" + CallbackIndex
+
+ CallbackIndex++
+ CallbackIndex = 1 if CallbackIndex >= 65536 * 65536
+ CallbackTable[index] = [ receiver, func, data ]
+
+ index
+
+ #---------------------------------------------------------------------------
+ @deregister: (index) ->
+ delete CallbackTable[index]
+
+ #---------------------------------------------------------------------------
+ @invoke: (index, args) ->
+ callback = CallbackTable[index]
+
+ unless callback
+ throw new Ex(arguments, "callback #{index} not registered or already invoked")
+
+ receiver = callback[0]
+ func = callback[1]
+ args = callback[2].concat(args)
+
+ try
+ func.apply receiver, args
+ catch e
+ funcName = func.name || func.signature
+ funcName = "<unnamed>" unless funcName
+ require("./Weinre").logError arguments.callee.signature + " exception invoking callback: #{funcName}(#{args.join(',')}): " + e
+ finally
+ Callback.deregister index
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/EventListeners.coffee b/weinre.web/modules/weinre/common/EventListeners.coffee
new file mode 100644
index 0000000..535b48f
--- /dev/null
+++ b/weinre.web/modules/weinre/common/EventListeners.coffee
@@ -0,0 +1,56 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('./Ex')
+Weinre = require('./Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class EventListeners
+
+ constructor: ->
+ @listeners = []
+
+ #---------------------------------------------------------------------------
+ add: (listener, useCapture) ->
+ @listeners.push [ listener, useCapture ]
+
+ #---------------------------------------------------------------------------
+ remove: (listener, useCapture) ->
+ listeners = @listeners.slice()
+
+ for _listener in listeners
+ continue unless _listener[0] == listener
+ continue unless _listener[1] == useCapture
+
+ @_listeners.splice i, 1
+ return
+
+ #---------------------------------------------------------------------------
+ fire: (event) ->
+ listeners = @listeners.slice()
+ for listener in listeners
+ listener = listener[0]
+
+ if typeof listener is "function"
+ try
+ listener.call null, event
+ catch e
+ Weinre.logError "#{arguments.callee.name} invocation exception: #{e}"
+ continue
+
+ if typeof listener?.handleEvent isnt "function"
+ throw new Ex(arguments, "listener does not implement the handleEvent() method")
+
+ try
+ listener.handleEvent.call listener, event
+ catch e
+ Weinre.logError "#{arguments.callee.name} invocation exception: #{e}"
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
+
diff --git a/weinre.web/modules/weinre/common/Ex.coffee b/weinre.web/modules/weinre/common/Ex.coffee
new file mode 100644
index 0000000..e5c1591
--- /dev/null
+++ b/weinre.web/modules/weinre/common/Ex.coffee
@@ -0,0 +1,31 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+StackTrace = require('./StackTrace')
+
+#-------------------------------------------------------------------------------
+module.exports = class Ex
+
+ constructor: (args, message) ->
+ if not args or not args.callee
+ throw Ex(arguments, "first parameter must be an Arguments object")
+
+ StackTrace.dump args
+ message = "threw error: " + message if message instanceof Error
+ new Error(prefix(args, message))
+
+#-------------------------------------------------------------------------------
+prefix = (args, string) ->
+ return args.callee.signature + ": " + string if args.callee.signature
+ return args.callee.displayName + ": " + string if args.callee.displayName
+ return args.callee.name + ": " + string if args.callee.name
+
+ "<anonymous>" + ": " + string
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/IDGenerator.coffee b/weinre.web/modules/weinre/common/IDGenerator.coffee
new file mode 100644
index 0000000..0a4f599
--- /dev/null
+++ b/weinre.web/modules/weinre/common/IDGenerator.coffee
@@ -0,0 +1,41 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+nextIdValue = 1
+idName = "__weinre__id"
+
+module.exports = class IDGenerator
+
+ #---------------------------------------------------------------------------
+ @checkId: (object) ->
+ object[idName]
+
+ #---------------------------------------------------------------------------
+ @getId: (object, map) ->
+ id = IDGenerator.checkId(object)
+
+ unless id
+ id = nextId()
+ object[idName] = id
+
+ map[id] = object if map
+
+ id
+
+ #---------------------------------------------------------------------------
+ @next: ->
+ nextId()
+
+#-------------------------------------------------------------------------------
+nextId = () ->
+ result = nextIdValue
+ nextIdValue += 1
+ result
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/IDLTools.coffee b/weinre.web/modules/weinre/common/IDLTools.coffee
new file mode 100644
index 0000000..a989836
--- /dev/null
+++ b/weinre.web/modules/weinre/common/IDLTools.coffee
@@ -0,0 +1,112 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('./Ex')
+Callback = require('./Callback')
+
+IDLs = {}
+
+#-------------------------------------------------------------------------------
+module.exports = class IDLTools
+
+ #---------------------------------------------------------------------------
+ constructor: ->
+ throw new Ex(arguments, "this class is not intended to be instantiated")
+
+ #---------------------------------------------------------------------------
+ @addIDLs: (idls) ->
+ for idl in idls
+ for intf in idl.interfaces
+ IDLs[intf.name] = intf
+ intf.module = idl.name
+
+ #---------------------------------------------------------------------------
+ @getIDL: (name) ->
+ IDLs[name]
+
+ #---------------------------------------------------------------------------
+ @getIDLsMatching: (regex) ->
+ results = []
+
+ for intfName of IDLs
+ intf = IDLs[intfName]
+ results.push intf if intfName.match(regex)
+
+ results
+
+ #---------------------------------------------------------------------------
+ @validateAgainstIDL: (klass, interfaceName) ->
+ intf = IDLTools.getIDL(interfaceName)
+ messagePrefix = "IDL validation for #{interfaceName}: "
+ if null == intf
+ throw new Ex(arguments, messagePrefix + "idl not found: '#{interfaceName}'")
+
+ errors = []
+ for intfMethod in intf.methods
+ classMethod = klass::[intfMethod.name]
+ printName = klass.name + "::" + intfMethod.name
+
+ if null == classMethod
+ errors.push messagePrefix + "method not implemented: '#{printName}'"
+ continue
+
+ unless classMethod.length == intfMethod.parameters.length
+ unless classMethod.length == intfMethod.parameters.length + 1
+ errors.push messagePrefix + "wrong number of parameters: '#{printName}'"
+ continue
+
+ for propertyName of klass::
+ continue if klass::hasOwnProperty(propertyName)
+ continue if propertyName.match(/^_.*/)
+ printName = klass.name + "::" + propertyName
+
+ unless intf.methods[propertyName]
+ errors.push messagePrefix + "method should not be implemented: '#{printName}'"
+ continue
+
+ return unless errors.length
+
+ for error in errors
+ require("./Weinre").logError error
+
+ #---------------------------------------------------------------------------
+ @buildProxyForIDL: (proxyObject, interfaceName) ->
+ intf = IDLTools.getIDL(interfaceName)
+ messagePrefix = "building proxy for IDL #{interfaceName}: "
+
+ if null == intf
+ throw new Ex(arguments, messagePrefix + "idl not found: '#{interfaceName}'")
+
+ for intfMethod in intf.methods
+ proxyObject[intfMethod.name] = getProxyMethod(intf, intfMethod)
+
+#-------------------------------------------------------------------------------
+getProxyMethod = (intf, method) ->
+ result = proxyMethod = ->
+
+ callbackId = null
+ args = [].slice.call(arguments)
+
+ if args.length > 0
+ if typeof args[args.length - 1] == "function"
+ callbackId = Callback.register(args[args.length - 1])
+ args = args.slice(0, args.length - 1)
+
+ while args.length < method.parameters.length
+ args.push null
+
+ args.push callbackId
+ @__invoke intf.name, method.name, args
+
+ result.displayName = intf.name + "__" + method.name
+
+ result
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
+
diff --git a/weinre.web/modules/weinre/common/MessageDispatcher.coffee b/weinre.web/modules/weinre/common/MessageDispatcher.coffee
new file mode 100644
index 0000000..5f1a4be
--- /dev/null
+++ b/weinre.web/modules/weinre/common/MessageDispatcher.coffee
@@ -0,0 +1,179 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('./Weinre')
+WebSocketXhr = require('./WebSocketXhr')
+IDLTools = require('./IDLTools')
+Binding = require('./Binding')
+Ex = require('./Ex')
+Callback = require('./Callback')
+
+Verbose = false
+InspectorBackend = null
+
+#-------------------------------------------------------------------------------
+module.exports = class MessageDispatcher
+
+ #---------------------------------------------------------------------------
+ constructor: (url, id) ->
+ id = "anonymous" unless id
+ @_url = url
+ @_id = id
+ @error = null
+ @_opening = false
+ @_opened = false
+ @_closed = false
+ @_interfaces = {}
+ @_open()
+
+ #---------------------------------------------------------------------------
+ @setInspectorBackend: (inspectorBackend) ->
+ InspectorBackend = inspectorBackend
+
+ #---------------------------------------------------------------------------
+ @verbose: (value) ->
+ Verbose = not not value if arguments.length >= 1
+ Verbose
+
+ #---------------------------------------------------------------------------
+ _open: ->
+ return if @_opened or @_opening
+ throw new Ex(arguments, "socket has already been closed") if @_closed
+ @_opening = true
+ @_socket = new WebSocketXhr(@_url, @_id)
+ @_socket.addEventListener "open", Binding(this, "_handleOpen")
+ @_socket.addEventListener "error", Binding(this, "_handleError")
+ @_socket.addEventListener "message", Binding(this, "_handleMessage")
+ @_socket.addEventListener "close", Binding(this, "_handleClose")
+
+ #---------------------------------------------------------------------------
+ close: ->
+ return if @_closed
+ @_opened = false
+ @_closed = true
+ @_socket.close()
+
+ #---------------------------------------------------------------------------
+ send: (data) ->
+ @_socket.send data
+
+ #---------------------------------------------------------------------------
+ getWebSocket: ->
+ @_socket
+
+ #---------------------------------------------------------------------------
+ registerInterface: (intfName, intf, validate) ->
+ if validate
+ IDLTools.validateAgainstIDL intf.constructor, intfName
+
+ if @_interfaces[intfName]
+ throw new Ex(arguments, "interface #{intfName} has already been registered")
+
+ @_interfaces[intfName] = intf
+
+ #---------------------------------------------------------------------------
+ createProxy: (intfName) ->
+ proxy = {}
+ IDLTools.buildProxyForIDL proxy, intfName
+ self = this
+
+ proxy.__invoke = __invoke = (intfName, methodName, args) ->
+ self._sendMethodInvocation intfName, methodName, args
+
+ proxy
+
+ #---------------------------------------------------------------------------
+ _sendMethodInvocation: (intfName, methodName, args) ->
+ unless typeof intfName == "string"
+ throw new Ex(arguments, "expecting intf parameter to be a string")
+
+ unless typeof methodName == "string"
+ throw new Ex(arguments, "expecting method parameter to be a string")
+
+ data =
+ interface: intfName
+ method: methodName
+ args: args
+
+ data = JSON.stringify(data)
+ @_socket.send data
+
+ if Verbose
+ Weinre.logDebug @constructor.name + "[#{@_url}]: send #{intfName}.#{methodName}(#{JSON.stringify(args)})"
+
+ #---------------------------------------------------------------------------
+ getState: ->
+ return "opening" if @_opening
+ return "opened" if @_opened
+ return "closed" if @_closed
+ "unknown"
+
+ #---------------------------------------------------------------------------
+ isOpen: ->
+ @_opened == true
+
+ #---------------------------------------------------------------------------
+ _handleOpen: (event) ->
+ @_opening = false
+ @_opened = true
+ @channel = event.channel
+ Callback.setConnectorChannel @channel
+
+ if Verbose
+ Weinre.logDebug @constructor.name + "[#{@_url}]: opened"
+
+ #---------------------------------------------------------------------------
+ _handleError: (message) ->
+ @error = message
+ @close()
+
+ if Verbose
+ Weinre.logDebug @constructor.name + "[#{@_url}]: error: " + message
+
+ #---------------------------------------------------------------------------
+ _handleMessage: (message) ->
+ try
+ data = JSON.parse(message.data)
+ catch e
+ throw new Ex(arguments, "invalid JSON data received: #{e}: '#{message.data}'")
+
+ intfName = data["interface"]
+ methodName = data.method
+ args = data.args
+ methodSignature = intfName + ".#{methodName}()"
+ intf = @_interfaces.hasOwnProperty(intfName) and @_interfaces[intfName]
+
+ if not intf and InspectorBackend and intfName.match(/.*Notify/)
+ intf = InspectorBackend.getRegisteredDomainDispatcher(intfName.substr(0, intfName.length - 6))
+
+ unless intf
+ Weinre.logWarning "weinre: request for non-registered interface:" + methodSignature
+ return
+
+ methodSignature = intf.constructor.name + ".#{methodName}()"
+ method = intf[methodName]
+
+ unless typeof method == "function"
+ Weinre.notImplemented methodSignature
+ return
+ try
+ method.apply intf, args
+ catch e
+ Weinre.logError "weinre: invocation exception on #{methodSignature}: " + e
+
+ if Verbose
+ Weinre.logDebug @constructor.name + "[#{@_url}]: recv #{intfName}.#{methodName}(#{JSON.stringify(args)})"
+
+ #---------------------------------------------------------------------------
+ _handleClose: ->
+ @_reallyClosed = true
+ if Verbose
+ Weinre.logDebug @constructor.name + "[#{@_url}]: closed"
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/MethodNamer.coffee b/weinre.web/modules/weinre/common/MethodNamer.coffee
new file mode 100644
index 0000000..4d5c755
--- /dev/null
+++ b/weinre.web/modules/weinre/common/MethodNamer.coffee
@@ -0,0 +1,25 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+module.exports = class MethodNamer
+
+ @setNamesForClass: (aClass) ->
+ for own key, val of aClass
+ if typeof(val) is "function"
+ val.signature = "#{aClass.name}::#{key}"
+ val.displayName = key
+ val.name = key
+
+ for own key, val of aClass.prototype
+ if typeof(val) is "function"
+ val.signature = "#{aClass.name}.#{key}"
+ val.displayName = key
+ val.name = key
+
+#-------------------------------------------------------------------------------
+MethodNamer.setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/Native.coffee b/weinre.web/modules/weinre/common/Native.coffee
new file mode 100644
index 0000000..04ea3c3
--- /dev/null
+++ b/weinre.web/modules/weinre/common/Native.coffee
@@ -0,0 +1,43 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+exports.original = {}
+
+exports.original.clearInterval = window.clearInterval
+exports.original.clearTimeout = window.clearTimeout
+exports.original.setTimeout = window.setTimeout
+exports.original.setInterval = window.setInterval
+exports.original.XMLHttpRequest = window.XMLHttpRequest
+exports.original.XMLHttpRequest_open = window.XMLHttpRequest.prototype.open
+exports.original.LocalStorage_setItem = window.localStorage?.setItem
+exports.original.LocalStorage_removeItem = window.localStorage?.removeItem
+exports.original.LocalStorage_clear = window.localStorage?.clear
+exports.original.SessionStorage_setItem = window.sessionStorage?.setItem
+exports.original.SessionStorage_removeItem = window.sessionStorage?.removeItem
+exports.original.SessionStorage_clear = window.sessionStorage?.clear
+exports.original.openDatabase = window.openDatabase
+
+exports.clearInterval = -> exports.original.clearInterval.apply( window, [].slice.call(arguments))
+exports.clearTimeout = -> exports.original.clearTimeout.apply( window, [].slice.call(arguments))
+exports.setInterval = -> exports.original.setInterval.apply( window, [].slice.call(arguments))
+exports.setTimeout = -> exports.original.setTimeout.apply( window, [].slice.call(arguments))
+exports.XMLHttpRequest = -> new exports.original.XMLHttpRequest()
+exports.XMLHttpRequest_open = -> exports.original.XMLHttpRequest_open.apply(this, [].slice.call(arguments))
+exports.LocalStorage_setItem = -> exports.original.LocalStorage_setItem.apply( window.localStorage, [].slice.call(arguments))
+exports.LocalStorage_removeItem = -> exports.original.LocalStorage_removeItem.apply( window.localStorage, [].slice.call(arguments))
+exports.LocalStorage_clear = -> exports.original.LocalStorage_clear.apply( window.localStorage, [].slice.call(arguments))
+exports.SessionStorage_setItem = -> exports.original.SessionStorage_setItem.apply( window.sessionStorage, [].slice.call(arguments))
+exports.SessionStorage_removeItem = -> exports.original.SessionStorage_removeItem.apply( window.sessionStorage, [].slice.call(arguments))
+exports.SessionStorage_clear = -> exports.original.SessionStorage_clear.apply( window.sessionStorage, [].slice.call(arguments))
+exports.openDatabase = -> exports.original.openDatabase.apply( window, [].slice.call(arguments))
+
+for own key, val of exports
+ if typeof(val) is "function"
+ val.signature = "Native::#{key}"
+ val.displayName = key
+ val.name = key
diff --git a/weinre.web/modules/weinre/common/StackTrace.coffee b/weinre.web/modules/weinre/common/StackTrace.coffee
new file mode 100644
index 0000000..b7ace3f
--- /dev/null
+++ b/weinre.web/modules/weinre/common/StackTrace.coffee
@@ -0,0 +1,55 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+module.exports = class StackTrace
+
+ constructor: (args) ->
+ if not args or not args.callee
+ throw Error("first parameter to #{arguments.callee.signature} must be an Arguments object")
+
+ @trace = getTrace(args)
+
+ #---------------------------------------------------------------------------
+ @dump: (args) ->
+ args = args or arguments
+ stackTrace = new StackTrace(args)
+ stackTrace.dump()
+
+ #---------------------------------------------------------------------------
+ dump: ->
+ console.log "StackTrace:"
+ for frame in @trace
+ console.log " " + frame
+
+#-------------------------------------------------------------------------------
+getTrace = (args) ->
+ result = []
+ visitedFuncs = []
+ func = args.callee
+
+ while func
+ if func.signature
+ result.push func.signature
+ else if func.displayName
+ result.push func.displayName
+ else if func.name
+ result.push func.name
+ else
+ result.push "<anonymous>"
+
+ unless -1 == visitedFuncs.indexOf(func)
+ result.push "... recursion"
+ return result
+
+ visitedFuncs.push func
+ func = func.caller
+
+ result
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/WebSocketXhr.coffee b/weinre.web/modules/weinre/common/WebSocketXhr.coffee
new file mode 100644
index 0000000..acc1f90
--- /dev/null
+++ b/weinre.web/modules/weinre/common/WebSocketXhr.coffee
@@ -0,0 +1,202 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('./Ex')
+Weinre = require('./Weinre')
+EventListeners = require('./EventListeners')
+Native = require('./Native')
+
+XMLHttpRequest = Native.XMLHttpRequest
+
+#-------------------------------------------------------------------------------
+module.exports = class WebSocketXhr
+
+ @CONNECTING = 0
+ @OPEN = 1
+ @CLOSING = 2
+ @CLOSED = 3
+
+ #---------------------------------------------------------------------------
+ constructor: (url, id) ->
+ @initialize url, id
+
+ #---------------------------------------------------------------------------
+ initialize: (url, id) ->
+ id = "anonymous" unless id
+ @readyState = WebSocketXhr.CONNECTING
+ @_url = url
+ @_id = id
+ @_urlChannel = null
+ @_queuedSends = []
+ @_sendInProgress = true
+
+ @_listeners =
+ open: new EventListeners()
+ message: new EventListeners()
+ error: new EventListeners()
+ close: new EventListeners()
+
+ @_getChannel()
+
+ #---------------------------------------------------------------------------
+ _getChannel: ->
+ body = JSON.stringify(id: @_id)
+ @_xhr @_url, "POST", body, @_handleXhrResponseGetChannel
+
+ #---------------------------------------------------------------------------
+ _handleXhrResponseGetChannel: (xhr) ->
+ return @_handleXhrResponseError(xhr) unless xhr.status == 200
+
+ try
+ object = JSON.parse(xhr.responseText)
+ catch e
+ @_fireEventListeners "error", message: "non-JSON response from channel open request"
+ @close()
+ return
+
+ unless object.channel
+ @_fireEventListeners "error", message: "channel open request did not include a channel"
+ @close()
+ return
+
+ @_urlChannel = @_url + "/" + object.channel
+ @readyState = WebSocketXhr.OPEN
+
+ @_fireEventListeners "open",
+ message: "open"
+ channel: object.channel
+
+ @_sendInProgress = false
+ @_sendQueued()
+ @_readLoop()
+
+ #---------------------------------------------------------------------------
+ _readLoop: ->
+ return if @readyState == WebSocketXhr.CLOSED
+ return if @readyState == WebSocketXhr.CLOSING
+
+ @_xhr @_urlChannel, "GET", "", @_handleXhrResponseGet
+
+ #---------------------------------------------------------------------------
+ _handleXhrResponseGet: (xhr) ->
+ self = this
+ return @_handleXhrResponseError(xhr) unless xhr.status == 200
+
+ try
+ datum = JSON.parse(xhr.responseText)
+ catch e
+ @readyState = WebSocketXhr.CLOSED
+ @_fireEventListeners "error", message: "non-JSON response from read request"
+ return
+
+ Native.setTimeout (->
+ self._readLoop()
+ ), 0
+
+ for data in datum
+ self._fireEventListeners "message", data: data
+
+ #---------------------------------------------------------------------------
+ send: (data) ->
+ unless typeof data == "string"
+ throw new Ex(arguments, @constructor.name + "." + @caller)
+
+ @_queuedSends.push data
+ return if @_sendInProgress
+ @_sendQueued()
+
+ #---------------------------------------------------------------------------
+ _sendQueued: ->
+ return if @_queuedSends.length == 0
+ return if @readyState == WebSocketXhr.CLOSED
+ return if @readyState == WebSocketXhr.CLOSING
+
+ datum = JSON.stringify(@_queuedSends)
+ @_queuedSends = []
+ @_sendInProgress = true
+ @_xhr @_urlChannel, "POST", datum, @_handleXhrResponseSend
+
+ #---------------------------------------------------------------------------
+ _handleXhrResponseSend: (xhr) ->
+ httpSocket = this
+ return @_handleXhrResponseError(xhr) unless xhr.status == 200
+
+ @_sendInProgress = false
+
+ Native.setTimeout (->
+ httpSocket._sendQueued()
+ ), 0
+
+ #---------------------------------------------------------------------------
+ close: ->
+ @_sendInProgress = true
+ @readyState = WebSocketXhr.CLOSING
+
+ @_fireEventListeners "close",
+ message: "closing"
+ wasClean: true
+
+ @readyState = WebSocketXhr.CLOSED
+
+ #---------------------------------------------------------------------------
+ addEventListener: (type, listener, useCapture) ->
+ @_getListeners(type).add listener, useCapture
+
+ #---------------------------------------------------------------------------
+ removeEventListener: (type, listener, useCapture) ->
+ @_getListeners(type).remove listener, useCapture
+
+ #---------------------------------------------------------------------------
+ _fireEventListeners: (type, event) ->
+ return if @readyState == WebSocketXhr.CLOSED
+
+ event.target = this
+ @_getListeners(type).fire event
+
+ #---------------------------------------------------------------------------
+ _getListeners: (type) ->
+ listeners = @_listeners[type]
+ if null == listeners
+ throw new Ex(arguments, "invalid event listener type: '#{type}'")
+ listeners
+
+ #---------------------------------------------------------------------------
+ _handleXhrResponseError: (xhr) ->
+ if xhr.status == 404
+ @close()
+ return
+
+ @_fireEventListeners "error",
+ target: this
+ status: xhr.status
+ message: "error from XHR invocation: " + xhr.statusText
+
+ Weinre.logError "error from XHR invocation: #{xhr.status}: " + xhr.statusText
+
+ #---------------------------------------------------------------------------
+ _xhr: (url, method, data, handler) ->
+ if null == handler
+ throw new Ex(arguments, "handler must not be null")
+
+ xhr = new XMLHttpRequest()
+ xhr.httpSocket = this
+ xhr.httpSocketHandler = handler
+ xhr.onreadystatechange = _xhrEventHandler
+ xhr.open method, url, true
+ xhr.setRequestHeader "Content-Type", "text/plain"
+ xhr.send data
+
+#-------------------------------------------------------------------------------
+_xhrEventHandler = (event) ->
+ xhr = event.target
+ return unless xhr.readyState == 4
+
+ xhr.httpSocketHandler.call xhr.httpSocket, xhr
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/common/Weinre.coffee b/weinre.web/modules/weinre/common/Weinre.coffee
new file mode 100644
index 0000000..52bc180
--- /dev/null
+++ b/weinre.web/modules/weinre/common/Weinre.coffee
@@ -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
+#---------------------------------------------------------------------------------
+
+Ex = require('./Ex')
+IDLTools = require('./IDLTools')
+StackTrace = require('./StackTrace')
+
+_notImplemented = {}
+_showNotImplemented = false
+CSSProperties = []
+logger = null
+
+#-------------------------------------------------------------------------------
+module.exports = class Weinre
+
+ #---------------------------------------------------------------------------
+ constructor: ->
+ throw new Ex(arguments, "this class is not intended to be instantiated")
+
+ #---------------------------------------------------------------------------
+ @addIDLs: (idls) ->
+ IDLTools.addIDLs idls
+
+ #---------------------------------------------------------------------------
+ @addCSSProperties: (cssProperties) ->
+ CSSProperties = cssProperties
+
+ #---------------------------------------------------------------------------
+ @getCSSProperties: ->
+ CSSProperties
+
+ #---------------------------------------------------------------------------
+ @deprecated: () ->
+ StackTrace.dump arguments
+
+ #---------------------------------------------------------------------------
+ @notImplemented: (thing) ->
+ return if _notImplemented[thing]
+
+ _notImplemented[thing] = true
+ return unless _showNotImplemented
+
+ Weinre.logWarning thing + " not implemented"
+
+ #---------------------------------------------------------------------------
+ @showNotImplemented: () ->
+ _showNotImplemented = true
+
+ for key of _notImplemented
+ Weinre.logWarning key + " not implemented"
+
+ #---------------------------------------------------------------------------
+ @logError: (message) ->
+ getLogger().logError message
+
+ #---------------------------------------------------------------------------
+ @logWarning: (message) ->
+ getLogger().logWarning message
+
+ #---------------------------------------------------------------------------
+ @logInfo: (message) ->
+ getLogger().logInfo message
+
+ #---------------------------------------------------------------------------
+ @logDebug: (message) ->
+ getLogger().logDebug message
+
+#-------------------------------------------------------------------------------
+class ConsoleLogger
+ logError: (message) -> console.log "error: #{message}"
+ logWarning: (message) -> console.log "warning: #{message}"
+ logInfo: (message) -> console.log "info: #{message}"
+ logDebug: (message) -> console.log "debug: #{message}"
+
+consoleLogger = new ConsoleLogger()
+
+#-------------------------------------------------------------------------------
+getLogger = () ->
+ return logger if logger
+
+ if Weinre.client
+ logger = Weinre.WeinreClientCommands
+ return logger
+
+ if Weinre.target
+ logger = Weinre.WeinreTargetCommands
+ return logger
+
+ consoleLogger
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/CSSStore.coffee b/weinre.web/modules/weinre/target/CSSStore.coffee
new file mode 100644
index 0000000..27ce891
--- /dev/null
+++ b/weinre.web/modules/weinre/target/CSSStore.coffee
@@ -0,0 +1,346 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+IDGenerator = require('../common/IDGenerator')
+Weinre = require('../common/Weinre')
+
+Properties = []
+
+_elementMatchesSelector = null
+
+#-------------------------------------------------------------------------------
+module.exports = class CSSStore
+
+ #---------------------------------------------------------------------------
+ constructor: ->
+ @styleSheetMap = {}
+ @styleRuleMap = {}
+ @styleDeclMap = {}
+ @testElement = document.createElement("div")
+
+ #---------------------------------------------------------------------------
+ @addCSSProperties: (properties) ->
+ Properties = properties
+
+ #---------------------------------------------------------------------------
+ getInlineStyle: (node) ->
+ styleObject = @_buildMirrorForStyle(node.style, true)
+
+ for cssProperty in styleObject.cssProperties
+ cssProperty.status = "style"
+
+ styleObject
+
+ #---------------------------------------------------------------------------
+ getComputedStyle: (node) ->
+ return {} unless node
+ return {} unless node.nodeType == Node.ELEMENT_NODE
+
+ styleObject = @_buildMirrorForStyle(window.getComputedStyle(node), false)
+ styleObject
+
+ #---------------------------------------------------------------------------
+ getMatchedCSSRules: (node) ->
+ result = []
+
+ for styleSheet in document.styleSheets
+ continue unless styleSheet.cssRules
+
+ for cssRule in styleSheet.cssRules
+ continue unless _elementMatchesSelector(node, cssRule.selectorText)
+ object = {}
+ object.ruleId = @_getStyleRuleId(cssRule)
+ object.selectorText = cssRule.selectorText
+ object.style = @_buildMirrorForStyle(cssRule.style, true)
+ result.push object
+
+ result
+
+ #---------------------------------------------------------------------------
+ getStyleAttributes: (node) ->
+ result = {}
+ result
+
+ #---------------------------------------------------------------------------
+ getPseudoElements: (node) ->
+ result = []
+ result
+
+ #---------------------------------------------------------------------------
+ setPropertyText: (styleId, propertyIndex, text, overwrite) ->
+ styleDecl = Weinre.cssStore._getStyleDecl(styleId)
+
+ unless styleDecl
+ Weinre.logWarning "requested style not available: " + styleId
+ return null
+
+ mirror = styleDecl.__weinre__mirror
+ unless mirror
+ Weinre.logWarning "requested mirror not available: " + styleId
+ return null
+
+ properties = mirror.cssProperties
+ propertyMirror = @_parseProperty(text)
+
+ if null == propertyMirror
+ @_removePropertyFromMirror mirror, propertyIndex
+ properties = mirror.cssProperties
+
+ else
+ @_removePropertyFromMirror mirror, propertyIndex
+ properties = mirror.cssProperties
+ propertyIndices = {}
+ i = 0
+
+ while i < properties.length
+ propertyIndices[properties[i].name] = i
+ i++
+ i = 0
+
+ while i < propertyMirror.cssProperties.length
+ if propertyIndices[propertyMirror.cssProperties[i].name]?
+ properties[propertyIndices[propertyMirror.cssProperties[i].name]] = propertyMirror.cssProperties[i]
+ else
+ properties.push propertyMirror.cssProperties[i]
+ i++
+
+ for key of propertyMirror.shorthandValues
+ mirror.shorthandValues[key] = propertyMirror.shorthandValues[key]
+
+ properties.sort compare = (p1, p2) ->
+ if p1.name < p2.name
+ -1
+ else if p1.name > p2.name
+ 1
+ else
+ 0
+
+ @_setStyleFromMirror styleDecl
+ mirror
+
+ #---------------------------------------------------------------------------
+ _removePropertyFromMirror: (mirror, index) ->
+ properties = mirror.cssProperties
+ return if index >= properties.length
+ property = properties[index]
+ properties[index] = null
+
+ if mirror.shorthandValues[property.name]
+ delete mirror.shorthandValues[property.name]
+
+ i = 0
+
+ while i < properties.length
+ if properties[i]
+ if properties[i].shorthandName == property.name
+ properties[i] = null
+ i++
+
+ newProperties = []
+ i = 0
+
+ while i < properties.length
+ newProperties.push properties[i] if properties[i]
+ i++
+
+ mirror.cssProperties = newProperties
+
+ #---------------------------------------------------------------------------
+ toggleProperty: (styleId, propertyIndex, disable) ->
+ styleDecl = Weinre.cssStore._getStyleDecl(styleId)
+ unless styleDecl
+ Weinre.logWarning "requested style not available: " + styleId
+ return null
+
+ mirror = styleDecl.__weinre__mirror
+ unless mirror
+ Weinre.logWarning "requested mirror not available: " + styleId
+ return null
+
+ cssProperty = mirror.cssProperties[propertyIndex]
+ unless cssProperty
+ Weinre.logWarning "requested property not available: #{styleId}: " + propertyIndex
+ return null
+
+ if disable
+ cssProperty.status = "disabled"
+ else
+ cssProperty.status = "active"
+
+ @_setStyleFromMirror styleDecl
+ mirror
+
+ #---------------------------------------------------------------------------
+ _setStyleFromMirror: (styleDecl) ->
+ cssText = []
+ cssProperties = styleDecl.__weinre__mirror.cssProperties
+ cssText = ""
+
+ for property in cssProperties
+ continue unless property.parsedOk
+ continue if property.status == "disabled"
+ continue if property.shorthandName
+
+ cssText += property.name + ": " + property.value
+ if property.priority == "important"
+ cssText += " !important; "
+ else
+ cssText += "; "
+
+ styleDecl.cssText = cssText
+
+ #---------------------------------------------------------------------------
+ _buildMirrorForStyle: (styleDecl, bind) ->
+ result =
+ properties: {}
+ cssProperties: []
+
+ return result unless styleDecl
+ if bind
+ result.styleId = @_getStyleDeclId(styleDecl)
+ styleDecl.__weinre__mirror = result
+
+ result.properties.width = styleDecl.getPropertyValue("width") or ""
+ result.properties.height = styleDecl.getPropertyValue("height") or ""
+ result.cssText = styleDecl.cssText
+ result.shorthandValues = {}
+
+ properties = []
+ if styleDecl
+ i = 0
+
+ while i < styleDecl.length
+ property = {}
+ name = styleDecl.item(i)
+ property.name = name
+ property.priority = styleDecl.getPropertyPriority(name)
+ property.implicit = styleDecl.isPropertyImplicit(name)
+ property.shorthandName = styleDecl.getPropertyShorthand(name) or ""
+ property.status = (if property.shorthandName then "style" else "active")
+ property.parsedOk = true
+ property.value = styleDecl.getPropertyValue(name)
+ properties.push property
+
+ if property.shorthandName
+ shorthandName = property.shorthandName
+
+ unless result.shorthandValues[shorthandName]
+ result.shorthandValues[shorthandName] = styleDecl.getPropertyValue(shorthandName)
+ property = {}
+ property.name = shorthandName
+ property.priority = styleDecl.getPropertyPriority(shorthandName)
+ property.implicit = styleDecl.isPropertyImplicit(shorthandName)
+ property.shorthandName = ""
+ property.status = "active"
+ property.parsedOk = true
+ property.value = styleDecl.getPropertyValue(name)
+ properties.push property
+ i++
+
+ properties.sort (p1, p2) ->
+ if p1.name < p2.name
+ -1
+ else if p1.name > p2.name
+ 1
+ else
+ 0
+
+ result.cssProperties = properties
+ result
+
+ #---------------------------------------------------------------------------
+ _parseProperty: (string) ->
+ testStyleDecl = @testElement.style
+
+ try
+ testStyleDecl.cssText = string
+ unless testStyleDecl.cssText == ""
+ return @_buildMirrorForStyle(testStyleDecl, false)
+
+ propertyPattern = /\s*(.+)\s*:\s*(.+)\s*(!important)?\s*;/
+ match = propertyPattern.exec(string)
+ return null unless match
+
+ match[3] = (if (match[3] == "!important") then "important" else "")
+
+ property = {}
+ property.name = match[1]
+ property.priority = match[3]
+ property.implicit = true
+ property.shorthandName = ""
+ property.status = "inactive"
+ property.parsedOk = false
+ property.value = match[2]
+
+ result = {}
+ result.width = 0
+ result.height = 0
+ result.shorthandValues = 0
+ result.cssProperties = [ property ]
+
+ result
+
+ #---------------------------------------------------------------------------
+ _getStyleSheet: (id) ->
+ _getMappableObject id, @styleSheetMap
+
+ #---------------------------------------------------------------------------
+ _getStyleSheetId: (styleSheet) ->
+ _getMappableId styleSheet, @styleSheetMap
+
+ #---------------------------------------------------------------------------
+ _getStyleRule: (id) ->
+ _getMappableObject id, @styleRuleMap
+
+ #---------------------------------------------------------------------------
+ _getStyleRuleId: (styleRule) ->
+ _getMappableId styleRule, @styleRuleMap
+
+ #---------------------------------------------------------------------------
+ _getStyleDecl: (id) ->
+ _getMappableObject id, @styleDeclMap
+
+ #---------------------------------------------------------------------------
+ _getStyleDeclId: (styleDecl) ->
+ _getMappableId styleDecl, @styleDeclMap
+
+#-------------------------------------------------------------------------------
+_getMappableObject = (id, map) ->
+ map[id]
+
+#-------------------------------------------------------------------------------
+_getMappableId = (object, map) ->
+ IDGenerator.getId object, map
+
+#-------------------------------------------------------------------------------
+_mozMatchesSelector = (element, selector) ->
+ return false unless element.mozMatchesSelector
+ element.mozMatchesSelector selector
+
+#-------------------------------------------------------------------------------
+_webkitMatchesSelector = (element, selector) ->
+ return false unless element.webkitMatchesSelector
+ element.webkitMatchesSelector selector
+
+#-------------------------------------------------------------------------------
+_fallbackMatchesSelector = (element, selector) ->
+ false
+
+#-------------------------------------------------------------------------------
+if (Element.prototype.webkitMatchesSelector)
+ _elementMatchesSelector = _webkitMatchesSelector
+
+else if (Element.prototype.mozMatchesSelector)
+ _elementMatchesSelector = _mozMatchesSelector
+
+else
+ _elementMatchesSelector = _fallbackMatchesSelector
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
+
diff --git a/weinre.web/modules/weinre/target/CheckForProblems.coffee b/weinre.web/modules/weinre/target/CheckForProblems.coffee
new file mode 100644
index 0000000..cb30171
--- /dev/null
+++ b/weinre.web/modules/weinre/target/CheckForProblems.coffee
@@ -0,0 +1,30 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+module.exports = class CheckForProblems
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ @check: ->
+ checkForOldPrototypeVersion()
+
+#-------------------------------------------------------------------------------
+checkForOldPrototypeVersion = () ->
+ badVersion = false
+ return if typeof Prototype == "undefined"
+ return unless Prototype.Version
+
+ badVersion = true if Prototype.Version.match(/^1\.5.*/)
+ badVersion = true if Prototype.Version.match(/^1\.6.*/)
+
+ if badVersion
+ alert "Sorry, weinre is not support in versions of Prototype earlier than 1.7"
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/Console.coffee b/weinre.web/modules/weinre/target/Console.coffee
new file mode 100644
index 0000000..800c84f
--- /dev/null
+++ b/weinre.web/modules/weinre/target/Console.coffee
@@ -0,0 +1,164 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+Timeline = require('../target/Timeline')
+
+UsingRemote = false
+
+RemoteConsole = null
+OriginalConsole = null
+
+MessageSource =
+ HTML: 0
+ WML: 1
+ XML: 2
+ JS: 3
+ CSS: 4
+ Other: 5
+
+MessageType =
+ Log: 0
+ Object: 1
+ Trace: 2
+ StartGroup: 3
+ StartGroupCollapsed: 4
+ EndGroup: 5
+ Assert: 6
+ UncaughtException: 7
+ Result: 8
+
+MessageLevel =
+ Tip: 0
+ Log: 1
+ Warning: 2
+ Error: 3
+ Debug: 4
+
+#-------------------------------------------------------------------------------
+module.exports = class Console
+
+ #---------------------------------------------------------------------------
+ Console::__defineGetter__("original", -> OriginalConsole)
+
+ #---------------------------------------------------------------------------
+ @useRemote: (value) ->
+ return UsingRemote if arguments.length == 0
+
+ oldValue = UsingRemote
+ UsingRemote = not not value
+
+ if UsingRemote
+ window.console = RemoteConsole
+ else
+ window.console = OriginalConsole
+
+ oldValue
+
+ #---------------------------------------------------------------------------
+ _generic: (level, messageParts) ->
+ message = messageParts[0].toString()
+ parameters = []
+
+ for messagePart in messageParts
+ parameters.push Weinre.injectedScript.wrapObjectForConsole(messagePart, true)
+
+ payload =
+ source: MessageSource.JS
+ type: MessageType.Log
+ level: level
+ message: message
+ parameters: parameters
+
+ Weinre.wi.ConsoleNotify.addConsoleMessage payload
+
+ #---------------------------------------------------------------------------
+ log: ->
+ @_generic MessageLevel.Log, [].slice.call(arguments)
+
+ #---------------------------------------------------------------------------
+ debug: ->
+ @_generic MessageLevel.Debug, [].slice.call(arguments)
+
+ #---------------------------------------------------------------------------
+ error: ->
+ @_generic MessageLevel.Error, [].slice.call(arguments)
+
+ #---------------------------------------------------------------------------
+ info: ->
+ @_generic MessageLevel.Log, [].slice.call(arguments)
+
+ #---------------------------------------------------------------------------
+ warn: ->
+ @_generic MessageLevel.Warning, [].slice.call(arguments)
+
+ #---------------------------------------------------------------------------
+ dir: ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ dirxml: ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ trace: ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ assert: (condition) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ count: ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ markTimeline: (message) ->
+ Timeline.addRecord_Mark message
+
+ #---------------------------------------------------------------------------
+ lastWMLErrorMessage: ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ profile: (title) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ profileEnd: (title) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ time: (title) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ timeEnd: (title) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ group: ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ groupCollapsed: ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ groupEnd: ->
+ Weinre.notImplemented arguments.callee.signature
+
+#-------------------------------------------------------------------------------
+RemoteConsole = new Console()
+OriginalConsole = window.console
+
+RemoteConsole.__original = OriginalConsole
+OriginalConsole.__original = OriginalConsole
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/ElementHighlighter.coffee b/weinre.web/modules/weinre/target/ElementHighlighter.coffee
new file mode 100644
index 0000000..b1a7ccb
--- /dev/null
+++ b/weinre.web/modules/weinre/target/ElementHighlighter.coffee
@@ -0,0 +1,119 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Binding = require('../common/Binding')
+Weinre = require('../common/Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class ElementHighlighter
+
+ ElementHighlighter::__defineGetter__("element", -> @boxMargin)
+
+ constructor: ->
+ @boxMargin = document.createElement("div")
+ @boxBorder = document.createElement("div")
+ @boxPadding = document.createElement("div")
+ @boxContent = document.createElement("div")
+
+ @boxMargin.appendChild @boxBorder
+ @boxBorder.appendChild @boxPadding
+ @boxPadding.appendChild @boxContent
+
+ @boxMargin.style.backgroundColor = "#FCC"
+ @boxBorder.style.backgroundColor = "#000"
+ @boxPadding.style.backgroundColor = "#CFC"
+ @boxContent.style.backgroundColor = "#CCF"
+
+ @boxMargin.style.opacity = @boxBorder.style.opacity = @boxPadding.style.opacity = @boxContent.style.opacity = 0.6
+ @boxMargin.style.position = @boxBorder.style.position = @boxPadding.style.position = @boxContent.style.position = "absolute"
+ @boxMargin.style.borderWidth = @boxBorder.style.borderWidth = @boxPadding.style.borderWidth = @boxContent.style.borderWidth = "thin"
+ @boxMargin.style.borderStyle = @boxBorder.style.borderStyle = @boxPadding.style.borderStyle = @boxContent.style.borderStyle = "solid"
+ @boxMargin.__weinreHighlighter = @boxBorder.__weinreHighlighter = @boxPadding.__weinreHighlighter = @boxContent.__weinreHighlighter = true
+
+ @boxMargin.style.display = "none"
+ document.body.appendChild @boxMargin
+
+ #---------------------------------------------------------------------------
+ on: (element) ->
+ return if null == element
+ return unless element.nodeType == Node.ELEMENT_NODE
+
+ @calculateMetrics element
+ @boxMargin.style.display = "block"
+
+ #---------------------------------------------------------------------------
+ off: ->
+ @boxMargin.style.display = "none"
+
+ #---------------------------------------------------------------------------
+ calculateMetrics: (element) ->
+ metrics = getMetrics(element)
+
+ @boxMargin.style.top = metrics.y + "px"
+ @boxMargin.style.left = metrics.x + "px"
+ @boxMargin.style.height = metrics.height + "px"
+ @boxMargin.style.width = metrics.width + "px"
+ @boxBorder.style.top = metrics.marginTop + "px"
+ @boxBorder.style.left = metrics.marginLeft + "px"
+ @boxBorder.style.bottom = metrics.marginBottom + "px"
+ @boxBorder.style.right = metrics.marginRight + "px"
+ @boxPadding.style.top = metrics.borderTop + "px"
+ @boxPadding.style.left = metrics.borderLeft + "px"
+ @boxPadding.style.bottom = metrics.borderBottom + "px"
+ @boxPadding.style.right = metrics.borderRight + "px"
+ @boxContent.style.top = metrics.paddingTop + "px"
+ @boxContent.style.left = metrics.paddingLeft + "px"
+ @boxContent.style.bottom = metrics.paddingBottom + "px"
+ @boxContent.style.right = metrics.paddingRight + "px"
+
+#-------------------------------------------------------------------------------
+getMetrics = (element) ->
+ result = {}
+ left = 0
+ top = 0
+ el = element
+
+ loop
+ left += el.offsetLeft
+ top += el.offsetTop
+ break unless el = el.offsetParent
+
+ result.x = left
+ result.y = top
+
+ cStyle = document.defaultView.getComputedStyle(element)
+
+ result.width = fromPx(cStyle["width"])
+ result.height = fromPx(cStyle["height"])
+ result.marginLeft = fromPx(cStyle["margin-left"])
+ result.marginRight = fromPx(cStyle["margin-right"])
+ result.marginTop = fromPx(cStyle["margin-top"])
+ result.marginBottom = fromPx(cStyle["margin-bottom"])
+ result.borderLeft = fromPx(cStyle["border-left-width"])
+ result.borderRight = fromPx(cStyle["border-right-width"])
+ result.borderTop = fromPx(cStyle["border-top-width"])
+ result.borderBottom = fromPx(cStyle["border-bottom-width"])
+ result.paddingLeft = fromPx(cStyle["padding-left"])
+ result.paddingRight = fromPx(cStyle["padding-right"])
+ result.paddingTop = fromPx(cStyle["padding-top"])
+ result.paddingBottom = fromPx(cStyle["padding-bottom"])
+
+ result.width += result.marginLeft + result.marginRight + result.borderRight + result.paddingLeft + result.paddingRight
+ result.height += result.marginTop + result.marginBottom + result.borderBottom + result.paddingTop + result.paddingBottom
+
+ result.x -= result.marginLeft
+ result.y -= result.marginTop
+
+ result
+
+#-------------------------------------------------------------------------------
+fromPx = (string) ->
+ parseInt string.replace(/px$/, "")
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/InjectedScriptHostImpl.coffee b/weinre.web/modules/weinre/target/InjectedScriptHostImpl.coffee
new file mode 100644
index 0000000..a4ba59f
--- /dev/null
+++ b/weinre.web/modules/weinre/target/InjectedScriptHostImpl.coffee
@@ -0,0 +1,50 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class InjectedScriptHostImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ clearConsoleMessages: (callback) ->
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ nodeForId: (nodeId, callback) ->
+ Weinre.nodeStore.getNode nodeId
+
+ #---------------------------------------------------------------------------
+ pushNodePathToFrontend: (node, withChildren, selectInUI, callback) ->
+ nodeId = Weinre.nodeStore.getNodeId(node)
+ children = Weinre.nodeStore.serializeNode(node, 1)
+ Weinre.wi.DOMNotify.setChildNodes nodeId, children
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ inspectedNode: (num, callback) ->
+ nodeId = Weinre.nodeStore.getInspectedNode(num)
+ nodeId
+
+ #---------------------------------------------------------------------------
+ internalConstructorName: (object) ->
+ ctor = object.constructor
+ ctorName = ctor.fullClassName or ctor.displayName or ctor.name
+ return ctorName if ctorName and (ctorName != "Object")
+
+ pattern = /\[object (.*)\]/
+ match = pattern.exec(ctor.toString())
+
+ return match[1] if match
+
+ "Object"
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/NodeStore.coffee b/weinre.web/modules/weinre/target/NodeStore.coffee
new file mode 100644
index 0000000..edd0269
--- /dev/null
+++ b/weinre.web/modules/weinre/target/NodeStore.coffee
@@ -0,0 +1,219 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+IDGenerator = require('../common/IDGenerator')
+
+#-------------------------------------------------------------------------------
+module.exports = class NodeStore
+
+ constructor: ->
+ @__nodeMap = {}
+ @__nodeDataMap = {}
+ @inspectedNodes = []
+
+ document.addEventListener "DOMSubtreeModified", handleDOMSubtreeModified, false
+ document.addEventListener "DOMNodeInserted", handleDOMNodeInserted, false
+ document.addEventListener "DOMNodeRemoved", handleDOMNodeRemoved, false
+ document.addEventListener "DOMAttrModified", handleDOMAttrModified, false
+ document.addEventListener "DOMCharacterDataModified", handleDOMCharacterDataModified, false
+
+ #---------------------------------------------------------------------------
+ addInspectedNode: (nodeId) ->
+ @inspectedNodes.unshift nodeId
+ @inspectedNodes = @inspectedNodes.slice(0, 5) if @inspectedNodes.length > 5
+
+ #---------------------------------------------------------------------------
+ getInspectedNode: (index) ->
+ @inspectedNodes[index]
+
+ #---------------------------------------------------------------------------
+ getNode: (nodeId) ->
+ @__nodeMap[nodeId]
+
+ #---------------------------------------------------------------------------
+ checkNodeId: (node) ->
+ IDGenerator.checkId node
+
+ #---------------------------------------------------------------------------
+ getNodeId: (node) ->
+ id = @checkNodeId(node)
+ return id if id
+ IDGenerator.getId node, @__nodeMap
+
+ #---------------------------------------------------------------------------
+ getNodeData: (nodeId, depth) ->
+ @serializeNode @getNode(nodeId), depth
+
+ #---------------------------------------------------------------------------
+ getPreviousSiblingId: (node) ->
+ while true
+ sib = node.previousSibling
+ return 0 unless sib
+
+ id = @checkNodeId(sib)
+ return id if id
+
+ node = sib
+
+ #---------------------------------------------------------------------------
+ nextNodeId: () ->
+ "" + IDGenerator.next()
+
+ #---------------------------------------------------------------------------
+ serializeNode: (node, depth) ->
+ nodeName = ""
+ nodeValue = null
+ localName = null
+ id = @getNodeId(node)
+
+ switch node.nodeType
+
+ when Node.TEXT_NODE, Node.COMMENT_NODE, Node.CDATA_SECTION_NODE
+ nodeValue = node.nodeValue
+
+ when Node.ATTRIBUTE_NODE
+ localName = node.localName
+
+ when Node.DOCUMENT_FRAGMENT_NODE
+ break
+
+ else
+ nodeName = node.nodeName
+ localName = node.localName
+
+ nodeData =
+ id: id
+ nodeType: node.nodeType
+ nodeName: nodeName
+ localName: localName
+ nodeValue: nodeValue
+
+ if node.nodeType == Node.ELEMENT_NODE or node.nodeType == Node.DOCUMENT_NODE or node.nodeType == Node.DOCUMENT_FRAGMENT_NODE
+ nodeData.childNodeCount = @childNodeCount(node)
+ children = @serializeNodeChildren(node, depth)
+ nodeData.children = children if children.length
+
+ if node.nodeType == Node.ELEMENT_NODE
+ nodeData.attributes = []
+ i = 0
+
+ while i < node.attributes.length
+ nodeData.attributes.push node.attributes[i].nodeName
+ nodeData.attributes.push node.attributes[i].nodeValue
+ i++
+
+ else
+ if node.nodeType == Node.DOCUMENT_NODE
+ nodeData.documentURL = window.location.href
+
+ else if node.nodeType == Node.DOCUMENT_TYPE_NODE
+ nodeData.publicId = node.publicId
+ nodeData.systemId = node.systemId
+ nodeData.internalSubset = node.internalSubset
+
+ else if node.nodeType == Node.ATTRIBUTE_NODE
+ nodeData.name = node.nodeName
+ nodeData.value = node.nodeValue
+
+ nodeData
+
+ #---------------------------------------------------------------------------
+ serializeNodeChildren: (node, depth) ->
+ result = []
+ childIds = @childNodeIds(node)
+
+ if depth == 0
+ if childIds.length == 1
+ childNode = @getNode(childIds[0])
+ if childNode.nodeType == Node.TEXT_NODE
+ result.push @serializeNode(childNode)
+ return result
+
+ depth--
+ i = 0
+
+ while i < childIds.length
+ result.push @serializeNode(@getNode(childIds[i]), depth)
+ i++
+
+ result
+
+ #---------------------------------------------------------------------------
+ childNodeCount: (node) ->
+ @childNodeIds(node).length
+
+ #---------------------------------------------------------------------------
+ childNodeIds: (node) ->
+ ids = []
+ i = 0
+
+ for childNode in node.childNodes
+ continue if @isToBeSkipped(childNode)
+ ids.push @getNodeId(childNode)
+
+ ids
+
+ #---------------------------------------------------------------------------
+ isToBeSkipped: (node) ->
+ return true unless node
+ return true if node.__weinreHighlighter
+ return false unless node.nodeType == Node.TEXT_NODE
+
+ not not node.nodeValue.match(/^\s*$/)
+
+#-------------------------------------------------------------------------------
+handleDOMSubtreeModified = (event) ->
+ return unless event.attrChange
+ NodeStore.handleDOMAttrModified event
+
+#-------------------------------------------------------------------------------
+handleDOMNodeInserted = (event) ->
+ targetId = Weinre.nodeStore.checkNodeId(event.target)
+ parentId = Weinre.nodeStore.checkNodeId(event.relatedNode)
+
+ return unless parentId
+
+ child = Weinre.nodeStore.serializeNode(event.target, 0)
+ previous = Weinre.nodeStore.getPreviousSiblingId(event.target)
+ Weinre.wi.DOMNotify.childNodeInserted parentId, previous, child
+
+#-------------------------------------------------------------------------------
+handleDOMNodeRemoved = (event) ->
+ targetId = Weinre.nodeStore.checkNodeId(event.target)
+ parentId = Weinre.nodeStore.checkNodeId(event.relatedNode)
+ return unless parentId
+
+ if targetId
+ Weinre.wi.DOMNotify.childNodeRemoved parentId, targetId
+ else
+ childCount = Weinre.nodeStore.childNodeCount(event.relatedNode)
+ Weinre.wi.DOMNotify.childNodeCountUpdated parentId, childCount
+
+#-------------------------------------------------------------------------------
+handleDOMAttrModified = (event) ->
+ targetId = Weinre.nodeStore.checkNodeId(event.target)
+ return unless targetId
+ attrs = []
+ i = 0
+
+ while i < event.target.attributes.length
+ attrs.push event.target.attributes[i].name
+ attrs.push event.target.attributes[i].value
+ i++
+
+ Weinre.wi.DOMNotify.attributesUpdated targetId, attrs
+
+#-------------------------------------------------------------------------------
+handleDOMCharacterDataModified = (event) ->
+ targetId = Weinre.nodeStore.checkNodeId(event.target)
+ return unless targetId
+ Weinre.wi.DOMNotify.characterDataModified targetId, event.newValue
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/SqlStepper.coffee b/weinre.web/modules/weinre/target/SqlStepper.coffee
new file mode 100644
index 0000000..82b5997
--- /dev/null
+++ b/weinre.web/modules/weinre/target/SqlStepper.coffee
@@ -0,0 +1,91 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Binding = require('../common/Binding')
+
+#-------------------------------------------------------------------------------
+module.exports = class SqlStepper
+
+ constructor: (steps) ->
+ return new SqlStepper(steps) unless (this instanceof SqlStepper)
+
+ @__context = {}
+
+ context = @__context
+ context.steps = steps
+
+ #---------------------------------------------------------------------------
+ run: (db, errorCallback) ->
+ context = @__context
+ if context.hasBeenRun
+ throw new Ex(arguments, "stepper has already been run")
+
+ context.hasBeenRun = true
+ context.db = db
+ context.errorCallback = errorCallback
+ context.nextStep = 0
+ context.ourErrorCallback = new Binding(this, ourErrorCallback)
+ context.runStep = new Binding(this, runStep)
+
+ @executeSql = new Binding(this, executeSql)
+
+ db.transaction context.runStep
+
+ #---------------------------------------------------------------------------
+ @example: (db, id) ->
+ step1 = ->
+ @executeSql "SELECT name FROM sqlite_master WHERE type='table'"
+
+ step2 = (resultSet) ->
+ rows = resultSet.rows
+ result = []
+
+ i = 0
+ while i < rows.length
+ name = rows.item(i).name
+ if name == "__WebKitDatabaseInfoTable__"
+ i++
+ continue
+
+ result.push name
+ i++
+
+ console.log "[#{@id}] table names: " + result.join(", ")
+
+ errorCb = (sqlError) ->
+ console.log "[#{@id}] sql error:#{sqlError.code}: " + sqlError.message
+
+ stepper = new SqlStepper([ step1, step2 ])
+ stepper.id = id
+ stepper.run db, errorCb
+
+
+#-------------------------------------------------------------------------------
+executeSql = (statement, data) ->
+ context = @__context
+ context.tx.executeSql statement, data, context.runStep, context.ourErrorCallback
+
+#-------------------------------------------------------------------------------
+ourErrorCallback = (tx, sqlError) ->
+ context = @__context
+ context.errorCallback.call this, sqlError
+
+#-------------------------------------------------------------------------------
+runStep = (tx, resultSet) ->
+ context = @__context
+ return if context.nextStep >= context.steps.length
+
+ context.tx = tx
+ context.currentStep = context.nextStep
+ context.nextStep++
+
+ step = context.steps[context.currentStep]
+ step.call this, resultSet
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/Target.coffee b/weinre.web/modules/weinre/target/Target.coffee
new file mode 100644
index 0000000..130a05b
--- /dev/null
+++ b/weinre.web/modules/weinre/target/Target.coffee
@@ -0,0 +1,202 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Native = require('../common/Native')
+Ex = require('../common/Ex')
+Binding = require('../common/Binding')
+Callback = require('../common/Callback')
+MessageDispatcher = require('../common/MessageDispatcher')
+Weinre = require('../common/Weinre')
+
+CheckForProblems = require('./CheckForProblems')
+NodeStore = require('./NodeStore')
+CSSStore = require('./CSSStore')
+ElementHighlighter = require('./ElementHighlighter')
+InjectedScriptHostImpl = require('./InjectedScriptHostImpl')
+WeinreTargetEventsImpl = require('./WeinreTargetEventsImpl')
+WeinreExtraClientCommandsImpl = require('./WeinreExtraClientCommandsImpl')
+WiConsoleImpl = require('./WiConsoleImpl')
+WiCSSImpl = require('./WiCSSImpl')
+WiDatabaseImpl = require('./WiDatabaseImpl')
+WiDOMImpl = require('./WiDOMImpl')
+WiDOMStorageImpl = require('./WiDOMStorageImpl')
+WiInspectorImpl = require('./WiInspectorImpl')
+WiRuntimeImpl = require('./WiRuntimeImpl')
+
+#-------------------------------------------------------------------------------
+module.exports = class Target
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ @main: ->
+ CheckForProblems.check()
+ Weinre.target = new Target()
+ Weinre.target.initialize()
+
+ Weinre.addCSSProperties = addCSSProperties = (properties) ->
+ CSSStore.addCSSProperties properties
+
+ #----------------------------------------------------------------------------
+ setWeinreServerURLFromScriptSrc: (element) ->
+ return if window.WeinreServerURL
+
+ if element
+ pattern = /(http:\/\/(.*?)\/)/
+ match = pattern.exec(element.src)
+ if match
+ window.WeinreServerURL = match[1]
+ return
+
+ message = "unable to calculate the weinre server url; explicity set the variable window.WeinreServerURL instead"
+ alert message
+ throw new Ex(arguments, message)
+
+ #---------------------------------------------------------------------------
+ setWeinreServerIdFromScriptSrc: (element) ->
+ return if window.WeinreServerId
+
+ element = @getTargetScriptElement()
+ hash = "anonymous"
+
+ if element
+ attempt = element.src.split("#")[1]
+ if attempt
+ hash = attempt
+ else
+ attempt = location.hash.split("#")[1]
+ hash = attempt if attempt
+
+ window.WeinreServerId = hash
+
+ #---------------------------------------------------------------------------
+ getTargetScriptElement: ->
+ elements = document.getElementsByTagName("script")
+ scripts = [ "Target.", "target-script.", "target-script-min." ]
+ i = 0
+
+ while i < elements.length
+ element = elements[i]
+ j = 0
+ while j < scripts.length
+ return element unless -1 == element.src.indexOf("/" + scripts[j])
+ j++
+ i++
+
+ #---------------------------------------------------------------------------
+ initialize: () ->
+ self = this
+
+ element = @getTargetScriptElement()
+
+ @setWeinreServerURLFromScriptSrc element
+ @setWeinreServerIdFromScriptSrc element
+
+ window.WeinreServerURL += "/" unless window.WeinreServerURL[window.WeinreServerURL.length - 1] == "/"
+ injectedScriptHost = new InjectedScriptHostImpl()
+ Weinre.injectedScript = injectedScriptConstructor(injectedScriptHost, window, 0, "?")
+
+ window.addEventListener "load", Binding(this, "onLoaded"), false
+ document.addEventListener "DOMContentLoaded", Binding(this, "onDOMContent"), false
+
+ @_startTime = currentTime()
+ if document.readyState == "loaded"
+ setTimeout (->
+ self.onDOMContent()
+ ), 10
+
+ if document.readyState == "complete"
+ setTimeout (->
+ self.onDOMContent()
+ ), 10
+ setTimeout (->
+ self.onLoaded()
+ ), 20
+
+# MessageDispatcher.verbose(true)
+ messageDispatcher = new MessageDispatcher(window.WeinreServerURL + "ws/target", window.WeinreServerId)
+ Weinre.messageDispatcher = messageDispatcher
+
+ Weinre.wi = {}
+ Weinre.wi.Console = new WiConsoleImpl()
+ Weinre.wi.CSS = new WiCSSImpl()
+ Weinre.wi.Database = new WiDatabaseImpl()
+ Weinre.wi.DOM = new WiDOMImpl()
+ Weinre.wi.DOMStorage = new WiDOMStorageImpl()
+ Weinre.wi.Inspector = new WiInspectorImpl()
+ Weinre.wi.Runtime = new WiRuntimeImpl()
+
+ messageDispatcher.registerInterface "Console", Weinre.wi.Console, false
+ messageDispatcher.registerInterface "CSS", Weinre.wi.CSS, false
+ messageDispatcher.registerInterface "Database", Weinre.wi.Database, false
+ messageDispatcher.registerInterface "DOM", Weinre.wi.DOM, false
+ messageDispatcher.registerInterface "DOMStorage", Weinre.wi.DOMStorage, false
+ messageDispatcher.registerInterface "Inspector", Weinre.wi.Inspector, false
+ messageDispatcher.registerInterface "Runtime", Weinre.wi.Runtime, false
+
+ messageDispatcher.registerInterface "WeinreExtraClientCommands", new WeinreExtraClientCommandsImpl(), true
+ messageDispatcher.registerInterface "WeinreTargetEvents", new WeinreTargetEventsImpl(), true
+
+ Weinre.wi.ApplicationCacheNotify = messageDispatcher.createProxy("ApplicationCacheNotify")
+ Weinre.wi.ConsoleNotify = messageDispatcher.createProxy("ConsoleNotify")
+ Weinre.wi.DOMNotify = messageDispatcher.createProxy("DOMNotify")
+ Weinre.wi.DOMStorageNotify = messageDispatcher.createProxy("DOMStorageNotify")
+ Weinre.wi.DatabaseNotify = messageDispatcher.createProxy("DatabaseNotify")
+ Weinre.wi.InspectorNotify = messageDispatcher.createProxy("InspectorNotify")
+ Weinre.wi.TimelineNotify = messageDispatcher.createProxy("TimelineNotify")
+ Weinre.WeinreTargetCommands = messageDispatcher.createProxy("WeinreTargetCommands")
+ Weinre.WeinreExtraTargetEvents = messageDispatcher.createProxy("WeinreExtraTargetEvents")
+
+ messageDispatcher.getWebSocket().addEventListener "open", Binding(this, @cb_webSocketOpened)
+
+ Weinre.nodeStore = new NodeStore()
+ Weinre.cssStore = new CSSStore()
+
+ window.addEventListener "error", ((e) ->
+ Target.handleError e
+ ), false
+
+ #---------------------------------------------------------------------------
+ @handleError: (event) ->
+ filename = event.filename or "[unknown filename]"
+ lineno = event.lineno or "[unknown lineno]"
+ message = event.message or "[unknown message]"
+
+ Weinre.logError "error occurred: #{filename}:#{lineno}: " + message
+
+ #---------------------------------------------------------------------------
+ cb_webSocketOpened: () ->
+ Weinre.WeinreTargetCommands.registerTarget window.location.href, Binding(this, @cb_registerTarget)
+
+ #---------------------------------------------------------------------------
+ cb_registerTarget: (targetDescription) ->
+ Weinre.targetDescription = targetDescription
+
+ #---------------------------------------------------------------------------
+ onLoaded: ->
+ Weinre.wi.InspectorNotify.loadEventFired currentTime() - @_startTime
+
+ #---------------------------------------------------------------------------
+ onDOMContent: ->
+ Weinre.wi.InspectorNotify.domContentEventFired currentTime() - @_startTime
+
+ #---------------------------------------------------------------------------
+ setDocument: () ->
+ Weinre.elementHighlighter = new ElementHighlighter()
+
+ nodeId = Weinre.nodeStore.getNodeId(document)
+ nodeData = Weinre.nodeStore.getNodeData(nodeId, 2)
+ Weinre.wi.DOMNotify.setDocument nodeData
+
+#-------------------------------------------------------------------------------
+currentTime = () ->
+ (new Date().getMilliseconds()) / 1000.0
+
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/Timeline.coffee b/weinre.web/modules/weinre/target/Timeline.coffee
new file mode 100644
index 0000000..488f0e9
--- /dev/null
+++ b/weinre.web/modules/weinre/target/Timeline.coffee
@@ -0,0 +1,348 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Ex = require('../common/Ex')
+Weinre = require('../common/Weinre')
+IDGenerator = require('../common/IDGenerator')
+StackTrace = require('../common/StackTrace')
+Native = require('../common/Native')
+
+Running = false
+
+TimerTimeouts = {}
+TimerIntervals = {}
+
+TimelineRecordType =
+ EventDispatch: 0
+ Layout: 1
+ RecalculateStyles: 2
+ Paint: 3
+ ParseHTML: 4
+ TimerInstall: 5
+ TimerRemove: 6
+ TimerFire: 7
+ XHRReadyStateChange: 8
+ XHRLoad: 9
+ EvaluateScript: 10
+ Mark: 11
+ ResourceSendRequest: 12
+ ResourceReceiveResponse: 13
+ ResourceFinish: 14
+ FunctionCall: 15
+ ReceiveResourceData: 16
+ GCEvent: 17
+ MarkDOMContent: 18
+ MarkLoad: 19
+ ScheduleResourceRequest: 20
+
+
+#-------------------------------------------------------------------------------
+module.exports = class Timeline
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ @start: ->
+ Running = true
+
+ #---------------------------------------------------------------------------
+ @stop: ->
+ Running = false
+
+ #---------------------------------------------------------------------------
+ @isRunning: ->
+ Running
+
+ #---------------------------------------------------------------------------
+ @addRecord_Mark: (message) ->
+ return unless Timeline.isRunning()
+
+ record = {}
+ record.type = TimelineRecordType.Mark
+ record.category = name: "scripting"
+ record.startTime = Date.now()
+ record.data = message: message
+
+ addStackTrace record, 3
+
+ Weinre.wi.TimelineNotify.addRecordToTimeline record
+
+ #---------------------------------------------------------------------------
+ @addRecord_EventDispatch: (event, name, category) ->
+ return unless Timeline.isRunning()
+
+ category = "scripting" unless category
+ record = {}
+ record.type = TimelineRecordType.EventDispatch
+ record.category = name: category
+ record.startTime = Date.now()
+ record.data = type: event.type
+
+ Weinre.wi.TimelineNotify.addRecordToTimeline record
+
+ #---------------------------------------------------------------------------
+ @addRecord_TimerInstall: (id, timeout, singleShot) ->
+ return unless Timeline.isRunning()
+
+ record = {}
+ record.type = TimelineRecordType.TimerInstall
+ record.category = name: "scripting"
+ record.startTime = Date.now()
+ record.data =
+ timerId: id
+ timeout: timeout
+ singleShot: singleShot
+
+ addStackTrace record, 4
+
+ Weinre.wi.TimelineNotify.addRecordToTimeline record
+
+ #---------------------------------------------------------------------------
+ @addRecord_TimerRemove: (id, timeout, singleShot) ->
+ return unless Timeline.isRunning()
+
+ record = {}
+ record.type = TimelineRecordType.TimerRemove
+ record.category = name: "scripting"
+ record.startTime = Date.now()
+ record.data =
+ timerId: id
+ timeout: timeout
+ singleShot: singleShot
+
+ addStackTrace record, 4
+ Weinre.wi.TimelineNotify.addRecordToTimeline record
+
+ #---------------------------------------------------------------------------
+ @addRecord_TimerFire: (id, timeout, singleShot) ->
+ return unless Timeline.isRunning()
+
+ record = {}
+ record.type = TimelineRecordType.TimerFire
+ record.category = name: "scripting"
+ record.startTime = Date.now()
+ record.data =
+ timerId: id
+ timeout: timeout
+ singleShot: singleShot
+
+ Weinre.wi.TimelineNotify.addRecordToTimeline record
+
+ #---------------------------------------------------------------------------
+ @addRecord_XHRReadyStateChange: (method, url, id, xhr) ->
+ return unless Timeline.isRunning()
+
+ if xhr.readyState == XMLHttpRequest.OPENED
+ record =
+ type: TimelineRecordType.ResourceSendRequest
+ category: name: "loading"
+ startTime: Date.now()
+ data:
+ identifier: id
+ url: url
+ requestMethod: method
+
+ else if xhr.readyState == XMLHttpRequest.DONE
+ record =
+ type: TimelineRecordType.ResourceReceiveResponse
+ category: name: "loading"
+ startTime: Date.now()
+ data:
+ identifier: id
+ statusCode: xhr.status
+ mimeType: xhr.getResponseHeader("Content-Type")
+ expectedContentLength: xhr.getResponseHeader("Content-Length")
+ url: url
+ else
+ return
+
+ Weinre.wi.TimelineNotify.addRecordToTimeline record
+
+ #---------------------------------------------------------------------------
+ @installGlobalListeners: ->
+ if applicationCache
+ applicationCache.addEventListener "checking", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.checking", "loading"
+ ), false
+
+ applicationCache.addEventListener "error", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.error", "loading"
+ ), false
+
+ applicationCache.addEventListener "noupdate", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.noupdate", "loading"
+ ), false
+
+ applicationCache.addEventListener "downloading", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.downloading", "loading"
+ ), false
+
+ applicationCache.addEventListener "progress", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.progress", "loading"
+ ), false
+
+ applicationCache.addEventListener "updateready", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.updateready", "loading"
+ ), false
+
+ applicationCache.addEventListener "cached", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.cached", "loading"
+ ), false
+
+ applicationCache.addEventListener "obsolete", ((e) ->
+ Timeline.addRecord_EventDispatch e, "applicationCache.obsolete", "loading"
+ ), false
+
+ window.addEventListener "error", ((e) ->
+ Timeline.addRecord_EventDispatch e, "window.error"
+ ), false
+
+ window.addEventListener "hashchange", ((e) ->
+ Timeline.addRecord_EventDispatch e, "window.hashchange"
+ ), false
+
+ window.addEventListener "message", ((e) ->
+ Timeline.addRecord_EventDispatch e, "window.message"
+ ), false
+
+ window.addEventListener "offline", ((e) ->
+ Timeline.addRecord_EventDispatch e, "window.offline"
+ ), false
+
+ window.addEventListener "online", ((e) ->
+ Timeline.addRecord_EventDispatch e, "window.online"
+ ), false
+
+ window.addEventListener "scroll", ((e) ->
+ Timeline.addRecord_EventDispatch e, "window.scroll"
+ ), false
+
+ #---------------------------------------------------------------------------
+ @installFunctionWrappers: ->
+ window.clearInterval = wrapped_clearInterval
+ window.clearTimeout = wrapped_clearTimeout
+ window.setTimeout = wrapped_setTimeout
+ window.setInterval = wrapped_setInterval
+ window.XMLHttpRequest::open = wrapped_XMLHttpRequest_open
+ window.XMLHttpRequest = wrapped_XMLHttpRequest
+
+
+#-------------------------------------------------------------------------------
+addStackTrace = (record, skip) ->
+ skip = 1 unless skip
+ trace = new StackTrace(arguments).trace
+ record.stackTrace = []
+ i = skip
+
+ while i < trace.length
+ record.stackTrace.push
+ functionName: trace[i]
+ scriptName: ""
+ lineNumber: ""
+ i++
+
+#-------------------------------------------------------------------------------
+wrapped_setInterval = (code, interval) ->
+ code = instrumentedTimerCode(code, interval, false)
+
+ id = Native.setInterval(code, interval)
+ code.__timerId = id
+ addTimer id, interval, false
+
+ id
+
+#-------------------------------------------------------------------------------
+wrapped_setTimeout = (code, delay) ->
+ code = instrumentedTimerCode(code, delay, true)
+
+ id = Native.setTimeout(code, delay)
+ code.__timerId = id
+ addTimer id, delay, true
+
+ id
+
+#-------------------------------------------------------------------------------
+wrapped_clearInterval = (id) ->
+ result = Native.clearInterval(id)
+ removeTimer id, false
+
+ result
+
+#-------------------------------------------------------------------------------
+wrapped_clearTimeout = (id) ->
+ result = Native.clearTimeout(id)
+ removeTimer id, true
+
+ result
+
+#-------------------------------------------------------------------------------
+addTimer = (id, timeout, singleShot) ->
+ timerSet = (if singleShot then TimerTimeouts else TimerIntervals)
+
+ timerSet[id] =
+ id: id
+ timeout: timeout
+ singleShot: singleShot
+
+ Timeline.addRecord_TimerInstall id, timeout, singleShot
+
+#-------------------------------------------------------------------------------
+removeTimer = (id, singleShot) ->
+ timerSet = (if singleShot then TimerTimeouts else TimerIntervals)
+ timer = timerSet[id]
+ return unless timer
+
+ Timeline.addRecord_TimerRemove id, timer.timeout, singleShot
+ delete timerSet[id]
+
+#-------------------------------------------------------------------------------
+instrumentedTimerCode = (code, timeout, singleShot) ->
+ return code unless typeof (code) == "function"
+
+ instrumentedCode = ->
+ result = code()
+ id = arguments.callee.__timerId
+ Timeline.addRecord_TimerFire id, timeout, singleShot
+ result
+
+ instrumentedCode
+
+#-------------------------------------------------------------------------------
+wrapped_XMLHttpRequest = () ->
+ xhr = new Native.XMLHttpRequest()
+ IDGenerator.getId xhr
+ xhr.addEventListener "readystatechange", getXhrEventHandler(xhr), false
+ xhr
+
+wrapped_XMLHttpRequest.UNSENT = 0
+wrapped_XMLHttpRequest.OPENED = 1
+wrapped_XMLHttpRequest.HEADERS_RECEIVED = 2
+wrapped_XMLHttpRequest.LOADING = 3
+wrapped_XMLHttpRequest.DONE = 4
+
+#-------------------------------------------------------------------------------
+wrapped_XMLHttpRequest_open = () ->
+ xhr = this
+
+ xhr.__weinre_method = arguments[0]
+ xhr.__weinre_url = arguments[1]
+ result = Native.XMLHttpRequest_open.apply(xhr, [].slice.call(arguments))
+
+ result
+
+#-------------------------------------------------------------------------------
+getXhrEventHandler = (xhr) ->
+ (event) ->
+ Timeline.addRecord_XHRReadyStateChange xhr.__weinre_method, xhr.__weinre_url, IDGenerator.getId(xhr), xhr
+
+#-------------------------------------------------------------------------------
+Timeline.installGlobalListeners()
+Timeline.installFunctionWrappers()
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.coffee b/weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.coffee
new file mode 100644
index 0000000..e638355
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WeinreExtraClientCommandsImpl.coffee
@@ -0,0 +1,27 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+WiDatabaseImpl = require('./WiDatabaseImpl')
+Console = require('./Console')
+
+#-------------------------------------------------------------------------------
+module.exports = class WeinreExtraClientCommandsImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ getDatabases: (callback) ->
+ return unless callback
+ result = WiDatabaseImpl.getDatabases()
+
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
+
diff --git a/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.coffee b/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.coffee
new file mode 100644
index 0000000..65bb187
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.coffee
@@ -0,0 +1,40 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+Callback = require('../common/Callback')
+Console = require('./Console')
+
+#-------------------------------------------------------------------------------
+module.exports = class WeinreTargetEventsImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ connectionCreated: (clientChannel, targetChannel) ->
+ message = "weinre: target #{targetChannel} connected to client " + clientChannel
+ Weinre.logInfo message
+
+ oldValue = Console.useRemote(true)
+ Weinre.target.setDocument()
+ Weinre.wi.TimelineNotify.timelineProfilerWasStopped()
+ Weinre.wi.DOMStorage.initialize()
+
+ #---------------------------------------------------------------------------
+ connectionDestroyed: (clientChannel, targetChannel) ->
+ message = "weinre: target #{targetChannel} disconnected from client " + clientChannel
+ Weinre.logInfo message
+
+ oldValue = Console.useRemote(false)
+
+ #---------------------------------------------------------------------------
+ sendCallback: (callbackId, result) ->
+ Callback.invoke callbackId, result
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WiCSSImpl.coffee b/weinre.web/modules/weinre/target/WiCSSImpl.coffee
new file mode 100644
index 0000000..e12efde
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WiCSSImpl.coffee
@@ -0,0 +1,122 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class WiCSSImpl
+
+ constructor: ->
+ @dummyComputedStyle = false
+
+ #---------------------------------------------------------------------------
+ getStylesForNode: (nodeId, callback) ->
+ result = {}
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ if @dummyComputedStyle
+ computedStyle =
+ styleId: null
+ properties: []
+ shorthandValues: []
+ cssProperties: []
+ else
+ computedStyle = Weinre.cssStore.getComputedStyle(node)
+
+ result =
+ inlineStyle: Weinre.cssStore.getInlineStyle(node)
+ computedStyle: computedStyle
+ matchedCSSRules: Weinre.cssStore.getMatchedCSSRules(node)
+ styleAttributes: Weinre.cssStore.getStyleAttributes(node)
+ pseudoElements: Weinre.cssStore.getPseudoElements(node)
+ inherited: []
+
+ parentNode = node.parentNode
+ while parentNode
+ parentStyle =
+ inlineStyle: Weinre.cssStore.getInlineStyle(parentNode)
+ matchedCSSRules: Weinre.cssStore.getMatchedCSSRules(parentNode)
+
+ result.inherited.push parentStyle
+ parentNode = parentNode.parentNode
+
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ getComputedStyleForNode: (nodeId, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ result = Weinre.cssStore.getComputedStyle(node)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ getInlineStyleForNode: (nodeId, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ result = Weinre.cssStore.getInlineStyle(node)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ getAllStyles: (callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ getStyleSheet: (styleSheetId, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ getStyleSheetText: (styleSheetId, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ setStyleSheetText: (styleSheetId, text, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ setPropertyText: (styleId, propertyIndex, text, overwrite, callback) ->
+ result = Weinre.cssStore.setPropertyText(styleId, propertyIndex, text, overwrite)
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ] if callback
+
+ #---------------------------------------------------------------------------
+ toggleProperty: (styleId, propertyIndex, disable, callback) ->
+ result = Weinre.cssStore.toggleProperty(styleId, propertyIndex, disable)
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ] if callback
+
+ #---------------------------------------------------------------------------
+ setRuleSelector: (ruleId, selector, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ addRule: (contextNodeId, selector, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ getSupportedCSSProperties: (callback) ->
+ Weinre.getCSSProperties()
+
+ #---------------------------------------------------------------------------
+ querySelectorAll: (documentId, selector, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WiConsoleImpl.coffee b/weinre.web/modules/weinre/target/WiConsoleImpl.coffee
new file mode 100644
index 0000000..35ab3f7
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WiConsoleImpl.coffee
@@ -0,0 +1,36 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class WiConsoleImpl
+
+ constructor: ->
+ @messagesEnabled = true
+
+ #---------------------------------------------------------------------------
+ setConsoleMessagesEnabled: (enabled, callback) ->
+ oldValue = @messagesEnabled
+ @messagesEnabled = enabled
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ oldValue ]
+
+ #---------------------------------------------------------------------------
+ clearConsoleMessages: (callback) ->
+ Weinre.wi.ConsoleNotify.consoleMessagesCleared()
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, []
+
+ #---------------------------------------------------------------------------
+ setMonitoringXHREnabled: (enabled, callback) ->
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, []
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WiDOMImpl.coffee b/weinre.web/modules/weinre/target/WiDOMImpl.coffee
new file mode 100644
index 0000000..675b5b9
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WiDOMImpl.coffee
@@ -0,0 +1,155 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class WiDOMImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ getChildNodes: (nodeId, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ children = Weinre.nodeStore.serializeNodeChildren(node, 1)
+ Weinre.wi.DOMNotify.setChildNodes nodeId, children
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ setAttribute: (elementId, name, value, callback) ->
+ element = Weinre.nodeStore.getNode(elementId)
+
+ unless element
+ Weinre.logWarning arguments.callee.signature + " passed an invalid elementId: " + elementId
+ return
+
+ element.setAttribute name, value
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ removeAttribute: (elementId, name, callback) ->
+ element = Weinre.nodeStore.getNode(elementId)
+
+ unless element
+ Weinre.logWarning arguments.callee.signature + " passed an invalid elementId: " + elementId
+ return
+
+ element.removeAttribute name
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ setTextNodeValue: (nodeId, value, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ node.nodeValue = value
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ getEventListenersForNode: (nodeId, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ copyNode: (nodeId, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ removeNode: (nodeId, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ unless node.parentNode
+ Weinre.logWarning arguments.callee.signature + " passed a parentless node: " + node
+ return
+
+ node.parentNode.removeChild node
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ changeTagName: (nodeId, newTagName, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ getOuterHTML: (nodeId, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ value = node.outerHTML
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ value ]
+
+ #---------------------------------------------------------------------------
+ setOuterHTML: (nodeId, outerHTML, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ node.outerHTML = outerHTML
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ addInspectedNode: (nodeId, callback) ->
+ Weinre.nodeStore.addInspectedNode nodeId
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ performSearch: (query, runSynchronously, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ searchCanceled: (callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ pushNodeByPathToFrontend: (path, callback) ->
+ Weinre.notImplemented arguments.callee.signature
+
+ #---------------------------------------------------------------------------
+ resolveNode: (nodeId, callback) ->
+ result = Weinre.injectedScript.resolveNode(nodeId)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ getNodeProperties: (nodeId, propertiesArray, callback) ->
+ propertiesArray = JSON.stringify(propertiesArray)
+ result = Weinre.injectedScript.getNodeProperties(nodeId, propertiesArray)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ getNodePrototypes: (nodeId, callback) ->
+ result = Weinre.injectedScript.getNodePrototypes(nodeId)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ pushNodeToFrontend: (objectId, callback) ->
+ objectId = JSON.stringify(objectId)
+ result = Weinre.injectedScript.pushNodeToFrontend(objectId)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WiDOMStorageImpl.coffee b/weinre.web/modules/weinre/target/WiDOMStorageImpl.coffee
new file mode 100644
index 0000000..23ef0ad
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WiDOMStorageImpl.coffee
@@ -0,0 +1,137 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+Native = require('../common/Native')
+
+#-------------------------------------------------------------------------------
+module.exports = class WiDOMStorageImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ getDOMStorageEntries: (storageId, callback) ->
+ storageArea = _getStorageArea(storageId)
+
+ unless storageArea
+ Weinre.logWarning arguments.callee.signature + " passed an invalid storageId: " + storageId
+ return
+
+ result = []
+ length = storageArea.length
+ i = 0
+
+ while i < length
+ key = storageArea.key(i)
+ val = storageArea.getItem(key)
+ result.push [ key, val ]
+ i++
+
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ setDOMStorageItem: (storageId, key, value, callback) ->
+ storageArea = _getStorageArea(storageId)
+
+ unless storageArea
+ Weinre.logWarning arguments.callee.signature + " passed an invalid storageId: " + storageId
+ return
+
+ result = true
+ try
+ if storageArea == window.localStorage
+ Native.LocalStorage_setItem key, value
+ else Native.SessionStorage_setItem key, value if storageArea == window.sessionStorage
+ catch e
+ result = false
+
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ removeDOMStorageItem: (storageId, key, callback) ->
+ storageArea = _getStorageArea(storageId)
+
+ unless storageArea
+ Weinre.logWarning arguments.callee.signature + " passed an invalid storageId: " + storageId
+ return
+
+ result = true
+ try
+ if storageArea == window.localStorage
+ Native.LocalStorage_removeItem key
+ else
+ if storageArea == window.sessionStorage
+ Native.SessionStorage_removeItem key
+ catch e
+ result = false
+
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ] if callback
+
+ #---------------------------------------------------------------------------
+ initialize: ->
+ if window.localStorage
+ Weinre.wi.DOMStorageNotify.addDOMStorage
+ id: 1
+ host: window.location.host
+ isLocalStorage: true
+
+ window.localStorage.setItem = (key, value) ->
+ Native.LocalStorage_setItem key, value
+ _storageEventHandler storageArea: window.localStorage
+
+ window.localStorage.removeItem = (key) ->
+ Native.LocalStorage_removeItem key
+ _storageEventHandler storageArea: window.localStorage
+
+ window.localStorage.clear = ->
+ Native.LocalStorage_clear()
+ _storageEventHandler storageArea: window.localStorage
+
+ if window.sessionStorage
+ Weinre.wi.DOMStorageNotify.addDOMStorage
+ id: 2
+ host: window.location.host
+ isLocalStorage: false
+
+ window.sessionStorage.setItem = (key, value) ->
+ Native.SessionStorage_setItem key, value
+ _storageEventHandler storageArea: window.sessionStorage
+
+ window.sessionStorage.removeItem = (key) ->
+ Native.SessionStorage_removeItem key
+ _storageEventHandler storageArea: window.sessionStorage
+
+ window.sessionStorage.clear = ->
+ Native.SessionStorage_clear()
+ _storageEventHandler storageArea: window.sessionStorage
+
+ document.addEventListener "storage", _storageEventHandler, false
+
+#-------------------------------------------------------------------------------
+_getStorageArea = (storageId) ->
+ if storageId == 1
+ return window.localStorage
+ else return window.sessionStorage if storageId == 2
+
+ null
+
+#-------------------------------------------------------------------------------
+_storageEventHandler = (event) ->
+ if event.storageArea == window.localStorage
+ storageId = 1
+ else if event.storageArea == window.sessionStorage
+ storageId = 2
+ else
+ return
+
+ Weinre.wi.DOMStorageNotify.updateDOMStorage storageId
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WiDatabaseImpl.coffee b/weinre.web/modules/weinre/target/WiDatabaseImpl.coffee
new file mode 100644
index 0000000..e458615
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WiDatabaseImpl.coffee
@@ -0,0 +1,158 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+Native = require('../common/Native')
+IDGenerator = require('../common/IDGenerator')
+SqlStepper = require('./SqlStepper')
+
+id2db = {}
+name2db = {}
+
+#-------------------------------------------------------------------------------
+module.exports = class WiDatabaseImpl
+
+ constructor: ->
+ return unless window.openDatabase
+ window.openDatabase = wrappedOpenDatabase
+
+ #---------------------------------------------------------------------------
+ @getDatabases: ->
+ result = []
+ for id of id2db
+ result.push id2db[id]
+ result
+
+ #---------------------------------------------------------------------------
+ getDatabaseTableNames: (databaseId, callback) ->
+ db = dbById(databaseId)
+ return unless db
+
+ stepper = SqlStepper([ getTableNames_step_1, getTableNames_step_2 ])
+ stepper.callback = callback
+ stepper.run db, logSqlError
+
+ #---------------------------------------------------------------------------
+ executeSQL: (databaseId, query, callback) ->
+ db = dbById(databaseId)
+ return unless db
+
+ txid = Weinre.targetDescription.channel + "-" + IDGenerator.next()
+
+ stepper = SqlStepper([ executeSQL_step_1, executeSQL_step_2 ])
+ stepper.txid = txid
+ stepper.query = query
+ stepper.callback = callback
+
+ stepper.run db, executeSQL_error
+
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ true, txid ]
+
+#-------------------------------------------------------------------------------
+logSqlError = (sqlError) ->
+ console.log "SQL Error #{sqlError.code}: " + sqlError.message
+
+#-------------------------------------------------------------------------------
+getTableNames_step_1 = () ->
+ @executeSql "SELECT name FROM sqlite_master WHERE type='table'"
+
+#-------------------------------------------------------------------------------
+getTableNames_step_2 = (resultSet) ->
+ rows = resultSet.rows
+ result = []
+
+ i = 0
+ while i < rows.length
+ name = rows.item(i).name
+ if name == "__WebKitDatabaseInfoTable__"
+ i++
+ continue
+
+ result.push name
+ i++
+
+ Weinre.WeinreTargetCommands.sendClientCallback @callback, [ result ]
+
+#-------------------------------------------------------------------------------
+executeSQL_step_1 = () ->
+ @executeSql @query
+
+#-------------------------------------------------------------------------------
+executeSQL_step_2 = (resultSet) ->
+ columnNames = []
+ values = []
+ rows = resultSet.rows
+ i = 0
+
+ while i < rows.length
+ row = rows.item(i)
+ if i == 0
+ for propName of row
+ columnNames.push propName
+ j = 0
+
+ while j < columnNames.length
+ values.push row[columnNames[j]]
+ j++
+ i++
+
+ Weinre.wi.DatabaseNotify.sqlTransactionSucceeded @txid, columnNames, values
+
+#-------------------------------------------------------------------------------
+executeSQL_error = (sqlError) ->
+ error =
+ code: sqlError.code
+ message: sqlError.message
+
+ Weinre.wi.DatabaseNotify.sqlTransactionFailed @txid, error
+
+#-------------------------------------------------------------------------------
+wrappedOpenDatabase = (name, version, displayName, estimatedSize, creationCallback) ->
+ db = Native.openDatabase(name, version, displayName, estimatedSize, creationCallback)
+ dbAdd db, name, version
+ db
+
+#-------------------------------------------------------------------------------
+dbById = (id) ->
+ record = id2db[id]
+ return null unless record
+ record.db
+
+#-------------------------------------------------------------------------------
+dbRecordById = (id) ->
+ id2db[id]
+
+#-------------------------------------------------------------------------------
+dbRecordByName = (name) ->
+ name2db[name]
+
+#-------------------------------------------------------------------------------
+dbAdd = (db, name, version) ->
+ record = dbRecordByName(name)
+ return record if record
+
+ record = {}
+ record.id = IDGenerator.next()
+ record.domain = window.location.origin
+ record.name = name
+ record.version = version
+ record.db = db
+
+ id2db[record.id] = record
+ name2db[name] = record
+
+ payload = {}
+ payload.id = record.id
+ payload.domain = record.domain
+ payload.name = name
+ payload.version = version
+ Weinre.WeinreExtraTargetEvents.databaseOpened payload
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WiInspectorImpl.coffee b/weinre.web/modules/weinre/target/WiInspectorImpl.coffee
new file mode 100644
index 0000000..daef844
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WiInspectorImpl.coffee
@@ -0,0 +1,51 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+Timeline = require('../target/Timeline')
+
+#-------------------------------------------------------------------------------
+module.exports = class WiInspectorImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ reloadPage: (callback) ->
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+ window.location.reload()
+
+ #---------------------------------------------------------------------------
+ highlightDOMNode: (nodeId, callback) ->
+ node = Weinre.nodeStore.getNode(nodeId)
+
+ unless node
+ Weinre.logWarning arguments.callee.signature + " passed an invalid nodeId: " + nodeId
+ return
+
+ Weinre.elementHighlighter.on node
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ hideDOMNodeHighlight: (callback) ->
+ Weinre.elementHighlighter.off()
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ startTimelineProfiler: (callback) ->
+ Timeline.start()
+ Weinre.wi.TimelineNotify.timelineProfilerWasStarted()
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+ #---------------------------------------------------------------------------
+ stopTimelineProfiler: (callback) ->
+ Timeline.stop()
+ Weinre.wi.TimelineNotify.timelineProfilerWasStopped()
+ Weinre.WeinreTargetCommands.sendClientCallback callback if callback
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)
diff --git a/weinre.web/modules/weinre/target/WiRuntimeImpl.coffee b/weinre.web/modules/weinre/target/WiRuntimeImpl.coffee
new file mode 100644
index 0000000..14c2e77
--- /dev/null
+++ b/weinre.web/modules/weinre/target/WiRuntimeImpl.coffee
@@ -0,0 +1,49 @@
+
+#---------------------------------------------------------------------------------
+# 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
+#---------------------------------------------------------------------------------
+
+Weinre = require('../common/Weinre')
+
+#-------------------------------------------------------------------------------
+module.exports = class WiRuntimeImpl
+
+ constructor: ->
+
+ #---------------------------------------------------------------------------
+ evaluate: (expression, objectGroup, includeCommandLineAPI, callback) ->
+ result = Weinre.injectedScript.evaluate(expression, objectGroup, includeCommandLineAPI)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ getCompletions: (expression, includeCommandLineAPI, callback) ->
+ result = Weinre.injectedScript.getCompletions(expression, includeCommandLineAPI)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ getProperties: (objectId, ignoreHasOwnProperty, abbreviate, callback) ->
+ objectId = JSON.stringify(objectId)
+ result = Weinre.injectedScript.getProperties(objectId, ignoreHasOwnProperty, abbreviate)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ setPropertyValue: (objectId, propertyName, expression, callback) ->
+ objectId = JSON.stringify(objectId)
+ result = Weinre.injectedScript.setPropertyValue(objectId, propertyName, expression)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+ #---------------------------------------------------------------------------
+ releaseWrapperObjectGroup: (injectedScriptId, objectGroup, callback) ->
+ result = Weinre.injectedScript.releaseWrapperObjectGroup(objectGroupName)
+ if callback
+ Weinre.WeinreTargetCommands.sendClientCallback callback, [ result ]
+
+#-------------------------------------------------------------------------------
+require("../common/MethodNamer").setNamesForClass(module.exports)