Skip to content
Browse files

Merge git://github.com/phonegap/phonegap-wp7

  • Loading branch information...
2 parents 581a8ac + c87bf09 commit f21e5af95a629dcb44c8e0c2aeb3aa4f2e205a6b @mrlacey committed
View
11 framework/PGView.xaml.cs
@@ -53,6 +53,8 @@ public partial class PGView : UserControl
/// </summary>
private NativeExecution nativeExecution;
+ protected DOMStorageHelper domStorageHelper;
+
public PGView()
{
@@ -115,6 +117,8 @@ void GapBrowser_Loaded(object sender, RoutedEventArgs e)
// prevents refreshing web control to initial state during pages transitions
if (this.IsBrowserInitialized) return;
+ this.domStorageHelper = new DOMStorageHelper(this.GapBrowser);
+
try
{
@@ -286,6 +290,13 @@ void GapBrowser_Navigating(object sender, NavigatingEventArgs e)
void GapBrowser_ScriptNotify(object sender, NotifyEventArgs e)
{
string commandStr = e.Value;
+
+ // DOMStorage/Local OR DOMStorage/Session
+ if (commandStr.IndexOf("DOMStorage") == 0)
+ {
+ this.domStorageHelper.HandleStorageCommand(commandStr);
+ return;
+ }
PhoneGapCommandCall commandCallParams = PhoneGapCommandCall.Parse(commandStr);
View
131 framework/PhoneGap/DOMStorageHelper.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using System.IO.IsolatedStorage;
+using System.Collections.Generic;
+using Microsoft.Phone.Controls;
+using System.Linq;
+using WP7GapClassLib.PhoneGap.JSON;
+
+/*
+ * Translates DOMStorage API between JS and Isolated Storage
+ * Missing pieces : QUOTA_EXCEEDED_ERR + StorageEvent
+ * */
+
+namespace WP7GapClassLib
+{
+ public class DOMStorageHelper
+ {
+ protected WebBrowser webBrowser1;
+
+ public DOMStorageHelper(WebBrowser gapBrowser)
+ {
+ this.webBrowser1 = gapBrowser;
+ // always clear session at creation
+ UserSettings["sessionStorage"] = new Dictionary<string, string>();
+
+ if (!UserSettings.Contains("localStorage"))
+ {
+ UserSettings["localStorage"] = new Dictionary<string, string>();
+ UserSettings.Save();
+ }
+ Application.Current.Exit += new EventHandler(OnAppExit);
+ }
+
+ void OnAppExit(object sender, EventArgs e)
+ {
+ UserSettings.Remove("sessionStorage");
+ UserSettings.Save();
+ }
+
+ protected IsolatedStorageSettings UserSettings
+ {
+ get
+ {
+ return IsolatedStorageSettings.ApplicationSettings;
+ }
+ }
+
+ protected Dictionary<string, string> getStorageByType(string type)
+ {
+ if (!UserSettings.Contains(type))
+ {
+ UserSettings[type] = new Dictionary<string, string>();
+ UserSettings.Save();
+ }
+ return UserSettings[type] as Dictionary<string,string>;
+ }
+
+
+ public void HandleStorageCommand(string commandStr)
+ {
+
+ string[] split = commandStr.Split('/');
+ if (split.Length > 3)
+ {
+ string api = split[0];
+ string type = split[1]; // localStorage || sessionStorage
+ string command = split[2];
+ string param = split[3];
+
+ Dictionary<string, string> currentStorage = getStorageByType(type);
+
+ switch (command)
+ {
+ case "get":
+ {
+
+ if (currentStorage.Keys.Contains(param))
+ {
+ string value = currentStorage[param];
+ webBrowser1.InvokeScript("execScript", "window." + type + ".onResult('" + param + "','" + value + "');");
+ }
+ else
+ {
+ webBrowser1.InvokeScript("execScript", "window." + type + ".onResult('" + param + "');");
+ }
+
+ }
+ break;
+ case "load":
+ {
+ string[] keys = currentStorage.Keys.ToArray();
+ string jsonString = JsonHelper.Serialize(keys);
+ string callbackJS = "window." + type + ".onKeysChanged('" + jsonString + "');";
+ webBrowser1.InvokeScript("execScript", callbackJS);
+ }
+ break;
+ case "set":
+ {
+ // TODO: check that length is not out of bounds
+ currentStorage[param] = split[4];
+ UserSettings.Save();
+ string[] keys = currentStorage.Keys.ToArray();
+ string jsonString = JsonHelper.Serialize(keys);
+ string callbackJS = "window." + type + ".onKeysChanged('" + jsonString + "');";
+ webBrowser1.InvokeScript("execScript", callbackJS);
+ }
+ break;
+ case "remove":
+ currentStorage.Remove(param);
+ UserSettings.Save();
+ break;
+ case "clear":
+ currentStorage = new Dictionary<string, string>();
+ UserSettings[type] = currentStorage;
+ UserSettings.Save();
+ break;
+ }
+
+ }
+
+ }
+ }
+}
View
1 framework/WP7GapClassLib.csproj
@@ -60,6 +60,7 @@
<Compile Include="PhoneGap\Commands\AudioPlayer.cs" />
<Compile Include="PhoneGap\Commands\Compass.cs" />
<Compile Include="PhoneGap\Commands\Media.cs" />
+ <Compile Include="PhoneGap\DOMStorageHelper.cs" />
<Compile Include="PhoneGap\JSON\JsonHelper.cs" />
<Compile Include="PhoneGap\Commands\MimeTypeMapper.cs" />
<Compile Include="PhoneGap\PhoneGapCommandCall.cs" />
View
208 framework/js/DOMStorage.js
@@ -0,0 +1,208 @@
+
+// this is a WP7 Only implementation of the Storage API for use in webpages loaded from the local file system
+// inside phonegap application.
+// there is a native implementation which is backing this and providing the persistance of values.
+// webpages loaded from a domain will not need to use this as IE9 has support for WebStorage
+// Javascript Interface is as defined here : http://dev.w3.org/html5/webstorage/#storage-0
+//
+
+if(!window.localStorage)
+{(function()
+{
+ "use strict";
+
+ 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))
+ {
+ console.log("didn't have a prop, now we do ...");
+ 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();
+
+
+})();};
+
View
208 framework/js/phonegap-1.1.0.js
@@ -1689,6 +1689,214 @@ PhoneGap.addConstructor(function() {
}
});
}
+
+// this is a WP7 Only implementation of the Storage API for use in webpages loaded from the local file system
+// inside phonegap application.
+// there is a native implementation which is backing this and providing the persistance of values.
+// webpages loaded from a domain will not need to use this as IE9 has support for WebStorage
+// Javascript Interface is as defined here : http://dev.w3.org/html5/webstorage/#storage-0
+//
+
+if(!window.localStorage)
+{(function()
+{
+ "use strict";
+
+ 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))
+ {
+ console.log("didn't have a prop, now we do ...");
+ 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();
+
+
+})();};
+
/*
* PhoneGap 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.
View
9 tests/MobileSpecUnitTests/www/autotest/index.html
@@ -65,8 +65,9 @@
<script type="text/javascript" src="tests/file.tests.js"></script>
<script type="text/javascript" src="tests/filetransfer.tests.js"></script>
<script type="text/javascript" src="tests/media.tests.js"></script>
-
-
+
+
+ <script type="text/javascript" src="tests/storage.tests.js"></script>
<!--
@@ -75,10 +76,10 @@
<script type="text/javascript" src="tests/orientation.tests.js"></script>
+ -->
+
- <script type="text/javascript" src="tests/storage.tests.js"></script>
- -->
</head>
<body onload="onBodyLoad()">
View
25 tests/MobileSpecUnitTests/www/autotest/tests/storage.tests.js
@@ -1,6 +1,7 @@
Tests.prototype.StorageTests = function()
{
module("Session Storage");
+
test("should exist", function() {
expect(7);
ok(window.sessionStorage != null, "sessionStorage is defined");
@@ -11,6 +12,7 @@ Tests.prototype.StorageTests = function()
ok(typeof(window.sessionStorage.removeItem) == "function", "sessionStorage.removeItem is defined");
ok(typeof(window.sessionStorage.clear) == "function", "sessionStorage.clear is defined");
});
+
test("check length", function() {
expect(3);
ok(window.sessionStorage.length == 0, "length should be 0");
@@ -19,6 +21,9 @@ Tests.prototype.StorageTests = function()
window.sessionStorage.removeItem("key");
ok(window.sessionStorage.length == 0, "length should be 0");
});
+
+
+
test("check key", function() {
expect(3);
ok(window.sessionStorage.key(0) == null, "key should be null");
@@ -27,6 +32,7 @@ Tests.prototype.StorageTests = function()
window.sessionStorage.removeItem("test");
ok(window.sessionStorage.key(0) == null, "key should be null");
});
+
test("check getItem", function() {
expect(3);
ok(window.sessionStorage.getItem("item") == null, "item should be null");
@@ -35,6 +41,7 @@ Tests.prototype.StorageTests = function()
window.sessionStorage.removeItem("item");
ok(window.sessionStorage.getItem("item") == null, "item should be null");
});
+
test("check setItem", function() {
expect(4);
ok(window.sessionStorage.getItem("item") == null, "item should be null");
@@ -45,6 +52,7 @@ Tests.prototype.StorageTests = function()
window.sessionStorage.removeItem("item");
ok(window.sessionStorage.getItem("item") == null, "item should be null");
});
+
test("check removeItem", function() {
expect(3);
ok(window.sessionStorage.getItem("item") == null, "item should be null");
@@ -53,6 +61,7 @@ Tests.prototype.StorageTests = function()
window.sessionStorage.removeItem("item");
ok(window.sessionStorage.getItem("item") == null, "item should be null");
});
+
test("check clear", function() {
expect(11);
ok(window.sessionStorage.getItem("item1") == null, "item1 should be null");
@@ -71,6 +80,7 @@ Tests.prototype.StorageTests = function()
ok(window.sessionStorage.getItem("item2") == null, "item2 should be null");
ok(window.sessionStorage.getItem("item3") == null, "item3 should be null");
});
+
test("check dot notation", function() {
expect(3);
ok(window.sessionStorage.item == null, "item should be null");
@@ -79,7 +89,9 @@ Tests.prototype.StorageTests = function()
window.sessionStorage.removeItem("item");
ok(window.sessionStorage.item == null, "item should be null");
});
+
module("Local Storage");
+
test("should exist", function() {
expect(7);
ok(window.localStorage != null, "localStorage is defined");
@@ -90,6 +102,7 @@ Tests.prototype.StorageTests = function()
ok(typeof(window.localStorage.removeItem) == "function", "localStorage.removeItem is defined");
ok(typeof(window.localStorage.clear) == "function", "localStorage.clear is defined");
});
+
test("check length", function() {
expect(3);
ok(window.localStorage.length == 0, "length should be 0");
@@ -98,6 +111,7 @@ Tests.prototype.StorageTests = function()
window.localStorage.removeItem("key");
ok(window.localStorage.length == 0, "length should be 0");
});
+
test("check key", function() {
expect(3);
ok(window.localStorage.key(0) == null, "key should be null");
@@ -106,6 +120,7 @@ Tests.prototype.StorageTests = function()
window.localStorage.removeItem("test");
ok(window.localStorage.key(0) == null, "key should be null");
});
+
test("check getItem", function() {
expect(3);
ok(window.localStorage.getItem("item") == null, "item should be null");
@@ -114,6 +129,7 @@ Tests.prototype.StorageTests = function()
window.localStorage.removeItem("item");
ok(window.localStorage.getItem("item") == null, "item should be null");
});
+
test("check setItem", function() {
expect(4);
ok(window.localStorage.getItem("item") == null, "item should be null");
@@ -124,6 +140,7 @@ Tests.prototype.StorageTests = function()
window.localStorage.removeItem("item");
ok(window.localStorage.getItem("item") == null, "item should be null");
});
+
test("check removeItem", function() {
expect(3);
ok(window.localStorage.getItem("item") == null, "item should be null");
@@ -132,6 +149,7 @@ Tests.prototype.StorageTests = function()
window.localStorage.removeItem("item");
ok(window.localStorage.getItem("item") == null, "item should be null");
});
+
test("check clear", function() {
expect(11);
ok(window.localStorage.getItem("item1") == null, "item1 should be null");
@@ -150,6 +168,7 @@ Tests.prototype.StorageTests = function()
ok(window.localStorage.getItem("item2") == null, "item2 should be null");
ok(window.localStorage.getItem("item3") == null, "item3 should be null");
});
+
test("check dot notation", function() {
expect(3);
ok(window.localStorage.item == null, "item should be null");
@@ -158,7 +177,12 @@ Tests.prototype.StorageTests = function()
window.localStorage.removeItem("item");
ok(window.localStorage.item == null, "item should be null");
});
+
+
+
+ /*
module("HTML 5 Storage");
+
test("should exist", function() {
expect(1);
ok(typeof(window.openDatabase) == "function", "Database is defined");
@@ -167,4 +191,5 @@ Tests.prototype.StorageTests = function()
var db = openDatabase("Database", "1.0", "HTML5 Database API example", 200000);
ok(db != null, "Database should be opened");
});
+ */
}
View
219 tests/MobileSpecUnitTests/www/phonegap-1.1.0.js
@@ -15,6 +15,7 @@
+
/**
* The order of events during page load and PhoneGap startup is as follows:
*
@@ -814,6 +815,7 @@ function()
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("camera")) {
@@ -959,6 +961,7 @@ PhoneGap.addConstructor(function() {
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("capture")) {
@@ -1158,6 +1161,7 @@ PhoneGap.addConstructor(function () {
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("compass")) {
@@ -1306,6 +1310,7 @@ function()
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("contact")) {
@@ -1617,6 +1622,7 @@ PhoneGap.addConstructor(function() {
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("device")) {
@@ -1683,12 +1689,221 @@ PhoneGap.addConstructor(function() {
}
});
}
+
+// this is a WP7 Only implementation of the Storage API for use in webpages loaded from the local file system
+// inside phonegap application.
+// there is a native implementation which is backing this and providing the persistance of values.
+// webpages loaded from a domain will not need to use this as IE9 has support for WebStorage
+// Javascript Interface is as defined here : http://dev.w3.org/html5/webstorage/#storage-0
+//
+
+if(!window.localStorage)
+{(function()
+{
+ "use strict";
+
+ 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))
+ {
+ console.log("didn't have a prop, now we do ...");
+ 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();
+
+
+})();};
+
/*
* PhoneGap 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) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("file")) {
@@ -2729,6 +2944,7 @@ PhoneGap.addConstructor(function () {
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("filetransfer")) {
@@ -2824,6 +3040,7 @@ var FileUploadOptions = function(fileKey, fileName, mimeType, params) {
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("media")) {
@@ -3050,6 +3267,7 @@ PhoneGapMediaonStatus = function (args) {
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("network")) {
@@ -3138,6 +3356,7 @@ PhoneGap.addConstructor(function() {
*
* Copyright (c) 2005-2011, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
+ * Copyright (c) 2011, Microsoft Corporation
*/
if (!PhoneGap.hasResource("notification")) {
View
23 tests/MobileSpecUnitTests/www/storage.html
@@ -3,7 +3,7 @@
<head>
<!-- meta name="viewport" content="width=device-width, height=device-height, user-scalable=yes, initial-scale=2.0, maximum-scale=4.0, minimum-scale=1.0" / -->
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
- <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>PhoneGap</title>
<link rel="stylesheet" href="master.css" type="text/css" media="screen"/>
@@ -52,19 +52,22 @@
<h1>Local Storage</h1>
<div id="info">
- You have run this app <span id="count">an untold number of</span> time(s).
+ You have loaded this view <span id="count">an untold number of</span> time(s).
</div>
<script>
- console.log("sessionStorage = " + ( 'sessionStorage' in window && window.sessionStorage != null ));
- console.log("localStorage = " + ( 'localStorage' in window && window.localStorage != null ));
-
- if (!localStorage.pageLoadCount) {
- localStorage.pageLoadCount = 0;
- }
- localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1;
- document.getElementById('count').textContent = localStorage.pageLoadCount;
+ console.log("sessionStorage = " + ( 'sessionStorage' in window && window.sessionStorage != null ));
+ console.log("localStorage = " + ( 'localStorage' in window && window.localStorage != null ));
+
+ if (!localStorage.pageLoadCount)
+ {
+ localStorage.setItem("pageLoadCount",0);
+ }
+
+ localStorage.setItem("pageLoadCount",parseInt(localStorage.pageLoadCount) + 1);
+
+ document.getElementById('count').textContent = localStorage.pageLoadCount;
</script>
<h2>&nbsp;</h2><a href="index.html" class="backBtn">Back</a>

0 comments on commit f21e5af

Please sign in to comment.
Something went wrong with that request. Please try again.