You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devicemap.apache.org by bd...@apache.org on 2012/05/31 17:19:09 UTC
svn commit: r1344766 - in /incubator/devicemap/trunk/prototypes/probefilter:
./ src/ src/main/ src/main/java/ src/main/java/org/
src/main/java/org/apache/ src/main/java/org/apache/devicemap/
src/main/java/org/apache/devicemap/probefilter/ src/main/java...
Author: bdelacretaz
Date: Thu May 31 15:19:08 2012
New Revision: 1344766
URL: http://svn.apache.org/viewvc?rev=1344766&view=rev
Log:
dynamic probes prototype
Added:
incubator/devicemap/trunk/prototypes/probefilter/ (with props)
incubator/devicemap/trunk/prototypes/probefilter/README.md
incubator/devicemap/trunk/prototypes/probefilter/pom.xml
incubator/devicemap/trunk/prototypes/probefilter/src/
incubator/devicemap/trunk/prototypes/probefilter/src/main/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/filter/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/filter/DeviceMapProbeFilter.java
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/Main.java
incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/TestServlet.java
incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/
incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_demo.html
incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_probe.html
Propchange: incubator/devicemap/trunk/prototypes/probefilter/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu May 31 15:19:08 2012
@@ -0,0 +1,10 @@
+target
+bin
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
Added: incubator/devicemap/trunk/prototypes/probefilter/README.md
URL: http://svn.apache.org/viewvc/incubator/devicemap/trunk/prototypes/probefilter/README.md?rev=1344766&view=auto
==============================================================================
--- incubator/devicemap/trunk/prototypes/probefilter/README.md (added)
+++ incubator/devicemap/trunk/prototypes/probefilter/README.md Thu May 31 15:19:08 2012
@@ -0,0 +1,39 @@
+# Apache DeviceMap dynamic probes prototype
+
+To run this, build the jar file with "mvn clean install", run it
+with java -jar and open http://localhost:8085.
+
+I have created this prototype to experiment with a device detection
+technique similar to that of http://detector.dmolsen.com/ and
+https://github.com/yiibu/profile (though much less complete so far).
+
+The scenario is as follows:
+
+1. When a request comes in, check if it has a DMAP_p cookie.
+
+2. If yes, let the request go through. The contents of the DMAP_p
+ cookie describe the device features, and can be used both
+ on the server and client sides.
+
+3. If the cookie is not present, redirect to a "dynamic probes"
+ page, which runs javascript code to detect client features,
+ sets the DMAP_p cookie with the results, and redirects
+ to the originally requested page (path is passed as an URL
+ parameter).
+
+That's it - the hard part is in the javascript features detection
+code, in this first version that's extremely basic, just to
+demonstrate the idea. We might use modernizr and platform.js
+(and/or share detection code with the above projets that inspired
+this experiment) for more complete features detection.
+
+TODO:
+
+Implement more realistic/complete features detection code.
+
+Cache DMAP_p values based on user-agent (or digest of that).
+Maybe differentiate between "static" values that are tied to
+the device, and "context" values like window size which can
+change due to orientation or resizing.
+
+Maybe define an exchange format for such cached values.
\ No newline at end of file
Added: incubator/devicemap/trunk/prototypes/probefilter/pom.xml
URL: http://svn.apache.org/viewvc/incubator/devicemap/trunk/prototypes/probefilter/pom.xml?rev=1344766&view=auto
==============================================================================
--- incubator/devicemap/trunk/prototypes/probefilter/pom.xml (added)
+++ incubator/devicemap/trunk/prototypes/probefilter/pom.xml Thu May 31 15:19:08 2012
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE- 2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache</groupId>
+ <artifactId>apache</artifactId>
+ <version>9</version>
+ <relativePath />
+ </parent>
+
+ <groupId>org.apache.devicemap</groupId>
+ <artifactId>probefilter</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>probefilter</name>
+ <url>http://incubator.apache.org/devicemap</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <!-- Unpack required dependencies to include them and
+ make our jar self-containing -->
+ <execution>
+ <id>unpack-jetty</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <includeGroupIds>commons-io,org.mortbay.jetty,org.slf4j</includeGroupIds>
+ <excludeTransitive>false</excludeTransitive>
+ <outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>false</overWriteSnapshots>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.apache.devicemap.probefilter.testserver.Main</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>6.1.25</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.5.2</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
Added: incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/filter/DeviceMapProbeFilter.java
URL: http://svn.apache.org/viewvc/incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/filter/DeviceMapProbeFilter.java?rev=1344766&view=auto
==============================================================================
--- incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/filter/DeviceMapProbeFilter.java (added)
+++ incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/filter/DeviceMapProbeFilter.java Thu May 31 15:19:08 2012
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.devicemap.probefilter.filter;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Servlet Filter that handles the DeviceMap dynamic probe logic:
+ *
+ * If a request comes without a DMAP_p cookie, redirect to the probing
+ * page which will run javascript features detection code and set
+ * that cookie. That page is expected to redirect to the originally
+ * requested page when done running the probes.
+ *
+ * TODO: we might want to cache results based on previous requests
+ * coming from the same user-agent. http://detector.dmolsen.com/ uses
+ * *digests* of the User-Agent strings for that, might be a good idea
+ * to avoid privacy concerns if that info is shared.
+ *
+ * TODO: we might want to store the devicemap data in a request
+ * attribute to make it easy to access downstream.
+ *
+ */
+public class DeviceMapProbeFilter implements Filter {
+
+ public static final String COOKIE_NAME = "DMAP_p";
+ public static final String FORCE_PARAM = "DMAP_force";
+ public static final String PROBE_PATH = "DMAP_probe.html";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ public void init(FilterConfig cfg) throws ServletException {
+ }
+
+ public void destroy() {
+ }
+
+ public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain)
+ throws IOException, ServletException {
+
+ final HttpServletRequest request = (HttpServletRequest)sreq;
+ final HttpServletResponse response = (HttpServletResponse)sresp;
+
+ final Cookie c = getCookie(request, COOKIE_NAME);
+ if(request.getParameter(FORCE_PARAM) != null) {
+ log.info("Sending {} due to {}", PROBE_PATH, FORCE_PARAM);
+ sendProbe(request, response);
+ } else if(c == null) {
+ // TODO watch for infinite loop...
+ if(request.getPathInfo().endsWith("/" + PROBE_PATH)) {
+ log.info("Sending {}", PROBE_PATH);
+ sendProbe(request, response);
+ } else {
+ log.info("No {} cookie in request, redirect to {}", COOKIE_NAME, PROBE_PATH);
+ final String nextPath = request.getPathInfo();
+ response.sendRedirect(request.getContextPath() + PROBE_PATH + "?next=" + URLEncoder.encode(nextPath, "UTF-8"));
+ }
+ } else {
+ log.info("Got {}={}", c.getName(), c.getValue());
+ chain.doFilter(sreq, sresp);
+ }
+ }
+
+ private Cookie getCookie(HttpServletRequest r, String name) {
+ final Cookie [] cookies = r.getCookies();
+ if(cookies != null) {
+ for(Cookie c : cookies) {
+ if(name.equals(c.getName())) {
+ return c;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void sendProbe(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ // TODO probe is a static page for now, we might want to build it from components/plugins
+ final String resourcePath = "/dmap_probe.html";
+ final InputStream page = getClass().getResourceAsStream(resourcePath);
+ if(page == null) {
+ throw new IOException("Resource not found: " + resourcePath);
+ }
+ response.setContentType("text/html");
+ response.setCharacterEncoding("UTF-8");
+ IOUtils.copy(page, response.getOutputStream());
+ response.getOutputStream().flush();
+ }
+}
Added: incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/Main.java
URL: http://svn.apache.org/viewvc/incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/Main.java?rev=1344766&view=auto
==============================================================================
--- incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/Main.java (added)
+++ incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/Main.java Thu May 31 15:19:08 2012
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.devicemap.probefilter.testserver;
+
+import org.apache.devicemap.probefilter.filter.DeviceMapProbeFilter;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.FilterHolder;
+import org.mortbay.jetty.servlet.ServletHolder;
+
+/** Starts the test servlet + filter */
+public class Main {
+ public static final String DEFAULT_PORT = "8085";
+
+ public static void main(String [] args) throws Exception {
+ final String portStr = args.length > 0 ? args[0] : DEFAULT_PORT;
+ final int port = Integer.parseInt(portStr);
+
+ Server server = new Server(port);
+ Context root = new Context(server,"/",Context.SESSIONS);
+ root.addServlet(new ServletHolder(new TestServlet()), "/*");
+
+ // TODO not sure what this value means
+ final int dispatches = 1;
+ root.addFilter(new FilterHolder(new DeviceMapProbeFilter()), "/*", dispatches);
+ server.start();
+ }
+}
Added: incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/TestServlet.java
URL: http://svn.apache.org/viewvc/incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/TestServlet.java?rev=1344766&view=auto
==============================================================================
--- incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/TestServlet.java (added)
+++ incubator/devicemap/trunk/prototypes/probefilter/src/main/java/org/apache/devicemap/probefilter/testserver/TestServlet.java Thu May 31 15:19:08 2012
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.devicemap.probefilter.testserver;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+
+/** Stupid servlet that displays an information page */
+public class TestServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ final String resourcePath = "/dmap_demo.html";
+ final InputStream page = getClass().getResourceAsStream(resourcePath);
+ if(page == null) {
+ throw new IOException("Resource not found: " + resourcePath);
+ }
+ response.setContentType("text/html");
+ response.setCharacterEncoding("UTF-8");
+ IOUtils.copy(page, response.getOutputStream());
+ response.getOutputStream().flush();
+ }
+}
Added: incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_demo.html
URL: http://svn.apache.org/viewvc/incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_demo.html?rev=1344766&view=auto
==============================================================================
--- incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_demo.html (added)
+++ incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_demo.html Thu May 31 15:19:08 2012
@@ -0,0 +1,114 @@
+<html>
+
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE- 2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<head>
+<title>DeviceMap dynamic probes demo: target page</title>
+<link href="http://incubator.apache.org/devicemap/css/devicemap.css" rel="stylesheet" type="text/css">
+</head>
+
+<script language="javascript">
+
+// start devicemap client scope
+(function() {
+
+ var dmapClient = {};
+
+ dmapClient.trim = function(str) {
+ return str.replace(/^\s+|\s+$/g, '');
+ }
+
+ dmapClient.getCookieValue = function(name) {
+ var cooks = document.cookie.split(";");
+ var prefix = name + "=";
+ for(var i in cooks) {
+ var c = dmapClient.trim(cooks[i]);
+ if(c.indexOf(prefix) == 0) {
+ return dmapClient.trim(c.substring(prefix.length));
+ }
+ }
+ }
+
+ dmapClient.dump = function(id) {
+ var e = document.getElementById(id);
+ if(e) {
+ e.innerHTML = dmapClient.getCookieValue("DMAP_p");
+ }
+ };
+
+ // set onload handler
+ var oldOnload = window.onload;
+ window.onload = function() {
+ dmapClient.dump("dmap-dump");
+ if(oldOnload) {
+ oldOnload.call(window);
+ }
+ }
+
+// end devicemap client scope
+})();
+</script>
+
+<body>
+
+<h1>DeviceMap dynamic probes demo - target page</h1>
+
+<p>
+
+<a href="http://incubator.apache.org/devicemap">
+<img align="right" src="http://incubator.apache.org/devicemap/images/devicemap-logo/devicemap-logo-300-98.png"/>
+</a>
+
+You should get here after accessing
+any URL on the test server, with the below device info containing device map
+information that's refreshed when the corresponding cookie expires (see
+<code>DMAP_cookieValiditySeconds</code> value in the below data).
+</p>
+
+<h1>Device map data</h1>
+
+<p>
+The following device data is read from a cookie that's set by the probe page, so
+it's accessible both on the client and server side.
+</p>
+
+<code id="dmap-dump">
+</code>
+
+<h1>More info</h1>
+
+<p>
+You can see the javascript code used to build this data in the source
+code of the <a href="/DMAP_probe.html?DMAP_force=true">DMAP_probe.html</a> page.
+</p>
+
+<p>
+The complete source code can be found at
+<a href="http://svn.apache.org/repos/asf/incubator/devicemap/trunk/prototypes/probefilter">https://svn.apache.org/repos/asf/incubator/devicemap/trunk/prototypes/probefilter</a>.
+</p>
+
+<p>
+Thanks to <a href="http://detector.dmolsen.com/">http://detector.dmolsen.com/</a> and <a href="https://github.com/yiibu/profile">https://github.com/yiibu/profile</a> for inspiration.
+This prototype is well on its way to be YABFDL <em>(Yet Another Browser- and Feature-Detection Library)</em>...we should try to share the features detection code which is the hard
+part, the rest is just plumbing.
+</p>
+
+</body>
+
+</html>
\ No newline at end of file
Added: incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_probe.html
URL: http://svn.apache.org/viewvc/incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_probe.html?rev=1344766&view=auto
==============================================================================
--- incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_probe.html (added)
+++ incubator/devicemap/trunk/prototypes/probefilter/src/main/resources/dmap_probe.html Thu May 31 15:19:08 2012
@@ -0,0 +1,150 @@
+<html>
+
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE- 2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<head>
+<title>DeviceMap dynamic probes demo: probes page</title>
+<link href="http://incubator.apache.org/devicemap/css/devicemap.css" rel="stylesheet" type="text/css">
+</head>
+
+<script language="javascript">
+
+// start devicemap code scope
+(function() {
+
+ // TODO short cookie validity for now, for testing
+ var dmapCookieValiditySeconds = 30;
+
+ // Detector functions - we need more of those, see
+ // previous logcapture prototype which used modernizr
+ // and platform.js for that.
+ var detectors = {
+ elementSupport : function(elementName, propertyName) {
+ var e = document.createElement(elementName);
+ var value = eval("e." + propertyName) ? "true" : "false";
+ return value;
+ },
+
+ // from http://en.wikipedia.org/wiki/XMLHttpRequest
+ xhr : function() {
+ var xhr = null;
+ try { xhr = new XMLHttpRequest(); } catch (e) {}
+ try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
+ try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
+ return (xhr!=null);
+ }
+ };
+
+ // Setup probes that we'll use to build the device map.
+ // We might use a simple plugin system for that.
+ var probes = {
+ "DMAP_timestamp" : function() { return new Date().getTime(); },
+ "DMAP_cookieValiditySeconds" : function() { return dmapCookieValiditySeconds; },
+
+ "navigator.vendor" : function() { return navigator.vendor; },
+ "navigator.platform" : function() { return navigator.platform; },
+
+ "html5Audio" : function() { return detectors.elementSupport("audio","play") },
+ "html5Video" : function() { return detectors.elementSupport("video","play") },
+
+ "xhr" : function() { return detectors.xhr(); },
+
+ "TODO" : function() { return "Need to add more probes, see previous logcapture prototype, modernizr etc..." }
+ };
+
+ // The actual DeviceMap building code - avoid javascript
+ // libraries to keep things minimal for now
+ var dmap = {};
+
+ dmap.setCookie = function(name, value, validitySeconds) {
+ var exp = new Date();
+ exp.setTime(exp.getTime() + validitySeconds * 1000);
+ var c = name + "=" + value + "; expires=" + exp.toGMTString() + "; path=/";
+ document.cookie = c;
+ }
+
+ dmap.decodeUrlParam = function(str) {
+ return decodeURIComponent(str.replace(/\+/g, ' '));
+ }
+
+ // from http://snipplr.com/view/19838/get-url-parameters/
+ dmap.getUrlParams = function() {
+ var map = {};
+ var f = function(m,key,value) { map[key] = dmap.decodeUrlParam(value); };
+ var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, f);
+ return map;
+ }
+
+ // Run our probes, build and dump device map data
+ dmap.probe = function() {
+ var dmapData = {};
+
+ for(i in probes) {
+ dmapData[i] = probes[i].call(window);
+ }
+
+ // Dump dmapData in cookie
+ // TODO do we need any encoding here?
+ var value = "{ ";
+ for(i in dmapData) {
+ value += '"' + i + '":';
+ value += '"' + dmapData[i] + '", ';
+ }
+ value += " }";
+
+ dmap.setCookie("DMAP_p", value, dmapCookieValiditySeconds);
+ };
+
+ // Run our probes when document is loaded.
+ var oldOnload = window.onload;
+ window.onload = function() {
+ dmap.probe();
+ var params = dmap.getUrlParams();
+ if(params.next) {
+ setTimeout("document.location.href='" + params.next + "'", 2000);
+ }
+ if(oldOnload) {
+ oldOnload.call(window);
+ }
+ }
+
+// end devicemap code scope
+})();
+</script>
+
+<body>
+
+<h1>DeviceMap dynamic probes page</h1>
+
+<p>
+<a href="http://incubator.apache.org/devicemap">
+<img align="right" src="http://incubator.apache.org/devicemap/images/devicemap-logo/devicemap-logo-300-98.png"/>
+</a>
+
+You might briefly see this page, but
+the probe code should redirect to the target page after 2 seconds.
+</p>
+
+<p>
+TODO: add link to redirect to the right place if this fails.
+</p>
+
+</body>
+
+</html>
\ No newline at end of file