You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pu...@apache.org on 2012/04/13 01:25:21 UTC

[3/6] git commit: added XHR patch and DOMStorage patch, both are conditionally polyfil'n expected APIs

added XHR patch and DOMStorage patch, both are conditionally polyfil'n expected APIs


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/commit/0c5d9179
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/0c5d9179
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/0c5d9179

Branch: refs/heads/master
Commit: 0c5d9179dacf9107d93b5a0971f6a47a5ba8fa74
Parents: 7e1461b
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Tue Apr 10 15:46:58 2012 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Thu Apr 12 16:22:02 2012 -0700

----------------------------------------------------------------------
 lib/wp7/platform.js              |  211 ++-------------------------------
 lib/wp7/plugin/wp7/DOMStorage.js |  198 ++++++++++++++++++++++++++++++
 lib/wp7/plugin/wp7/XHRPatch.js   |  212 +++++++++++++++++++++++++++++++++
 3 files changed, 420 insertions(+), 201 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/0c5d9179/lib/wp7/platform.js
----------------------------------------------------------------------
diff --git a/lib/wp7/platform.js b/lib/wp7/platform.js
index ff61830..4a89e27 100644
--- a/lib/wp7/platform.js
+++ b/lib/wp7/platform.js
@@ -1,214 +1,23 @@
 var cordova = require('cordova'),
       exec = require('cordova/exec');
 
+// specifically require the following patches
+// localStorage+SessionStorage APIs
+require("cordova/plugin/wp7/DOMStorage");
+// Fix XHR calls to local file-system
+require("cordova/plugin/wp7/XHRPatch");
+
+
 module.exports = {
     id: "wp7",
     initialize:function() {
 
-console.log("window.CordovaMediaonStatus = " + window.CordovaMediaonStatus);
-
-if(!window.localStorage)
-{(function()
-{
-	
-	
-
-    var DOMStorage = function(type)
-    {
-        // default type is local
-        if(type == "sessionStorage")
-        {
-            this._type = type;
-        }
-        Object.defineProperty( this, "length", 
-        {
-            configurable: true,
-            get: function(){ return this.getLength() }
-        });
-
-    };
-
-    DOMStorage.prototype = 
-    {
-        _type:"localStorage",
-        _result:null,
-        keys:null,
-    
-        onResult:function(key,valueStr)
-        {
-            if(!this.keys)
-            {
-                this.keys = [];
-            }
-            this._result = valueStr;
-        },
-
-        onKeysChanged:function(jsonKeys)
-        {
-            this.keys = JSON.parse(jsonKeys);
-
-            var key;
-            for(var n = 0,len =this.keys.length; n < len; n++)
-            {
-                key = this.keys[n];
-                if(!this.hasOwnProperty(key))
-                {
-                    Object.defineProperty( this, key, 
-                    {
-
-                        configurable: true,
-                        get: function(){ return this.getItem(key); },
-                        set: function(val){ return this.setItem(key,val); }
-                    });
-                }
-            }
-
-        },
-
-        initialize:function()
-        {
-            window.external.Notify("DOMStorage/" + this._type + "/load/keys");
-        },
-
-    /*
-        The length attribute must return the number of key/value pairs currently present in the list associated with the object.
-    */
-        getLength:function()
-        {
-            if(!this.keys)
-            {
-                this.initialize();
-            }
-            return this.keys.length;
-        },
-
-    /*
-        The key(n) method must return the name of the nth key in the list. 
-        The order of keys is user-agent defined, but must be consistent within an object so long as the number of keys doesn't change. 
-        (Thus, adding or removing a key may change the order of the keys, but merely changing the value of an existing key must not.) 
-        If n is greater than or equal to the number of key/value pairs in the object, then this method must return null. 
-    */
-        key:function(n)
-        {
-            if(!this.keys)
-            {
-                this.initialize();
-            }
-
-            if(n >= this.keys.length)
-            {
-                return null;
-            }
-            else
-            {
-                return this.keys[n];
-            }
-        },
-
-    /*
-        The getItem(key) method must return the current value associated with the given key. 
-        If the given key does not exist in the list associated with the object then this method must return null.
-    */
-        getItem:function(key)
-        {
-            if(!this.keys)
-            {
-                this.initialize();
-            }
-
-            var retVal = null;
-            if(this.keys.indexOf(key) > -1)
-            {
-                window.external.Notify("DOMStorage/" + this._type + "/get/" + key);
-                retVal = this._result;
-                this._result = null;
-            }
-            return retVal;
-        },
-    /*
-        The setItem(key, value) method must first check if a key/value pair with the given key already exists 
-        in the list associated with the object.
-        If it does not, then a new key/value pair must be added to the list, with the given key and with its value set to value.
-        If the given key does exist in the list, then it must have its value updated to value.
-        If it couldn't set the new value, the method must raise an QUOTA_EXCEEDED_ERR exception. 
-        (Setting could fail if, e.g., the user has disabled storage for the site, or if the quota has been exceeded.)
-    */
-        setItem:function(key,value)
-        {
-            if(!this.keys)
-            {
-                this.initialize();
-            }
-            window.external.Notify("DOMStorage/" + this._type + "/set/" + key + "/" + value);
-        },
-
-    /*
-        The removeItem(key) method must cause the key/value pair with the given key to be removed from the list 
-        associated with the object, if it exists. 
-        If no item with that key exists, the method must do nothing.
-    */
-        removeItem:function(key)
-        {
-            if(!this.keys)
-            {
-                this.initialize();
-            }
-            var index = this.keys.indexOf(key);
-            if(index > -1)
-            {
-                this.keys.splice(index,1);
-                // TODO: need sanity check for keys ? like 'clear','setItem', ...
-                window.external.Notify("DOMStorage/" + this._type + "/remove/" + key);
-                delete this[key];
-            }
-            
-        },
-
-    /*
-        The clear() method must atomically cause the list associated with the object to be emptied of all 
-        key/value pairs, if there are any. 
-        If there are none, then the method must do nothing.
-    */
-        clear:function()
-        {
-            if(!this.keys)
-            {
-                this.initialize();
-            }
-
-            for(var n=0,len=this.keys.length; n < len;n++)
-            {
-                // TODO: do we need a sanity check for keys ? like 'clear','setItem', ...
-                delete this[this.keys[n]];
-            }
-            this.keys = [];
-            window.external.Notify("DOMStorage/" + this._type + "/clear/");
-        }
-    };
-
-    // initialize DOMStorage
-    
-    Object.defineProperty( window, "localStorage", 
-    {
-        writable: false,
-        configurable: false,
-        value:new DOMStorage("localStorage")
-    });
-    window.localStorage.initialize();
-
-    Object.defineProperty( window, "sessionStorage", 
-    {
-        writable: false,
-        configurable: false,
-        value:new DOMStorage("sessionStorage")
-    });
-    window.sessionStorage.initialize();
-
+    console.log("window.CordovaMediaonStatus = " + window.CordovaMediaonStatus);
+    console.log("window.localStorage = " + window.localStorage);
 
-})();};
 
 
-		// INject a lsitener for the backbutton, and tell native to override the flag (true/false) when we have 1 or more, or 0, listeners
+	// INject a lsitener for the backbutton, and tell native to override the flag (true/false) when we have 1 or more, or 0, listeners
     var backButtonChannel = cordova.addDocumentEventHandler('backbutton', {
       onSubscribe:function() {
         if (this.numHandlers === 1) {

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/0c5d9179/lib/wp7/plugin/wp7/DOMStorage.js
----------------------------------------------------------------------
diff --git a/lib/wp7/plugin/wp7/DOMStorage.js b/lib/wp7/plugin/wp7/DOMStorage.js
new file mode 100644
index 0000000..db61f4c
--- /dev/null
+++ b/lib/wp7/plugin/wp7/DOMStorage.js
@@ -0,0 +1,198 @@
+(function()
+{
+
+    var DOMStorage = function(type)
+    {
+        // default type is local
+        if(type == "sessionStorage")
+        {
+            this._type = type;
+        }
+        Object.defineProperty( this, "length", 
+        {
+            configurable: true,
+            get: function(){ return this.getLength() }
+        });
+
+    };
+
+    DOMStorage.prototype = 
+    {
+        _type:"localStorage",
+        _result:null,
+        keys:null,
+    
+        onResult:function(key,valueStr)
+        {
+            if(!this.keys)
+            {
+                this.keys = [];
+            }
+            this._result = valueStr;
+        },
+
+        onKeysChanged:function(jsonKeys)
+        {
+            this.keys = JSON.parse(jsonKeys);
+
+            var key;
+            for(var n = 0,len =this.keys.length; n < len; n++)
+            {
+                key = this.keys[n];
+                if(!this.hasOwnProperty(key))
+                {
+                    Object.defineProperty( this, key, 
+                    {
+
+                        configurable: true,
+                        get: function(){ return this.getItem(key); },
+                        set: function(val){ return this.setItem(key,val); }
+                    });
+                }
+            }
+
+        },
+
+        initialize:function()
+        {
+            window.external.Notify("DOMStorage/" + this._type + "/load/keys");
+        },
+
+    /*
+        The length attribute must return the number of key/value pairs currently present in the list associated with the object.
+    */
+        getLength:function()
+        {
+            if(!this.keys)
+            {
+                this.initialize();
+            }
+            return this.keys.length;
+        },
+
+    /*
+        The key(n) method must return the name of the nth key in the list. 
+        The order of keys is user-agent defined, but must be consistent within an object so long as the number of keys doesn't change. 
+        (Thus, adding or removing a key may change the order of the keys, but merely changing the value of an existing key must not.) 
+        If n is greater than or equal to the number of key/value pairs in the object, then this method must return null. 
+    */
+        key:function(n)
+        {
+            if(!this.keys)
+            {
+                this.initialize();
+            }
+
+            if(n >= this.keys.length)
+            {
+                return null;
+            }
+            else
+            {
+                return this.keys[n];
+            }
+        },
+
+    /*
+        The getItem(key) method must return the current value associated with the given key. 
+        If the given key does not exist in the list associated with the object then this method must return null.
+    */
+        getItem:function(key)
+        {
+            if(!this.keys)
+            {
+                this.initialize();
+            }
+
+            var retVal = null;
+            if(this.keys.indexOf(key) > -1)
+            {
+                window.external.Notify("DOMStorage/" + this._type + "/get/" + key);
+                retVal = this._result;
+                this._result = null;
+            }
+            return retVal;
+        },
+    /*
+        The setItem(key, value) method must first check if a key/value pair with the given key already exists 
+        in the list associated with the object.
+        If it does not, then a new key/value pair must be added to the list, with the given key and with its value set to value.
+        If the given key does exist in the list, then it must have its value updated to value.
+        If it couldn't set the new value, the method must raise an QUOTA_EXCEEDED_ERR exception. 
+        (Setting could fail if, e.g., the user has disabled storage for the site, or if the quota has been exceeded.)
+    */
+        setItem:function(key,value)
+        {
+            if(!this.keys)
+            {
+                this.initialize();
+            }
+            window.external.Notify("DOMStorage/" + this._type + "/set/" + key + "/" + value);
+        },
+
+    /*
+        The removeItem(key) method must cause the key/value pair with the given key to be removed from the list 
+        associated with the object, if it exists. 
+        If no item with that key exists, the method must do nothing.
+    */
+        removeItem:function(key)
+        {
+            if(!this.keys)
+            {
+                this.initialize();
+            }
+            var index = this.keys.indexOf(key);
+            if(index > -1)
+            {
+                this.keys.splice(index,1);
+                // TODO: need sanity check for keys ? like 'clear','setItem', ...
+                window.external.Notify("DOMStorage/" + this._type + "/remove/" + key);
+                delete this[key];
+            }
+            
+        },
+
+    /*
+        The clear() method must atomically cause the list associated with the object to be emptied of all 
+        key/value pairs, if there are any. 
+        If there are none, then the method must do nothing.
+    */
+        clear:function()
+        {
+            if(!this.keys)
+            {
+                this.initialize();
+            }
+
+            for(var n=0,len=this.keys.length; n < len;n++)
+            {
+                // TODO: do we need a sanity check for keys ? like 'clear','setItem', ...
+                delete this[this.keys[n]];
+            }
+            this.keys = [];
+            window.external.Notify("DOMStorage/" + this._type + "/clear/");
+        }
+    };
+
+    // initialize DOMStorage
+    
+    Object.defineProperty( window, "localStorage", 
+    {
+        writable: false,
+        configurable: false,
+        value:new DOMStorage("localStorage")
+    });
+    window.localStorage.initialize();
+
+    Object.defineProperty( window, "sessionStorage", 
+    {
+        writable: false,
+        configurable: false,
+        value:new DOMStorage("sessionStorage")
+    });
+    window.sessionStorage.initialize();
+
+
+})();
+
+module.exports = null;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/0c5d9179/lib/wp7/plugin/wp7/XHRPatch.js
----------------------------------------------------------------------
diff --git a/lib/wp7/plugin/wp7/XHRPatch.js b/lib/wp7/plugin/wp7/XHRPatch.js
new file mode 100644
index 0000000..2133c93
--- /dev/null
+++ b/lib/wp7/plugin/wp7/XHRPatch.js
@@ -0,0 +1,212 @@
+
+
+(function (win, doc) {
+
+var docDomain = null;
+try {
+    docDomain = doc.domain;
+}
+catch (err) 
+{
+    //console.log("caught exception trying to access document.domain");
+}
+
+if (!docDomain || docDomain.length == 0) {
+
+    var aliasXHR = win.XMLHttpRequest;
+
+    win.XMLHttpRequest = function () { };
+    win.XMLHttpRequest.noConflict = aliasXHR;
+    win.XMLHttpRequest.UNSENT = 0;
+    win.XMLHttpRequest.OPENED = 1;
+    win.XMLHttpRequest.HEADERS_RECEIVED = 2;
+    win.XMLHttpRequest.LOADING = 3;
+    win.XMLHttpRequest.DONE = 4;
+
+    win.XMLHttpRequest.prototype =
+	{
+	    UNSENT: 0,
+	    OPENED: 1,
+	    HEADERS_RECEIVED: 2,
+	    LOADING: 3,
+	    DONE: 4,
+
+	    isAsync: false,
+	    onreadystatechange: null,
+	    readyState: 0,
+	    _url: "",
+	    timeout: 0,
+	    withCredentials: false,
+	    _requestHeaders: null,
+	    open: function (reqType, uri, isAsync, user, password) {
+	        console.log("XMLHttpRequest.open ::: " + uri);
+
+	        if (uri && uri.indexOf("http") == 0) {
+	            if (!this.wrappedXHR) {
+	                this.wrappedXHR = new aliasXHR();
+	                var self = this;
+
+	                // timeout
+	                if (this.timeout > 0) {
+	                    this.wrappedXHR.timeout = this.timeout;
+	                }
+	                Object.defineProperty(this, "timeout", {
+	                    set: function (val) {
+	                        this.wrappedXHR.timeout = val;
+	                    },
+	                    get: function () {
+	                        return this.wrappedXHR.timeout;
+	                    }
+	                });
+
+
+
+	                if (this.withCredentials) {
+	                    this.wrappedXHR.withCredentials = this.withCredentials;
+	                }
+	                Object.defineProperty(this, "withCredentials", {
+	                    set: function (val) {
+	                        this.wrappedXHR.withCredentials = val;
+	                    },
+	                    get: function () {
+	                        return this.wrappedXHR.withCredentials;
+	                    }
+	                });
+
+
+	                Object.defineProperty(this, "status", { get: function () {
+	                    return this.wrappedXHR.status;
+	                }
+	                });
+	                Object.defineProperty(this, "responseText", { get: function () {
+	                    return this.wrappedXHR.responseText;
+	                }
+	                });
+	                Object.defineProperty(this, "statusText", { get: function () {
+	                    return this.wrappedXHR.statusText;
+	                }
+	                });
+
+	                Object.defineProperty(this, "responseXML", { get: function () {
+	                    return this.wrappedXHR.responseXML;
+	                }
+	                });
+
+	                this.getResponseHeader = function (header) {
+	                    return this.wrappedXHR.getResponseHeader(header);
+	                };
+	                this.getAllResponseHeaders = function () {
+	                    return this.wrappedXHR.getAllResponseHeaders();
+	                };
+
+	                this.wrappedXHR.onreadystatechange = function () {
+	                    self.changeReadyState(self.wrappedXHR.readyState);
+	                };
+	            }
+	            return this.wrappedXHR.open(reqType, uri, isAsync, user, password);
+	        }
+	        else {
+	            // x-wmapp1://app/www/page2.html
+	            // need to work some magic on the actual url/filepath
+	            var newUrl = uri;
+	            if (newUrl.indexOf(":/") > -1) {
+	                newUrl = newUrl.split(":/")[1];
+	            }
+
+	            if (newUrl.lastIndexOf("/") === newUrl.length - 1) {
+	                newUrl += "index.html"; // default page is index.html, when call is to a dir/ ( why not ...? )
+	            }
+	            this._url = newUrl;
+	        }
+	    },
+	    statusText: "",
+	    changeReadyState: function (newState) {
+	        this.readyState = newState;
+	        if (this.onreadystatechange) {
+	            this.onreadystatechange();
+	        }
+	    },
+	    setRequestHeader: function (header, value) {
+	        if (this.wrappedXHR) {
+	            this.wrappedXHR.setRequestHeader(header, value);
+	        }
+	    },
+	    getResponseHeader: function (header) {
+	        return this.wrappedXHR ? this.wrappedXHR.getResponseHeader(header) : "";
+	    },
+	    getAllResponseHeaders: function () {
+	        return this.wrappedXHR ? this.wrappedXHR.getAllResponseHeaders() : "";
+	    },
+	    responseText: "",
+	    responseXML: "",
+	    onResult: function (res) {
+	        this.status = 200;
+	        this.responseText = res;
+
+	        Object.defineProperty(this, "responseXML", { get: function () {
+	            var parser = new DOMParser();
+	            return parser.parseFromString(this.responseText, "text/xml");
+	        }
+	        });
+	        this.changeReadyState(this.DONE);
+	    },
+	    onError: function (err) {
+	        console.log("Wrapped XHR received Error from FileAPI :: " + err);
+	        this.status = 404;
+	        this.changeReadyState(this.DONE);
+	    },
+
+	    abort: function () {
+	        if (this.wrappedXHR) {
+	            return this.wrappedXHR.abort();
+	        }
+	    },
+
+	    send: function (data) {
+	        if (this.wrappedXHR) {
+	            return this.wrappedXHR.send(data);
+	        }
+	        else {
+	            this.changeReadyState(this.OPENED);
+
+	            var alias = this;
+
+	            function fail(evt) {
+	                console.log("fail :: " + JSON.stringify(evt));
+
+	                alias.onError(evt.code);
+	            }
+
+	            function gotFile(file) {
+	                console.log("got file");
+	                var reader = new FileReader();
+	                reader.onloadend = function (evt) {
+	                    console.log("Read as text");
+	                    alias.onResult(evt.target.result);
+	                };
+	                reader.readAsText(file);
+	            }
+
+	            function gotEntry(entry) {
+	                console.log("got entry");
+	                entry.file(gotFile, fail);
+	            }
+
+	            function gotFS(fs) {
+	                console.log("got filesystem");
+	                fs.root.getFile(alias._url, null, gotEntry, fail);
+	            }
+
+	            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
+
+	        }
+	    },
+	    status: 404
+	};
+} // if doc domain 
+
+// end closure wrap
+})(window, document); 
+
+module.exports = null;
+