cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From purplecabb...@apache.org
Subject git commit: Added IBrowserDecorator for generic definition of BrowserDecorating functions, including XHR patching, and Orientation. Mostly these will be polyfills of things we would expect the browser to already have
Date Thu, 27 Jun 2013 22:24:26 GMT
Updated Branches:
  refs/heads/master b5f6026f1 -> a87588d68


Added IBrowserDecorator for generic definition of BrowserDecorating functions, including XHR patching, and Orientation.  Mostly these will be polyfills of things we would expect the browser to already have


Project: http://git-wip-us.apache.org/repos/asf/cordova-wp8/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp8/commit/a87588d6
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp8/tree/a87588d6
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp8/diff/a87588d6

Branch: refs/heads/master
Commit: a87588d68225af750d61c14eb6735d9b2a363645
Parents: b5f6026
Author: Jesse MacFadyen <purplecabbage@gmail.com>
Authored: Thu Jun 27 15:23:55 2013 -0700
Committer: Jesse MacFadyen <purplecabbage@gmail.com>
Committed: Thu Jun 27 15:23:55 2013 -0700

----------------------------------------------------------------------
 wp7/framework/CordovaLib/XHRProxy.cs         | 262 ----------------------
 wp7/framework/WPCordovaClassLib.csproj       |   9 +-
 wp7/template/CordovaWP7AppProj.csproj        |   5 +-
 wp7/template/MyTemplate.vstemplate           |  10 +-
 wp7/template/cordovalib/CordovaView.xaml.cs  |  52 +++--
 wp7/template/cordovalib/DOMStorageProxy.cs   | 155 +++++++++++++
 wp7/template/cordovalib/IBrowserDecorator.cs |  15 ++
 wp7/template/cordovalib/OrientationHelper.cs |  45 ++--
 wp7/template/cordovalib/XHRHelper.cs         | 252 +++++++++++++++++++++
 wp7/template/cordovalib/XHRProxy.cs          | 261 ---------------------
 wp8/framework/WPCordovaClassLib.csproj       |   7 +-
 wp8/template/CordovaWP8AppProj.csproj        |   6 +-
 wp8/template/MyTemplate.vstemplate           |   8 +-
 wp8/template/cordovalib/CordovaView.xaml.cs  |  47 ++--
 wp8/template/cordovalib/IBrowserDecorator.cs |  16 ++
 wp8/template/cordovalib/OrientationHelper.cs |  43 ++--
 wp8/template/cordovalib/XHRHelper.cs         | 252 +++++++++++++++++++++
 wp8/template/cordovalib/XHRProxy.cs          | 261 ---------------------
 18 files changed, 828 insertions(+), 878 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/framework/CordovaLib/XHRProxy.cs
----------------------------------------------------------------------
diff --git a/wp7/framework/CordovaLib/XHRProxy.cs b/wp7/framework/CordovaLib/XHRProxy.cs
deleted file mode 100644
index 8a53f0b..0000000
--- a/wp7/framework/CordovaLib/XHRProxy.cs
+++ /dev/null
@@ -1,262 +0,0 @@
-using Microsoft.Phone.Controls;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.IO.IsolatedStorage;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-
-namespace WPCordovaClassLib.CordovaLib
-{
-    public class XHRProxy
-    {
-
-        private WebBrowser webBrowser;
-
-        public XHRProxy(ref WebBrowser browser) 
-        {
-            this.webBrowser = browser;
-            browser.ScriptNotify += browser_ScriptNotify;
-            browser.Navigated += browser_Navigated;
-        }
-
-        void browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
-        {
-
-
-            string script = @"(function(win, doc) {
-
-    var docDomain = null;
-    try {
-        docDomain = doc.domain;
-    } catch (err) {}
-
-    if (!docDomain || docDomain.length === 0) {
-
-        var aliasXHR = win.XMLHttpRequest;
-        
-        var XHRShim = function() {};
-        win.XMLHttpRequest = XHRShim;
-        XHRShim.noConflict = aliasXHR;
-        XHRShim.UNSENT = 0;
-        XHRShim.OPENED = 1;
-        XHRShim.HEADERS_RECEIVED = 2;
-        XHRShim.LOADING = 3;
-        XHRShim.DONE = 4;
-        XHRShim.prototype = {
-            isAsync: false,
-            onreadystatechange: null,
-            readyState: 0,
-            _url: '',
-            timeout: 0,
-            withCredentials: false,
-            _requestHeaders: null,
-            open: function (reqType, uri, isAsync, user, password) {
-                
-                if (uri && uri.indexOf('http') === 0) {
-                    if (!this.wrappedXHR) {
-                        this.wrappedXHR = new aliasXHR();
-                        var self = this;
-                        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
-                {
-                    this.isAsync = isAsync;
-                    this.reqType = reqType;
-                    var newUrl = uri;
-                    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;
-                if (typeof res == 'object') {
-                    res = JSON.stringify(res);
-                }
-                this.responseText = res;
-                this.responseXML = res;
-                this.changeReadyState(XHRShim.DONE);
-            },
-            onError: function(err) {
-                this.status = 404;
-                this.changeReadyState(XHRShim.DONE);
-            },
-            abort: function() {
-                if (this.wrappedXHR) {
-                    return this.wrappedXHR.abort();
-                }
-            },
-            send: function(data) {
-                if (this.wrappedXHR) {
-                    return this.wrappedXHR.send(data);
-                } 
-                else {
-                    this.changeReadyState(XHRShim.OPENED);
-                    var alias = this;
-                    var funk = function () {
-                        window.__onXHRLocalCallback = function (responseCode, responseText) {
-                            alias.status = responseCode;
-                            if (responseCode == '200') {
-                                alias.responseText = responseText;
-                            }
-                            else {
-                                alias.onerror && alias.onerror(responseCode);
-                            }
-
-                            alias.changeReadyState(XHRShim.DONE);
-                            alias.onload && alias.onload();
-                            
-                        }
-                        alias.changeReadyState(XHRShim.LOADING);
-                        window.external.Notify('XHRLOCAL/' + alias._url); 
-                    }
-                    if (this.isAsync) {
-                        setTimeout(funk, 0);
-                    }
-                    else {
-                        funk();
-                    }
-                }
-            },
-            getContentLocation: function() {
-                if (window.contentLocation === undefined) {
-                    window.contentLocation = navigator.userAgent.toUpperCase().indexOf('MSIE 10') > -1 ? this.contentLocation.RESOURCES : this.contentLocation.ISOLATED_STORAGE;
-                }
-                return window.contentLocation;
-            },
-            contentLocation: {
-                ISOLATED_STORAGE: 0,
-                RESOURCES: 1
-            },
-            status: 404
-        };
-    }
-})(window, document); ";
-
-
-            webBrowser.InvokeScript("execScript", new string[] { script });
-
-
-        }
-
-        void browser_ScriptNotify(object sender, NotifyEventArgs e)
-        {
-            Debug.WriteLine("ScriptNotify::" + e.Value);
-            string commandStr = e.Value;
-
-            if (commandStr.IndexOf("XHRLOCAL") == 0)
-            {
-                string url = commandStr.Replace("XHRLOCAL/", "");
-
-                Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
-
-                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
-                {
-                    if (isoFile.FileExists(uri.AbsolutePath))
-                    {
-                        using (TextReader reader = new StreamReader(isoFile.OpenFile(uri.AbsolutePath, FileMode.Open, FileAccess.Read)))
-                        {
-                            string text = reader.ReadToEnd();
-                            webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
-                            return;
-                        }
-                    }       
-                }
-
-                Uri relUri = new Uri(uri.AbsolutePath,UriKind.Relative);
-                
-                var resource = Application.GetResourceStream(relUri);
-
-                if (resource == null)
-                {
-                    // 404 ? 
-                    webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "404" });
-                    return;
-                }
-                else 
-                {
-                    using (StreamReader streamReader = new StreamReader(resource.Stream))
-                    {
-                        string text = streamReader.ReadToEnd();
-                        webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
-                        return;
-                    }
-                }
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/framework/WPCordovaClassLib.csproj
----------------------------------------------------------------------
diff --git a/wp7/framework/WPCordovaClassLib.csproj b/wp7/framework/WPCordovaClassLib.csproj
index 9676f56..4c6ba8c 100644
--- a/wp7/framework/WPCordovaClassLib.csproj
+++ b/wp7/framework/WPCordovaClassLib.csproj
@@ -155,9 +155,6 @@
     <Compile Include="..\..\common\Plugins\UI\VideoRecorder.xaml.cs">
       <Link>Plugins\UI\VideoRecorder.xaml.cs</Link>
     </Compile>
-    <Compile Include="..\..\wp8\template\cordovalib\XHRProxy.cs">
-      <Link>CordovaLib\XHRProxy.cs</Link>
-    </Compile>
     <Compile Include="..\template\cordovalib\BaseCommand.cs">
       <Link>CordovaLib\BaseCommand.cs</Link>
     </Compile>
@@ -179,6 +176,9 @@
     <Compile Include="..\template\cordovalib\DOMStorageHelper.cs">
       <Link>CordovaLib\DOMStorageHelper.cs</Link>
     </Compile>
+    <Compile Include="..\template\cordovalib\IBrowserDecorator.cs">
+      <Link>CordovaLib\IBrowserDecorator.cs</Link>
+    </Compile>
     <Compile Include="..\template\cordovalib\ImageExifHelper.cs">
       <Link>CordovaLib\ImageExifHelper.cs</Link>
     </Compile>
@@ -197,6 +197,9 @@
     <Compile Include="..\template\cordovalib\ScriptCallback.cs">
       <Link>CordovaLib\ScriptCallback.cs</Link>
     </Compile>
+    <Compile Include="..\template\cordovalib\XHRHelper.cs">
+      <Link>CordovaLib\XHRHelper.cs</Link>
+    </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <ItemGroup>

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/CordovaWP7AppProj.csproj
----------------------------------------------------------------------
diff --git a/wp7/template/CordovaWP7AppProj.csproj b/wp7/template/CordovaWP7AppProj.csproj
index 2307284..f52ae1e 100644
--- a/wp7/template/CordovaWP7AppProj.csproj
+++ b/wp7/template/CordovaWP7AppProj.csproj
@@ -93,15 +93,14 @@
       <DependentUpon>CordovaView.xaml</DependentUpon>
     </Compile>
     <Compile Include="cordovalib\DOMStorageHelper.cs" />
+    <Compile Include="cordovalib\IBrowserDecorator.cs" />
     <Compile Include="cordovalib\ImageExifHelper.cs" />
     <Compile Include="cordovalib\JSON\JsonHelper.cs" />
     <Compile Include="cordovalib\NativeExecution.cs" />
     <Compile Include="cordovalib\OrientationHelper.cs" />
     <Compile Include="cordovalib\PluginResult.cs" />
     <Compile Include="cordovalib\ScriptCallback.cs" />
-    <Compile Include="cordovalib\MimeTypeMapper.cs" />
-    <Compile Include="cordovalib\DebugConsole.cs" />
-    <Compile Include="cordovalib\XHRProxy.cs" />
+    <Compile Include="cordovalib\XHRHelper.cs" />
     <Compile Include="MainPage.xaml.cs">
       <DependentUpon>MainPage.xaml</DependentUpon>
     </Compile>

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/MyTemplate.vstemplate
----------------------------------------------------------------------
diff --git a/wp7/template/MyTemplate.vstemplate b/wp7/template/MyTemplate.vstemplate
index 8494316..e3ed91a 100644
--- a/wp7/template/MyTemplate.vstemplate
+++ b/wp7/template/MyTemplate.vstemplate
@@ -1,6 +1,6 @@
 <VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
   <TemplateData>
-    <Name>CordovaWP7_0_0_0
+    <Name>CordovaWP7_9_9_9
 
 
 </Name>
@@ -10,10 +10,7 @@
     </ProjectSubType>
     <SortOrder>1000</SortOrder>
     <CreateNewFolder>true</CreateNewFolder>
-    <DefaultName>CordovaWP7_0_0_0
-
-
-</DefaultName>
+    <DefaultName>CordovaWP7_9_9_9</DefaultName>
     <ProvideDefaultName>true</ProvideDefaultName>
     <LocationField>Enabled</LocationField>
     <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
@@ -57,6 +54,7 @@
         <ProjectItem ReplaceParameters="true" TargetFileName="CordovaView.xaml">CordovaView.xaml</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="CordovaView.xaml.cs">CordovaView.xaml.cs</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="DOMStorageHelper.cs">DOMStorageHelper.cs</ProjectItem>
+        <ProjectItem ReplaceParameters="true" TargetFileName="IBrowserDecorator.cs">IBrowserDecorator.cs</ProjectItem>        
         <ProjectItem ReplaceParameters="true" TargetFileName="ImageExifHelper.cs">ImageExifHelper.cs</ProjectItem>
         <Folder Name="JSON" TargetFolderName="JSON">
           <ProjectItem ReplaceParameters="true" TargetFileName="JsonHelper.cs">JsonHelper.cs</ProjectItem>
@@ -65,7 +63,7 @@
         <ProjectItem ReplaceParameters="true" TargetFileName="OrientationHelper.cs">OrientationHelper.cs</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="PluginResult.cs">PluginResult.cs</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="ScriptCallback.cs">ScriptCallback.cs</ProjectItem>
-        <ProjectItem ReplaceParameters="true" TargetFileName="XHRProxy.cs">XHRProxy.cs</ProjectItem>
+        <ProjectItem ReplaceParameters="true" TargetFileName="XHRHelper.cs">XHRHelper.cs</ProjectItem>
       </Folder>
       <ProjectItem ReplaceParameters="true" TargetFileName="CordovaSourceDictionary.xml">CordovaSourceDictionary.xml</ProjectItem>
       <Folder Name="Images" TargetFolderName="Images">

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/cordovalib/CordovaView.xaml.cs
----------------------------------------------------------------------
diff --git a/wp7/template/cordovalib/CordovaView.xaml.cs b/wp7/template/cordovalib/CordovaView.xaml.cs
index 1180776..ba9ee49 100644
--- a/wp7/template/cordovalib/CordovaView.xaml.cs
+++ b/wp7/template/cordovalib/CordovaView.xaml.cs
@@ -75,12 +75,10 @@ namespace WPCordovaClassLib
 
         protected BrowserMouseHelper bmHelper;
 
-        protected DOMStorageHelper domStorageHelper;
-        protected OrientationHelper orientationHelper;
-        protected XHRProxy xhrProxy;
-
         private ConfigHandler configHandler;
 
+        private Dictionary<string, IBrowserDecorator> browserDecorators;
+
         public System.Windows.Controls.Grid _LayoutRoot
         {
             get
@@ -165,10 +163,31 @@ namespace WPCordovaClassLib
                 }
             }  
 
+                                                                      
+            browserDecorators = new Dictionary<string, IBrowserDecorator>();
+
             // initializes native execution logic
             nativeExecution = new NativeExecution(ref this.CordovaBrowser);
             bmHelper = new BrowserMouseHelper(ref this.CordovaBrowser);
-            xhrProxy = new XHRProxy(ref this.CordovaBrowser);
+
+            CreateDecorators();
+        }
+
+        /*
+         *   browserDecorators are a collection of plugin-like classes (IBrowserDecorator) that add some bit of functionality to the browser.
+         *   These are somewhat different than plugins in that they are usually not async and patch a browser feature that we would 
+         *   already expect to have.  Essentially these are browser polyfills that are patched from the outside in.
+         * */
+        void CreateDecorators()
+        {
+            XHRHelper xhrProxy = new XHRHelper();
+            xhrProxy.Browser = CordovaBrowser;
+            browserDecorators.Add("XHRLOCAL", xhrProxy);
+
+            OrientationHelper orientHelper = new OrientationHelper();
+            orientHelper.Browser = CordovaBrowser;
+            browserDecorators.Add("Orientation", orientHelper);
+
         }
 
 
@@ -222,7 +241,7 @@ namespace WPCordovaClassLib
 
 
 
-            this.domStorageHelper = new DOMStorageHelper(this.CordovaBrowser);
+            //this.domStorageHelper = new DOMStorageHelper(this.CordovaBrowser);
 
             try
             {
@@ -332,9 +351,6 @@ namespace WPCordovaClassLib
                 if (page != null)
                 {
                     page.BackKeyPress += new EventHandler<CancelEventArgs>(page_BackKeyPress);
-
-                    this.orientationHelper = new OrientationHelper(this.CordovaBrowser, page);
-
                 }
             }
         }
@@ -427,17 +443,15 @@ namespace WPCordovaClassLib
 
             if (commandStr.IndexOf("DOMStorage") == 0)
             {
-                this.domStorageHelper.HandleStorageCommand(commandStr);
-                return;
-            }
-            else if (commandStr.IndexOf("Orientation") == 0)
-            {
-                this.orientationHelper.HandleCommand(commandStr);
+               // this.domStorageHelper.HandleStorageCommand(commandStr);
                 return;
             }
-            else if (commandStr.IndexOf("XHRLOCAL") == 0)
+
+            string commandName = commandStr.Split('/').FirstOrDefault();
+
+            if (browserDecorators.ContainsKey(commandName))
             {
-                // XHRProxy listens for this itself
+                browserDecorators[commandName].HandleCommand(commandStr);
                 return;
             }
 
@@ -497,6 +511,10 @@ namespace WPCordovaClassLib
         private void GapBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
         {
             Debug.WriteLine("GapBrowser_Navigated :: " + e.Uri.ToString());
+            foreach (IBrowserDecorator iBD in browserDecorators.Values)
+            {
+                iBD.InjectScript();
+            }
         }
 
 

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/cordovalib/DOMStorageProxy.cs
----------------------------------------------------------------------
diff --git a/wp7/template/cordovalib/DOMStorageProxy.cs b/wp7/template/cordovalib/DOMStorageProxy.cs
new file mode 100644
index 0000000..59ca4e6
--- /dev/null
+++ b/wp7/template/cordovalib/DOMStorageProxy.cs
@@ -0,0 +1,155 @@
+using Microsoft.Phone.Controls;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPCordovaClassLib.CordovaLib
+{
+    class DOMStorageProxy
+    {
+        private WebBrowser webBrowser;
+
+        public DOMStorageProxy(ref WebBrowser browser) 
+        {
+            this.webBrowser = browser;
+            browser.ScriptNotify += browser_ScriptNotify;
+        }
+
+        public void InjectScript()
+        {
+              var script = @"(function(win, doc) {
+var docDomain = null;
+try {
+    docDomain = doc.domain;
+} catch (err) {}
+
+if (!docDomain || docDomain.length === 0) {
+    var DOMStorage = function(type) {
+        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');
+        },
+        getLength: function() {
+            if (!this.keys) {
+                this.initialize();
+            }
+            return this.keys.length;
+        },
+        key: function(n) {
+            if (!this.keys) {
+                this.initialize();
+            }
+            if (n >= this.keys.length) {
+                return null;
+            } else {
+                return this.keys[n];
+            }
+        },
+        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 = window.unescape(decodeURIComponent(this._result));
+                this._result = null;
+            }
+            return retVal;
+        },
+        setItem: function(key, value) {
+            if (!this.keys) {
+                this.initialize();
+            }
+            window.external.Notify('DOMStorage/' + this._type + '/set/' + key + '/' + encodeURIComponent(window.escape(value)));
+        },
+        removeItem: function(key) {
+            if (!this.keys) {
+                this.initialize();
+            }
+            var index = this.keys.indexOf(key);
+            if (index > -1) {
+                this.keys.splice(index, 1);
+                window.external.Notify('DOMStorage/' + this._type + '/remove/' + key);
+                delete this[key];
+            }
+        },
+        clear: function() {
+            if (!this.keys) {
+                this.initialize();
+            }
+            for (var n = 0, len = this.keys.length; n < len; n++) {
+                delete this[this.keys[n]];
+            }
+            this.keys = [];
+            window.external.Notify('DOMStorage/' + this._type + '/clear/');
+        }
+    };
+    if (typeof window.localStorage === 'undefined') {
+        Object.defineProperty(window, 'localStorage', {
+            writable: false,
+            configurable: false,
+            value: new DOMStorage('localStorage')
+        });
+        window.localStorage.initialize();
+    }
+    if (typeof window.sessionStorage === 'undefined') {
+        Object.defineProperty(window, 'sessionStorage', {
+            writable: false,
+            configurable: false,
+            value: new DOMStorage('sessionStorage')
+        });
+        window.sessionStorage.initialize();
+    }
+}
+})(window, document);";
+
+              webBrowser.InvokeScript("execScript", new string[] { script });
+
+        }
+
+        void browser_ScriptNotify(object sender, NotifyEventArgs e)
+        {
+            
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/cordovalib/IBrowserDecorator.cs
----------------------------------------------------------------------
diff --git a/wp7/template/cordovalib/IBrowserDecorator.cs b/wp7/template/cordovalib/IBrowserDecorator.cs
new file mode 100644
index 0000000..14ea815
--- /dev/null
+++ b/wp7/template/cordovalib/IBrowserDecorator.cs
@@ -0,0 +1,15 @@
+using Microsoft.Phone.Controls;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace WPCordovaClassLib.CordovaLib
+{
+    interface IBrowserDecorator
+    {
+        WebBrowser Browser { get; set; }
+        void InjectScript();
+        bool HandleCommand(string cmd);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/cordovalib/OrientationHelper.cs
----------------------------------------------------------------------
diff --git a/wp7/template/cordovalib/OrientationHelper.cs b/wp7/template/cordovalib/OrientationHelper.cs
index 81a329e..5a298b2 100644
--- a/wp7/template/cordovalib/OrientationHelper.cs
+++ b/wp7/template/cordovalib/OrientationHelper.cs
@@ -23,32 +23,35 @@ using System.Windows.Media;
 using System.Windows.Media.Animation;
 using System.Windows.Shapes;
 using Microsoft.Phone.Controls;
+using WPCordovaClassLib.CordovaLib;
 
 namespace WPCordovaClassLib.Cordova
 {
-    public class OrientationHelper
+    public class OrientationHelper : IBrowserDecorator
     {
-        protected WebBrowser gapBrowser;
-        protected PhoneApplicationPage page;
-        // private PageOrientation CurrentOrientation = PageOrientation.PortraitUp;
-        //private PageOrientation[] SupportedOrientations; // TODO:
+        public WebBrowser Browser { get; set; }
 
-        public OrientationHelper(WebBrowser gapBrowser, PhoneApplicationPage gapPage)
+        public PhoneApplicationPage Page
         {
-            this.gapBrowser = gapBrowser;
-            page = gapPage;
-
-            page.OrientationChanged += new EventHandler<OrientationChangedEventArgs>(page_OrientationChanged);
-            gapBrowser.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(gapBrowser_LoadCompleted);
-
-
+            get
+            {
+                PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
+                if (frame != null)
+                {
+                    return frame.Content as PhoneApplicationPage;
+                }
+                return null;
+            }
         }
 
-        void gapBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
+        // private PageOrientation CurrentOrientation = PageOrientation.PortraitUp;
+        //private PageOrientation[] SupportedOrientations; // TODO:
+
+        public void InjectScript()
         {
             int i = 0;
 
-            switch (this.page.Orientation)
+            switch (Page.Orientation)
             {
                 case PageOrientation.Portrait: // intentional fall through
                 case PageOrientation.PortraitUp:
@@ -65,12 +68,11 @@ namespace WPCordovaClassLib.Cordova
                     i = 90;
                     break;
             }
-            // Cordova.fireEvent('orientationchange', window);
             string jsCallback = String.Format("window.orientation = {0};", i);
 
             try
             {
-                gapBrowser.InvokeScript("execScript", jsCallback);
+                Browser.InvokeScript("execScript", new string[] { jsCallback });
             }
             catch (Exception)
             {
@@ -104,23 +106,24 @@ namespace WPCordovaClassLib.Cordova
             try
             {
 
-                gapBrowser.InvokeScript("execScript", jsCallback);
+                Browser.InvokeScript("execScript", new string[] { jsCallback });
 
                 jsCallback = "var evt = document.createEvent('HTMLEvents');";
                 jsCallback += "evt.initEvent( 'orientationchange', true, false );";
                 jsCallback += "window.dispatchEvent(evt);";
                 jsCallback += "if(window.onorientationchange){window.onorientationchange(evt);}";
 
-                gapBrowser.InvokeScript("execScript", jsCallback);
+                Browser.InvokeScript("execScript", new string[] {jsCallback});
             }
             catch (Exception)
             {
             }
         }
 
-        public void HandleCommand(string commandStr)
+        public bool HandleCommand(string commandStr)
         {
-
+            // No commands are currently accepted.
+            return true;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/cordovalib/XHRHelper.cs
----------------------------------------------------------------------
diff --git a/wp7/template/cordovalib/XHRHelper.cs b/wp7/template/cordovalib/XHRHelper.cs
new file mode 100644
index 0000000..7c2fe10
--- /dev/null
+++ b/wp7/template/cordovalib/XHRHelper.cs
@@ -0,0 +1,252 @@
+using Microsoft.Phone.Controls;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Linq;
+using System.Text;
+using System.Windows;
+
+namespace WPCordovaClassLib.CordovaLib
+{
+    public class XHRHelper : IBrowserDecorator
+    {
+
+        public WebBrowser Browser { get; set; }
+        public PhoneApplicationPage Page { get; set; }
+
+        public void InjectScript() 
+        {
+
+
+            string script = @"(function(win, doc) {
+
+    var docDomain = null;
+    try {
+        docDomain = doc.domain;
+    } catch (err) {}
+
+    if (!docDomain || docDomain.length === 0) {
+
+        var aliasXHR = win.XMLHttpRequest;
+        
+        var XHRShim = function() {};
+        win.XMLHttpRequest = XHRShim;
+        XHRShim.noConflict = aliasXHR;
+        XHRShim.UNSENT = 0;
+        XHRShim.OPENED = 1;
+        XHRShim.HEADERS_RECEIVED = 2;
+        XHRShim.LOADING = 3;
+        XHRShim.DONE = 4;
+        XHRShim.prototype = {
+            isAsync: false,
+            onreadystatechange: null,
+            readyState: 0,
+            _url: '',
+            timeout: 0,
+            withCredentials: false,
+            _requestHeaders: null,
+            open: function (reqType, uri, isAsync, user, password) {
+                
+                if (uri && uri.indexOf('http') === 0) {
+                    if (!this.wrappedXHR) {
+                        this.wrappedXHR = new aliasXHR();
+                        var self = this;
+                        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
+                {
+                    this.isAsync = isAsync;
+                    this.reqType = reqType;
+                    var newUrl = uri;
+                    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;
+                if (typeof res == 'object') {
+                    res = JSON.stringify(res);
+                }
+                this.responseText = res;
+                this.responseXML = res;
+                this.changeReadyState(XHRShim.DONE);
+            },
+            onError: function(err) {
+                this.status = 404;
+                this.changeReadyState(XHRShim.DONE);
+            },
+            abort: function() {
+                if (this.wrappedXHR) {
+                    return this.wrappedXHR.abort();
+                }
+            },
+            send: function(data) {
+                if (this.wrappedXHR) {
+                    return this.wrappedXHR.send(data);
+                } 
+                else {
+                    this.changeReadyState(XHRShim.OPENED);
+                    var alias = this;
+                    var funk = function () {
+                        window.__onXHRLocalCallback = function (responseCode, responseText) {
+                            alias.status = responseCode;
+                            if (responseCode == '200') {
+                                alias.responseText = responseText;
+                            }
+                            else {
+                                alias.onerror && alias.onerror(responseCode);
+                            }
+
+                            alias.changeReadyState(XHRShim.DONE);
+                            alias.onload && alias.onload();
+                            
+                        }
+                        alias.changeReadyState(XHRShim.LOADING);
+                        window.external.Notify('XHRLOCAL/' + alias._url); 
+                    }
+                    if (this.isAsync) {
+                        setTimeout(funk, 0);
+                    }
+                    else {
+                        funk();
+                    }
+                }
+            },
+            getContentLocation: function() {
+                if (window.contentLocation === undefined) {
+                    window.contentLocation = navigator.userAgent.toUpperCase().indexOf('MSIE 10') > -1 ? this.contentLocation.RESOURCES : this.contentLocation.ISOLATED_STORAGE;
+                }
+                return window.contentLocation;
+            },
+            contentLocation: {
+                ISOLATED_STORAGE: 0,
+                RESOURCES: 1
+            },
+            status: 404
+        };
+    }
+})(window, document); ";
+
+
+            Browser.InvokeScript("execScript", new string[] { script });
+        }
+
+        public bool HandleCommand(string commandStr) 
+        {
+            if (commandStr.IndexOf("XHRLOCAL") == 0)
+            {
+                string url = commandStr.Replace("XHRLOCAL/", "");
+
+                Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (isoFile.FileExists(uri.AbsolutePath))
+                    {
+                        using (TextReader reader = new StreamReader(isoFile.OpenFile(uri.AbsolutePath, FileMode.Open, FileAccess.Read)))
+                        {
+                            string text = reader.ReadToEnd();
+                            Browser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
+                            return true;
+                        }
+                    }       
+                }
+
+                Uri relUri = new Uri(uri.AbsolutePath,UriKind.Relative);
+                
+                var resource = Application.GetResourceStream(relUri);
+
+                if (resource == null)
+                {
+                    // 404 ? 
+                    Browser.InvokeScript("__onXHRLocalCallback", new string[] { "404" });
+                    return true;
+                }
+                else 
+                {
+                    using (StreamReader streamReader = new StreamReader(resource.Stream))
+                    {
+                        string text = streamReader.ReadToEnd();
+                        Browser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp7/template/cordovalib/XHRProxy.cs
----------------------------------------------------------------------
diff --git a/wp7/template/cordovalib/XHRProxy.cs b/wp7/template/cordovalib/XHRProxy.cs
deleted file mode 100644
index c5dfe0a..0000000
--- a/wp7/template/cordovalib/XHRProxy.cs
+++ /dev/null
@@ -1,261 +0,0 @@
-using Microsoft.Phone.Controls;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.IO.IsolatedStorage;
-using System.Linq;
-using System.Text;
-using System.Windows;
-
-namespace WPCordovaClassLib.CordovaLib
-{
-    public class XHRProxy
-    {
-
-        private WebBrowser webBrowser;
-
-        public XHRProxy(ref WebBrowser browser) 
-        {
-            this.webBrowser = browser;
-            browser.ScriptNotify += browser_ScriptNotify;
-            browser.Navigated += browser_Navigated;
-        }
-
-        void browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
-        {
-
-
-            string script = @"(function(win, doc) {
-
-    var docDomain = null;
-    try {
-        docDomain = doc.domain;
-    } catch (err) {}
-
-    if (!docDomain || docDomain.length === 0) {
-
-        var aliasXHR = win.XMLHttpRequest;
-        
-        var XHRShim = function() {};
-        win.XMLHttpRequest = XHRShim;
-        XHRShim.noConflict = aliasXHR;
-        XHRShim.UNSENT = 0;
-        XHRShim.OPENED = 1;
-        XHRShim.HEADERS_RECEIVED = 2;
-        XHRShim.LOADING = 3;
-        XHRShim.DONE = 4;
-        XHRShim.prototype = {
-            isAsync: false,
-            onreadystatechange: null,
-            readyState: 0,
-            _url: '',
-            timeout: 0,
-            withCredentials: false,
-            _requestHeaders: null,
-            open: function (reqType, uri, isAsync, user, password) {
-                
-                if (uri && uri.indexOf('http') === 0) {
-                    if (!this.wrappedXHR) {
-                        this.wrappedXHR = new aliasXHR();
-                        var self = this;
-                        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
-                {
-                    this.isAsync = isAsync;
-                    this.reqType = reqType;
-                    var newUrl = uri;
-                    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;
-                if (typeof res == 'object') {
-                    res = JSON.stringify(res);
-                }
-                this.responseText = res;
-                this.responseXML = res;
-                this.changeReadyState(XHRShim.DONE);
-            },
-            onError: function(err) {
-                this.status = 404;
-                this.changeReadyState(XHRShim.DONE);
-            },
-            abort: function() {
-                if (this.wrappedXHR) {
-                    return this.wrappedXHR.abort();
-                }
-            },
-            send: function(data) {
-                if (this.wrappedXHR) {
-                    return this.wrappedXHR.send(data);
-                } 
-                else {
-                    this.changeReadyState(XHRShim.OPENED);
-                    var alias = this;
-                    var funk = function () {
-                        window.__onXHRLocalCallback = function (responseCode, responseText) {
-                            alias.status = responseCode;
-                            if (responseCode == '200') {
-                                alias.responseText = responseText;
-                            }
-                            else {
-                                alias.onerror && alias.onerror(responseCode);
-                            }
-
-                            alias.changeReadyState(XHRShim.DONE);
-                            alias.onload && alias.onload();
-                            
-                        }
-                        alias.changeReadyState(XHRShim.LOADING);
-                        window.external.Notify('XHRLOCAL/' + alias._url); 
-                    }
-                    if (this.isAsync) {
-                        setTimeout(funk, 0);
-                    }
-                    else {
-                        funk();
-                    }
-                }
-            },
-            getContentLocation: function() {
-                if (window.contentLocation === undefined) {
-                    window.contentLocation = navigator.userAgent.toUpperCase().indexOf('MSIE 10') > -1 ? this.contentLocation.RESOURCES : this.contentLocation.ISOLATED_STORAGE;
-                }
-                return window.contentLocation;
-            },
-            contentLocation: {
-                ISOLATED_STORAGE: 0,
-                RESOURCES: 1
-            },
-            status: 404
-        };
-    }
-})(window, document); ";
-
-
-            webBrowser.InvokeScript("execScript", new string[] { script });
-
-
-        }
-
-        void browser_ScriptNotify(object sender, NotifyEventArgs e)
-        {
-            Debug.WriteLine("ScriptNotify::" + e.Value);
-            string commandStr = e.Value;
-
-            if (commandStr.IndexOf("XHRLOCAL") == 0)
-            {
-                string url = commandStr.Replace("XHRLOCAL/", "");
-
-                Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
-
-                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
-                {
-                    if (isoFile.FileExists(uri.AbsolutePath))
-                    {
-                        using (TextReader reader = new StreamReader(isoFile.OpenFile(uri.AbsolutePath, FileMode.Open, FileAccess.Read)))
-                        {
-                            string text = reader.ReadToEnd();
-                            webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
-                            return;
-                        }
-                    }       
-                }
-
-                Uri relUri = new Uri(uri.AbsolutePath,UriKind.Relative);
-                
-                var resource = Application.GetResourceStream(relUri);
-
-                if (resource == null)
-                {
-                    // 404 ? 
-                    webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "404" });
-                    return;
-                }
-                else 
-                {
-                    using (StreamReader streamReader = new StreamReader(resource.Stream))
-                    {
-                        string text = streamReader.ReadToEnd();
-                        webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
-                        return;
-                    }
-                }
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/framework/WPCordovaClassLib.csproj
----------------------------------------------------------------------
diff --git a/wp8/framework/WPCordovaClassLib.csproj b/wp8/framework/WPCordovaClassLib.csproj
index 75ff9b9..7df678a 100644
--- a/wp8/framework/WPCordovaClassLib.csproj
+++ b/wp8/framework/WPCordovaClassLib.csproj
@@ -215,6 +215,9 @@
     <Compile Include="..\template\cordovalib\CordovaView.xaml.cs">
       <Link>CordovaLib\CordovaView.xaml.cs</Link>
     </Compile>
+    <Compile Include="..\template\cordovalib\IBrowserDecorator.cs">
+      <Link>CordovaLib\IBrowserDecorator.cs</Link>
+    </Compile>
     <Compile Include="..\template\cordovalib\JSON\JsonHelper.cs">
       <Link>CordovaLib\JSON\JsonHelper.cs</Link>
     </Compile>
@@ -230,8 +233,8 @@
     <Compile Include="..\template\cordovalib\ScriptCallback.cs">
       <Link>CordovaLib\ScriptCallback.cs</Link>
     </Compile>
-    <Compile Include="..\template\cordovalib\XHRProxy.cs">
-      <Link>CordovaLib\XHRProxy.cs</Link>
+    <Compile Include="..\template\cordovalib\XHRHelper.cs">
+      <Link>CordovaLib\XHRHelper.cs</Link>
     </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/template/CordovaWP8AppProj.csproj
----------------------------------------------------------------------
diff --git a/wp8/template/CordovaWP8AppProj.csproj b/wp8/template/CordovaWP8AppProj.csproj
index 42d81f6..af72633 100644
--- a/wp8/template/CordovaWP8AppProj.csproj
+++ b/wp8/template/CordovaWP8AppProj.csproj
@@ -131,15 +131,13 @@
     <Compile Include="cordovalib\CordovaView.xaml.cs">
       <DependentUpon>CordovaView.xaml</DependentUpon>
     </Compile>
+    <Compile Include="cordovalib\IBrowserDecorator.cs" />
     <Compile Include="cordovalib\JSON\JsonHelper.cs" />
     <Compile Include="cordovalib\NativeExecution.cs" />
     <Compile Include="cordovalib\OrientationHelper.cs" />
     <Compile Include="cordovalib\PluginResult.cs" />
     <Compile Include="cordovalib\ScriptCallback.cs" />
-    <Compile Include="cordovalib\MimeTypeMapper.cs" />
-    <Compile Include="cordovalib\DebugConsole.cs" />
-    <Compile Include="cordovalib\ImageExifHelper.cs" />
-    <Compile Include="cordovalib\XHRProxy.cs" />
+    <Compile Include="cordovalib\XHRHelper.cs" />
     <Compile Include="MainPage.xaml.cs">
       <DependentUpon>MainPage.xaml</DependentUpon>
     </Compile>

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/template/MyTemplate.vstemplate
----------------------------------------------------------------------
diff --git a/wp8/template/MyTemplate.vstemplate b/wp8/template/MyTemplate.vstemplate
index 2ba0fc6..485edae 100644
--- a/wp8/template/MyTemplate.vstemplate
+++ b/wp8/template/MyTemplate.vstemplate
@@ -1,13 +1,13 @@
 <VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
   <TemplateData>
-    <Name>CordovaWP8_0_0_0</Name>
+    <Name>CordovaWP8_9_9_9</Name>
     <Description>Starter project for building a Cordova app for Windows Phone 8 version: 0.0.0</Description>
     <ProjectType>CSharp</ProjectType>
     <ProjectSubType>
     </ProjectSubType>
     <SortOrder>1000</SortOrder>
     <CreateNewFolder>true</CreateNewFolder>
-    <DefaultName>CordovaWP8_0_0_0</DefaultName>
+    <DefaultName>CordovaWP8_9_9_9</DefaultName>
     <ProvideDefaultName>true</ProvideDefaultName>
     <LocationField>Enabled</LocationField>
     <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
@@ -51,7 +51,7 @@
         <ProjectItem ReplaceParameters="true" TargetFileName="CordovaCommandCall.cs">CordovaCommandCall.cs</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="CordovaView.xaml">CordovaView.xaml</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="CordovaView.xaml.cs">CordovaView.xaml.cs</ProjectItem>
-        <ProjectItem ReplaceParameters="true" TargetFileName="DOMStorageHelper.cs">DOMStorageHelper.cs</ProjectItem>
+        <ProjectItem ReplaceParameters="true" TargetFileName="IBrowserDecorator.cs">IBrowserDecorator.cs</ProjectItem>
         <Folder Name="JSON" TargetFolderName="JSON">
           <ProjectItem ReplaceParameters="true" TargetFileName="JsonHelper.cs">JsonHelper.cs</ProjectItem>
         </Folder>
@@ -59,7 +59,7 @@
         <ProjectItem ReplaceParameters="true" TargetFileName="OrientationHelper.cs">OrientationHelper.cs</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="PluginResult.cs">PluginResult.cs</ProjectItem>
         <ProjectItem ReplaceParameters="true" TargetFileName="ScriptCallback.cs">ScriptCallback.cs</ProjectItem>
-        <ProjectItem ReplaceParameters="true" TargetFileName="XHRProxy.cs">XHRProxy.cs</ProjectItem>
+        <ProjectItem ReplaceParameters="true" TargetFileName="XHRHelper.cs">XHRHelper.cs</ProjectItem>
       </Folder>
       <Folder Name="Images" TargetFolderName="Images">
         <ProjectItem ReplaceParameters="false" TargetFileName="appbar.back.rest.png">appbar.back.rest.png</ProjectItem>

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/template/cordovalib/CordovaView.xaml.cs
----------------------------------------------------------------------
diff --git a/wp8/template/cordovalib/CordovaView.xaml.cs b/wp8/template/cordovalib/CordovaView.xaml.cs
index 0b27fea..49e6816 100644
--- a/wp8/template/cordovalib/CordovaView.xaml.cs
+++ b/wp8/template/cordovalib/CordovaView.xaml.cs
@@ -74,11 +74,11 @@ namespace WPCordovaClassLib
         private NativeExecution nativeExecution;
 
         protected BrowserMouseHelper bmHelper;
-        protected OrientationHelper orientationHelper;
-        protected XHRProxy xhrProxy;
 
         private ConfigHandler configHandler;
 
+        private Dictionary<string, IBrowserDecorator> browserDecorators;
+
         public System.Windows.Controls.Grid _LayoutRoot
         {
             get
@@ -95,6 +95,8 @@ namespace WPCordovaClassLib
             }
         }
 
+
+
         /*
          * Setting StartPageUri only has an effect if called before the view is loaded.
          **/
@@ -175,12 +177,31 @@ namespace WPCordovaClassLib
                 }
             }
 
+            browserDecorators = new Dictionary<string, IBrowserDecorator>();
+
             nativeExecution = new NativeExecution(ref this.CordovaBrowser);
             bmHelper = new BrowserMouseHelper(ref this.CordovaBrowser);
-            xhrProxy = new XHRProxy(ref this.CordovaBrowser);
+
+
+            CreateDecorators();
         }
 
+        /*
+         *   browserDecorators are a collection of plugin-like classes (IBrowserDecorator) that add some bit of functionality to the browser.
+         *   These are somewhat different than plugins in that they are usually not async and patch a browser feature that we would 
+         *   already expect to have.  Essentially these are browser polyfills that are patched from the outside in.
+         * */
+        void CreateDecorators()
+        {
+            XHRHelper xhrProxy = new XHRHelper();
+            xhrProxy.Browser = CordovaBrowser;
+            browserDecorators.Add("XHRLOCAL", xhrProxy);
+
+            OrientationHelper orientHelper = new OrientationHelper();
+            orientHelper.Browser = CordovaBrowser;
+            browserDecorators.Add("Orientation", orientHelper);
 
+        }
 
         void AppClosing(object sender, ClosingEventArgs e)
         {
@@ -345,9 +366,6 @@ namespace WPCordovaClassLib
                 if (page != null)
                 {
                     page.BackKeyPress += new EventHandler<CancelEventArgs>(page_BackKeyPress);
-
-                    this.orientationHelper = new OrientationHelper(this.CordovaBrowser, page);
-
                 }
             }
         }
@@ -390,6 +408,7 @@ namespace WPCordovaClassLib
 
         void CordovaBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
         {
+            Debug.WriteLine("CordovaBrowser_LoadCompleted");
             string[] autoloadPlugs = this.configHandler.AutoloadPlugins;
             foreach (string plugName in autoloadPlugs)
             {
@@ -440,14 +459,11 @@ namespace WPCordovaClassLib
         {
             string commandStr = e.Value;
 
-            if (commandStr.IndexOf("Orientation") == 0)
-            {
-                this.orientationHelper.HandleCommand(commandStr);
-                return;
-            }
-            else if (commandStr.IndexOf("XHRLOCAL") == 0)
+            string commandName = commandStr.Split('/').FirstOrDefault();
+
+            if (browserDecorators.ContainsKey(commandName))
             {
-                // XHRProxy listens for this itself
+                browserDecorators[commandName].HandleCommand(commandStr);
                 return;
             }
 
@@ -505,7 +521,10 @@ namespace WPCordovaClassLib
 
         private void CordovaBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
         {
-            Debug.WriteLine("CordovaBrowser_Navigated :: " + e.Uri.ToString());
+           foreach(IBrowserDecorator iBD in browserDecorators.Values)
+           {
+               iBD.InjectScript();
+           }
         }
 
 

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/template/cordovalib/IBrowserDecorator.cs
----------------------------------------------------------------------
diff --git a/wp8/template/cordovalib/IBrowserDecorator.cs b/wp8/template/cordovalib/IBrowserDecorator.cs
new file mode 100644
index 0000000..5c51680
--- /dev/null
+++ b/wp8/template/cordovalib/IBrowserDecorator.cs
@@ -0,0 +1,16 @@
+using Microsoft.Phone.Controls;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPCordovaClassLib.CordovaLib
+{
+    interface IBrowserDecorator
+    {
+        WebBrowser Browser { get; set; }
+        void InjectScript();
+        bool HandleCommand(string cmd);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/template/cordovalib/OrientationHelper.cs
----------------------------------------------------------------------
diff --git a/wp8/template/cordovalib/OrientationHelper.cs b/wp8/template/cordovalib/OrientationHelper.cs
index 0e29b22..5a298b2 100644
--- a/wp8/template/cordovalib/OrientationHelper.cs
+++ b/wp8/template/cordovalib/OrientationHelper.cs
@@ -23,28 +23,31 @@ using System.Windows.Media;
 using System.Windows.Media.Animation;
 using System.Windows.Shapes;
 using Microsoft.Phone.Controls;
+using WPCordovaClassLib.CordovaLib;
 
 namespace WPCordovaClassLib.Cordova
 {
-    public class OrientationHelper
+    public class OrientationHelper : IBrowserDecorator
     {
-        protected WebBrowser CordovaBrowser;
-        protected PhoneApplicationPage Page;
-        // private PageOrientation CurrentOrientation = PageOrientation.PortraitUp;
-        //private PageOrientation[] SupportedOrientations; // TODO:
+        public WebBrowser Browser { get; set; }
 
-        public OrientationHelper(WebBrowser browser, PhoneApplicationPage page)
+        public PhoneApplicationPage Page
         {
-            CordovaBrowser = browser;
-            Page = page;
-
-            Page.OrientationChanged += new EventHandler<OrientationChangedEventArgs>(page_OrientationChanged);
-            CordovaBrowser.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(browser_LoadCompleted);
-
-
+            get
+            {
+                PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
+                if (frame != null)
+                {
+                    return frame.Content as PhoneApplicationPage;
+                }
+                return null;
+            }
         }
 
-        void browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
+        // private PageOrientation CurrentOrientation = PageOrientation.PortraitUp;
+        //private PageOrientation[] SupportedOrientations; // TODO:
+
+        public void InjectScript()
         {
             int i = 0;
 
@@ -65,12 +68,11 @@ namespace WPCordovaClassLib.Cordova
                     i = 90;
                     break;
             }
-            // Cordova.fireEvent('orientationchange', window);
             string jsCallback = String.Format("window.orientation = {0};", i);
 
             try
             {
-                CordovaBrowser.InvokeScript("execScript", jsCallback);
+                Browser.InvokeScript("execScript", new string[] { jsCallback });
             }
             catch (Exception)
             {
@@ -104,23 +106,24 @@ namespace WPCordovaClassLib.Cordova
             try
             {
 
-                CordovaBrowser.InvokeScript("execScript", jsCallback);
+                Browser.InvokeScript("execScript", new string[] { jsCallback });
 
                 jsCallback = "var evt = document.createEvent('HTMLEvents');";
                 jsCallback += "evt.initEvent( 'orientationchange', true, false );";
                 jsCallback += "window.dispatchEvent(evt);";
                 jsCallback += "if(window.onorientationchange){window.onorientationchange(evt);}";
 
-                CordovaBrowser.InvokeScript("execScript", jsCallback);
+                Browser.InvokeScript("execScript", new string[] {jsCallback});
             }
             catch (Exception)
             {
             }
         }
 
-        public void HandleCommand(string commandStr)
+        public bool HandleCommand(string commandStr)
         {
-
+            // No commands are currently accepted.
+            return true;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/template/cordovalib/XHRHelper.cs
----------------------------------------------------------------------
diff --git a/wp8/template/cordovalib/XHRHelper.cs b/wp8/template/cordovalib/XHRHelper.cs
new file mode 100644
index 0000000..7c2fe10
--- /dev/null
+++ b/wp8/template/cordovalib/XHRHelper.cs
@@ -0,0 +1,252 @@
+using Microsoft.Phone.Controls;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Linq;
+using System.Text;
+using System.Windows;
+
+namespace WPCordovaClassLib.CordovaLib
+{
+    public class XHRHelper : IBrowserDecorator
+    {
+
+        public WebBrowser Browser { get; set; }
+        public PhoneApplicationPage Page { get; set; }
+
+        public void InjectScript() 
+        {
+
+
+            string script = @"(function(win, doc) {
+
+    var docDomain = null;
+    try {
+        docDomain = doc.domain;
+    } catch (err) {}
+
+    if (!docDomain || docDomain.length === 0) {
+
+        var aliasXHR = win.XMLHttpRequest;
+        
+        var XHRShim = function() {};
+        win.XMLHttpRequest = XHRShim;
+        XHRShim.noConflict = aliasXHR;
+        XHRShim.UNSENT = 0;
+        XHRShim.OPENED = 1;
+        XHRShim.HEADERS_RECEIVED = 2;
+        XHRShim.LOADING = 3;
+        XHRShim.DONE = 4;
+        XHRShim.prototype = {
+            isAsync: false,
+            onreadystatechange: null,
+            readyState: 0,
+            _url: '',
+            timeout: 0,
+            withCredentials: false,
+            _requestHeaders: null,
+            open: function (reqType, uri, isAsync, user, password) {
+                
+                if (uri && uri.indexOf('http') === 0) {
+                    if (!this.wrappedXHR) {
+                        this.wrappedXHR = new aliasXHR();
+                        var self = this;
+                        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
+                {
+                    this.isAsync = isAsync;
+                    this.reqType = reqType;
+                    var newUrl = uri;
+                    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;
+                if (typeof res == 'object') {
+                    res = JSON.stringify(res);
+                }
+                this.responseText = res;
+                this.responseXML = res;
+                this.changeReadyState(XHRShim.DONE);
+            },
+            onError: function(err) {
+                this.status = 404;
+                this.changeReadyState(XHRShim.DONE);
+            },
+            abort: function() {
+                if (this.wrappedXHR) {
+                    return this.wrappedXHR.abort();
+                }
+            },
+            send: function(data) {
+                if (this.wrappedXHR) {
+                    return this.wrappedXHR.send(data);
+                } 
+                else {
+                    this.changeReadyState(XHRShim.OPENED);
+                    var alias = this;
+                    var funk = function () {
+                        window.__onXHRLocalCallback = function (responseCode, responseText) {
+                            alias.status = responseCode;
+                            if (responseCode == '200') {
+                                alias.responseText = responseText;
+                            }
+                            else {
+                                alias.onerror && alias.onerror(responseCode);
+                            }
+
+                            alias.changeReadyState(XHRShim.DONE);
+                            alias.onload && alias.onload();
+                            
+                        }
+                        alias.changeReadyState(XHRShim.LOADING);
+                        window.external.Notify('XHRLOCAL/' + alias._url); 
+                    }
+                    if (this.isAsync) {
+                        setTimeout(funk, 0);
+                    }
+                    else {
+                        funk();
+                    }
+                }
+            },
+            getContentLocation: function() {
+                if (window.contentLocation === undefined) {
+                    window.contentLocation = navigator.userAgent.toUpperCase().indexOf('MSIE 10') > -1 ? this.contentLocation.RESOURCES : this.contentLocation.ISOLATED_STORAGE;
+                }
+                return window.contentLocation;
+            },
+            contentLocation: {
+                ISOLATED_STORAGE: 0,
+                RESOURCES: 1
+            },
+            status: 404
+        };
+    }
+})(window, document); ";
+
+
+            Browser.InvokeScript("execScript", new string[] { script });
+        }
+
+        public bool HandleCommand(string commandStr) 
+        {
+            if (commandStr.IndexOf("XHRLOCAL") == 0)
+            {
+                string url = commandStr.Replace("XHRLOCAL/", "");
+
+                Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
+
+                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
+                {
+                    if (isoFile.FileExists(uri.AbsolutePath))
+                    {
+                        using (TextReader reader = new StreamReader(isoFile.OpenFile(uri.AbsolutePath, FileMode.Open, FileAccess.Read)))
+                        {
+                            string text = reader.ReadToEnd();
+                            Browser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
+                            return true;
+                        }
+                    }       
+                }
+
+                Uri relUri = new Uri(uri.AbsolutePath,UriKind.Relative);
+                
+                var resource = Application.GetResourceStream(relUri);
+
+                if (resource == null)
+                {
+                    // 404 ? 
+                    Browser.InvokeScript("__onXHRLocalCallback", new string[] { "404" });
+                    return true;
+                }
+                else 
+                {
+                    using (StreamReader streamReader = new StreamReader(resource.Stream))
+                    {
+                        string text = streamReader.ReadToEnd();
+                        Browser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/a87588d6/wp8/template/cordovalib/XHRProxy.cs
----------------------------------------------------------------------
diff --git a/wp8/template/cordovalib/XHRProxy.cs b/wp8/template/cordovalib/XHRProxy.cs
deleted file mode 100644
index c5dfe0a..0000000
--- a/wp8/template/cordovalib/XHRProxy.cs
+++ /dev/null
@@ -1,261 +0,0 @@
-using Microsoft.Phone.Controls;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.IO.IsolatedStorage;
-using System.Linq;
-using System.Text;
-using System.Windows;
-
-namespace WPCordovaClassLib.CordovaLib
-{
-    public class XHRProxy
-    {
-
-        private WebBrowser webBrowser;
-
-        public XHRProxy(ref WebBrowser browser) 
-        {
-            this.webBrowser = browser;
-            browser.ScriptNotify += browser_ScriptNotify;
-            browser.Navigated += browser_Navigated;
-        }
-
-        void browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
-        {
-
-
-            string script = @"(function(win, doc) {
-
-    var docDomain = null;
-    try {
-        docDomain = doc.domain;
-    } catch (err) {}
-
-    if (!docDomain || docDomain.length === 0) {
-
-        var aliasXHR = win.XMLHttpRequest;
-        
-        var XHRShim = function() {};
-        win.XMLHttpRequest = XHRShim;
-        XHRShim.noConflict = aliasXHR;
-        XHRShim.UNSENT = 0;
-        XHRShim.OPENED = 1;
-        XHRShim.HEADERS_RECEIVED = 2;
-        XHRShim.LOADING = 3;
-        XHRShim.DONE = 4;
-        XHRShim.prototype = {
-            isAsync: false,
-            onreadystatechange: null,
-            readyState: 0,
-            _url: '',
-            timeout: 0,
-            withCredentials: false,
-            _requestHeaders: null,
-            open: function (reqType, uri, isAsync, user, password) {
-                
-                if (uri && uri.indexOf('http') === 0) {
-                    if (!this.wrappedXHR) {
-                        this.wrappedXHR = new aliasXHR();
-                        var self = this;
-                        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
-                {
-                    this.isAsync = isAsync;
-                    this.reqType = reqType;
-                    var newUrl = uri;
-                    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;
-                if (typeof res == 'object') {
-                    res = JSON.stringify(res);
-                }
-                this.responseText = res;
-                this.responseXML = res;
-                this.changeReadyState(XHRShim.DONE);
-            },
-            onError: function(err) {
-                this.status = 404;
-                this.changeReadyState(XHRShim.DONE);
-            },
-            abort: function() {
-                if (this.wrappedXHR) {
-                    return this.wrappedXHR.abort();
-                }
-            },
-            send: function(data) {
-                if (this.wrappedXHR) {
-                    return this.wrappedXHR.send(data);
-                } 
-                else {
-                    this.changeReadyState(XHRShim.OPENED);
-                    var alias = this;
-                    var funk = function () {
-                        window.__onXHRLocalCallback = function (responseCode, responseText) {
-                            alias.status = responseCode;
-                            if (responseCode == '200') {
-                                alias.responseText = responseText;
-                            }
-                            else {
-                                alias.onerror && alias.onerror(responseCode);
-                            }
-
-                            alias.changeReadyState(XHRShim.DONE);
-                            alias.onload && alias.onload();
-                            
-                        }
-                        alias.changeReadyState(XHRShim.LOADING);
-                        window.external.Notify('XHRLOCAL/' + alias._url); 
-                    }
-                    if (this.isAsync) {
-                        setTimeout(funk, 0);
-                    }
-                    else {
-                        funk();
-                    }
-                }
-            },
-            getContentLocation: function() {
-                if (window.contentLocation === undefined) {
-                    window.contentLocation = navigator.userAgent.toUpperCase().indexOf('MSIE 10') > -1 ? this.contentLocation.RESOURCES : this.contentLocation.ISOLATED_STORAGE;
-                }
-                return window.contentLocation;
-            },
-            contentLocation: {
-                ISOLATED_STORAGE: 0,
-                RESOURCES: 1
-            },
-            status: 404
-        };
-    }
-})(window, document); ";
-
-
-            webBrowser.InvokeScript("execScript", new string[] { script });
-
-
-        }
-
-        void browser_ScriptNotify(object sender, NotifyEventArgs e)
-        {
-            Debug.WriteLine("ScriptNotify::" + e.Value);
-            string commandStr = e.Value;
-
-            if (commandStr.IndexOf("XHRLOCAL") == 0)
-            {
-                string url = commandStr.Replace("XHRLOCAL/", "");
-
-                Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
-
-                using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
-                {
-                    if (isoFile.FileExists(uri.AbsolutePath))
-                    {
-                        using (TextReader reader = new StreamReader(isoFile.OpenFile(uri.AbsolutePath, FileMode.Open, FileAccess.Read)))
-                        {
-                            string text = reader.ReadToEnd();
-                            webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
-                            return;
-                        }
-                    }       
-                }
-
-                Uri relUri = new Uri(uri.AbsolutePath,UriKind.Relative);
-                
-                var resource = Application.GetResourceStream(relUri);
-
-                if (resource == null)
-                {
-                    // 404 ? 
-                    webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "404" });
-                    return;
-                }
-                else 
-                {
-                    using (StreamReader streamReader = new StreamReader(resource.Stream))
-                    {
-                        string text = streamReader.ReadToEnd();
-                        webBrowser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
-                        return;
-                    }
-                }
-            }
-        }
-    }
-}


Mime
View raw message