You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by mw...@apache.org on 2013/05/15 22:35:53 UTC
[14/37] Add WP7 and WP8 platform files.
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/BrowserMouseHelper.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/BrowserMouseHelper.cs b/lib/cordova-wp8/templates/standalone/cordovalib/BrowserMouseHelper.cs
new file mode 100644
index 0000000..fc83e03
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/BrowserMouseHelper.cs
@@ -0,0 +1,162 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Phone.Controls;
+using System.Windows.Input;
+using System.Diagnostics;
+using System.Windows.Media;
+using System;
+using System.Collections.Generic;
+
+namespace WPCordovaClassLib
+{
+
+ /// <summary>
+ /// Suppresses pinch zoom and optionally scrolling of the WebBrowser control
+ /// </summary>
+ public class BrowserMouseHelper
+ {
+ private WebBrowser _browser;
+
+ /// <summary>
+ /// Gets or sets whether to suppress the scrolling of
+ /// the WebBrowser control;
+ /// </summary>
+ public bool ScrollDisabled {
+ get;
+ set;
+ }
+
+ private bool userScalable = true;
+ private double maxScale = 2.0;
+ private double minScale = 0.5;
+ protected Border border;
+
+ /// <summary>
+ /// Represent min delta value to consider event as a mouse move. Experimental calculated.
+ /// </summary>
+ private const int MouseMoveDeltaThreshold = 10;
+
+ public BrowserMouseHelper(ref WebBrowser browser)
+ {
+ _browser = browser;
+ browser.Loaded += new RoutedEventHandler(browser_Loaded);
+ }
+
+ private void browser_Loaded(object sender, RoutedEventArgs e)
+ {
+ var border0 = VisualTreeHelper.GetChild(_browser, 0);
+ var border1 = VisualTreeHelper.GetChild(border0, 0);
+ var panZoom = VisualTreeHelper.GetChild(border1, 0);
+ var grid = VisualTreeHelper.GetChild(panZoom, 0);
+ var grid2 = VisualTreeHelper.GetChild(grid, 0);
+ border = VisualTreeHelper.GetChild(grid2, 0) as Border;
+
+ if (border != null)
+ {
+ border.ManipulationDelta += Border_ManipulationDelta;
+ border.ManipulationCompleted += Border_ManipulationCompleted;
+ }
+
+ _browser.LoadCompleted += Browser_LoadCompleted;
+
+ }
+
+ void ParseViewportMeta()
+ {
+ string metaScript = "(function() { return document.querySelector('meta[name=viewport]').content; })()";
+
+ try
+ {
+ string metaContent = _browser.InvokeScript("eval", new string[] { metaScript }) as string;
+ string[] arr = metaContent.Split(new[] { ' ', ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
+ Dictionary<string, string> metaDictionary = new Dictionary<string, string>();
+ foreach (string val in arr)
+ {
+ string[] keyVal = val.Split('=');
+ metaDictionary.Add(keyVal[0], keyVal[1]);
+ }
+
+ this.userScalable = false; // reset to default
+ if (metaDictionary.ContainsKey("user-scalable"))
+ {
+ this.userScalable = metaDictionary["user-scalable"] == "yes";
+ }
+
+ this.maxScale = 2.0;// reset to default
+ if (metaDictionary.ContainsKey("maximum-scale"))
+ {
+ this.maxScale = double.Parse(metaDictionary["maximum-scale"]);
+ }
+
+ this.minScale = 0.5;// reset to default
+ if (metaDictionary.ContainsKey("minimum-scale"))
+ {
+ this.minScale = double.Parse(metaDictionary["minimum-scale"]);
+ }
+ }
+ catch (Exception)
+ {
+
+ }
+ }
+
+ void Browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
+ {
+ ParseViewportMeta();
+ }
+
+ #region ManipulationEvents
+
+ private void Border_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
+ {
+ //Debug.WriteLine("Border_ManipulationDelta");
+ // optionally suppress zoom
+ if ((ScrollDisabled || !userScalable) && (e.DeltaManipulation.Scale.X != 0.0 || e.DeltaManipulation.Scale.Y != 0.0))
+ {
+ e.Handled = true;
+ }
+ // optionally suppress scrolling
+ if (ScrollDisabled && (e.DeltaManipulation.Translation.X != 0.0 || e.DeltaManipulation.Translation.Y != 0.0))
+ {
+ e.Handled = true;
+ }
+ }
+
+ private void Border_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
+ {
+ //Debug.WriteLine("Border_ManipulationCompleted");
+ // suppress zoom
+ if (!userScalable && e.FinalVelocities != null)
+ {
+ if (e.FinalVelocities.ExpansionVelocity.X != 0.0 ||
+ e.FinalVelocities.ExpansionVelocity.Y != 0.0)
+ {
+ e.Handled = true;
+ }
+ }
+ }
+
+
+ #endregion
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/CommandFactory.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/CommandFactory.cs b/lib/cordova-wp8/templates/standalone/cordovalib/CommandFactory.cs
new file mode 100644
index 0000000..974ee79
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/CommandFactory.cs
@@ -0,0 +1,112 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+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.Collections.Generic;
+using WPCordovaClassLib.Cordova.Commands;
+using System.Reflection;
+using System.Diagnostics;
+
+namespace WPCordovaClassLib.Cordova
+{
+ /// <summary>
+ /// Provides functionality to create Cordova command by name.
+ /// </summary>
+ public static class CommandFactory
+ {
+ /// <summary>
+ /// Represents predefined namespace name for custom plugins
+ /// </summary>
+ private static readonly string CustomPluginNamespacePrefix = "Cordova.Extension.Commands.";
+
+ private static readonly string BaseCommandNamespacePrefix = "WPCordovaClassLib.Cordova.Commands.";
+
+ /// <summary>
+ /// Cache instantiated commands in a map.
+ /// </summary>
+
+ private static Dictionary<string, BaseCommand> commandMap = new Dictionary<string, BaseCommand>();
+
+ /// <summary>
+ /// Creates command using command class name. Returns null for unknown commands.
+ /// </summary>
+ /// <param name="service">Command class name, for example Device or Notification</param>
+ /// <returns>Command class instance or null</returns>
+ public static BaseCommand CreateByServiceName(string service)
+ {
+
+ if (string.IsNullOrEmpty(service))
+ {
+ throw new ArgumentNullException("service", "service to create can't be null");
+ }
+
+ if (!commandMap.ContainsKey(service))
+ {
+
+ Type t = Type.GetType(BaseCommandNamespacePrefix + service);
+
+ // custom plugin could be defined in own namespace and assembly
+ if (t == null)
+ {
+ string serviceFullName = service.Contains(".") ? service : CustomPluginNamespacePrefix + service;
+
+ foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ // in this case service name represents full type name including namespace
+ t = a.GetType(serviceFullName);
+
+ if (t == null) // try the Commands Namespace
+ {
+ t = a.GetType(BaseCommandNamespacePrefix + service);
+ }
+
+ if (t != null)
+ {
+ break;
+ }
+ }
+
+ }
+
+ // unknown command, still didn't find it
+ if (t == null)
+ {
+ Debug.WriteLine("Unable to locate command :: " + service);
+ return null;
+ }
+
+ commandMap[service] = Activator.CreateInstance(t) as BaseCommand;
+ }
+
+ return commandMap[service];
+ }
+
+ public static void ResetAllCommands()
+ {
+ foreach (BaseCommand bc in commandMap.Values)
+ {
+ bc.OnReset();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/Commands/BaseCommand.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/Commands/BaseCommand.cs b/lib/cordova-wp8/templates/standalone/cordovalib/Commands/BaseCommand.cs
new file mode 100644
index 0000000..9de0e4d
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/Commands/BaseCommand.cs
@@ -0,0 +1,187 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+using System;
+using System.Reflection;
+using Microsoft.Phone.Shell;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace WPCordovaClassLib.Cordova.Commands
+{
+ public abstract class BaseCommand : IDisposable
+ {
+ /*
+ * All commands + plugins must extend BaseCommand, because they are dealt with as BaseCommands in CordovaView.xaml.cs
+ *
+ **/
+
+ public event EventHandler<PluginResult> OnCommandResult;
+
+ public event EventHandler<ScriptCallback> OnCustomScript;
+
+ public string CurrentCommandCallbackId { get; set; }
+
+ public BaseCommand()
+ {
+ ResultHandlers = new Dictionary<string, EventHandler<PluginResult>>();
+ PhoneApplicationService service = PhoneApplicationService.Current;
+ service.Activated += this.OnResume;
+ service.Deactivated += this.OnPause;
+ }
+
+ protected Dictionary<string, EventHandler<PluginResult>> ResultHandlers;
+ public void AddResultHandler(string callbackId, EventHandler<PluginResult> handler)
+ {
+ ResultHandlers.Add(callbackId, handler);
+ }
+ public bool RemoveResultHandler(string callbackId)
+ {
+ return ResultHandlers.Remove(callbackId);
+ }
+
+ /*
+ * InvokeMethodNamed will call the named method of a BaseCommand subclass if it exists and pass the variable arguments list along.
+ **/
+
+ public object InvokeMethodNamed(string callbackId, string methodName, params object[] args)
+ {
+ //Debug.WriteLine(string.Format("InvokeMethodNamed:{0} callbackId:{1}",methodName,callbackId));
+ this.CurrentCommandCallbackId = callbackId;
+ return InvokeMethodNamed(methodName, args);
+ }
+
+ public object InvokeMethodNamed(string methodName, params object[] args)
+ {
+ MethodInfo mInfo = this.GetType().GetMethod(methodName);
+
+ if (mInfo != null)
+ {
+ // every function handles DispatchCommandResult by itself
+ return mInfo.Invoke(this, args);
+ }
+
+ // actually methodName could refer to a property
+ if (args == null || args.Length == 0 ||
+ (args.Length == 1 && "undefined".Equals(args[0])))
+ {
+ PropertyInfo pInfo = this.GetType().GetProperty(methodName);
+ if (pInfo != null)
+ {
+ object res = pInfo.GetValue(this, null);
+
+ DispatchCommandResult(new PluginResult(PluginResult.Status.OK, res));
+
+ return res;
+ }
+ }
+
+ throw new MissingMethodException(methodName);
+
+ }
+
+ [Obsolete]
+ public void InvokeCustomScript(ScriptCallback script, bool removeHandler)
+ {
+ if (this.OnCustomScript != null)
+ {
+ this.OnCustomScript(this, script);
+ if (removeHandler)
+ {
+ this.OnCustomScript = null;
+ }
+ }
+ }
+
+ public void DispatchCommandResult()
+ {
+ this.DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
+ }
+
+ public void DispatchCommandResult(PluginResult result,string callbackId="")
+ {
+ if (!string.IsNullOrEmpty(callbackId))
+ {
+ result.CallbackId = callbackId;
+ }
+ else
+ {
+ result.CallbackId = this.CurrentCommandCallbackId;
+ }
+
+ if (ResultHandlers.ContainsKey(result.CallbackId))
+ {
+ ResultHandlers[result.CallbackId](this, result);
+ }
+ else if (this.OnCommandResult != null)
+ {
+ OnCommandResult(this, result);
+ }
+ else
+ {
+ Debug.WriteLine("Failed to locate callback for id : " + result.CallbackId);
+ }
+
+ if (!result.KeepCallback)
+ {
+ this.Dispose();
+ }
+
+ }
+
+
+ /// <summary>
+ /// Occurs when the application is being deactivated.
+ /// </summary>
+ public virtual void OnReset() {}
+
+ /// <summary>
+ /// Occurs when the application is being loaded, and the config.xml has an autoload entry
+ /// </summary>
+ public virtual void OnInit() {}
+
+
+ /// <summary>
+ /// Occurs when the application is being deactivated.
+ /// </summary>
+ public virtual void OnPause(object sender, DeactivatedEventArgs e) {}
+
+ /// <summary>
+ /// Occurs when the application is being made active after previously being put
+ /// into a dormant state or tombstoned.
+ /// </summary>
+ public virtual void OnResume(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e) {}
+
+ public void Dispose()
+ {
+ PhoneApplicationService service = PhoneApplicationService.Current;
+ service.Activated -= this.OnResume;
+ service.Deactivated -= this.OnPause;
+ this.OnCommandResult = null;
+ }
+
+ public static string GetBaseURL()
+ {
+#if CORDOVA_CLASSLIB
+ return "/WPCordovaClassLib;component/";
+#else
+ return "./";
+#endif
+ }
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/ConfigHandler.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/ConfigHandler.cs b/lib/cordova-wp8/templates/standalone/cordovalib/ConfigHandler.cs
new file mode 100644
index 0000000..06806d3
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/ConfigHandler.cs
@@ -0,0 +1,242 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Resources;
+using System.Xml.Linq;
+
+namespace WPCordovaClassLib.CordovaLib
+{
+ class ConfigHandler
+ {
+ public class PluginConfig
+ {
+ public PluginConfig(string name, bool autoLoad = false)
+ {
+ Name = name;
+ isAutoLoad = autoLoad;
+ }
+ public string Name;
+ public bool isAutoLoad;
+ }
+
+ protected Dictionary<string, PluginConfig> AllowedPlugins;
+ protected List<string> AllowedDomains;
+ protected Dictionary<string, string> Preferences;
+
+ protected bool AllowAllDomains = false;
+ protected bool AllowAllPlugins = false;
+
+ public ConfigHandler()
+ {
+ AllowedPlugins = new Dictionary<string, PluginConfig>();
+ AllowedDomains = new List<string>();
+ Preferences = new Dictionary<string, string>();
+ }
+
+ public string GetPreference(string key)
+ {
+ return Preferences[key];
+ }
+
+ protected static string[] AllowedSchemes = { "http", "https", "ftp", "ftps" };
+ protected bool SchemeIsAllowed(string scheme)
+ {
+ return AllowedSchemes.Contains(scheme);
+ }
+
+ protected void AddWhiteListEntry(string origin, bool allowSubdomains)
+ {
+
+ if (origin == "*")
+ {
+ AllowAllDomains = true;
+ }
+
+ if (AllowAllDomains)
+ {
+ return;
+ }
+
+ string hostMatchingRegex = "";
+ string hostName;
+
+ try
+ {
+
+ Uri uri = new Uri(origin.Replace("*", "replaced-text"), UriKind.Absolute);
+
+ string tempHostName = uri.Host.Replace("replaced-text", "*");
+ //if (uri.HostNameType == UriHostNameType.Dns){}
+ // starts with wildcard match - we make the first '.' optional (so '*.org.apache.cordova' will match 'org.apache.cordova')
+ if (tempHostName.StartsWith("*."))
+ { //"(\\s{0}|*.)"
+ hostName = @"\w*.*" + tempHostName.Substring(2).Replace(".", @"\.").Replace("*", @"\w*");
+ }
+ else
+ {
+ hostName = tempHostName.Replace(".", @"\.").Replace("*", @"\w*");
+ }
+ // "^https?://"
+ hostMatchingRegex = uri.Scheme + "://" + hostName + uri.PathAndQuery;
+ Debug.WriteLine("Adding regex :: " + hostMatchingRegex);
+ AllowedDomains.Add(hostMatchingRegex);
+
+ }
+ catch (Exception)
+ {
+ Debug.WriteLine("Invalid Whitelist entry (probably missing the protocol):: " + origin);
+ }
+
+ }
+
+ /**
+
+ An access request is granted for a given URI if there exists an item inside the access-request list such that:
+
+ - The URI's scheme component is the same as scheme; and
+ - if subdomains is false or if the URI's host component is not a domain name (as defined in [RFC1034]), the URI's host component is the same as host; or
+ - if subdomains is true, the URI's host component is either the same as host, or is a subdomain of host (as defined in [RFC1034]); and
+ - the URI's port component is the same as port.
+
+ **/
+
+ public bool URLIsAllowed(string url)
+ {
+ // Debug.WriteLine("Testing URLIsAllowed : " + url);
+ // easy case first
+ if (this.AllowAllDomains)
+ {
+ return true;
+ }
+ else
+ {
+ // start simple
+ Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
+ if (uri.IsAbsoluteUri)
+ {
+ if (this.SchemeIsAllowed(uri.Scheme))
+ {
+ // additional test because our pattern will always have a trailing '/'
+ string matchUrl = url;
+ if (uri.PathAndQuery == "/")
+ {
+ matchUrl = url + "/";
+ }
+ foreach (string pattern in AllowedDomains)
+ {
+ if (Regex.IsMatch(matchUrl, pattern))
+ {
+ // make sure it is at the start, and not part of the query string
+ // special case :: http://some.other.domain/page.html?x=1&g=http://build.apache.org/
+ if (Regex.IsMatch(uri.Scheme + "://" + uri.Host + "/", pattern) ||
+ (!Regex.IsMatch(uri.PathAndQuery, pattern)))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsPluginAllowed(string key)
+ {
+ return AllowAllPlugins || AllowedPlugins.Keys.Contains(key);
+ }
+
+ public string[] AutoloadPlugins
+ {
+ get
+ {
+ var res = from results in AllowedPlugins.TakeWhile(p => p.Value.isAutoLoad)
+ select results.Value.Name;
+
+ foreach (var s in res)
+ {
+ Debug.WriteLine(s);
+ }
+ //string[] res = from results in (AllowedPlugins.Where(p => p.Value.isAutoLoad) )
+ // select (string)results.Key;
+
+ return new string[] { "", "asd" };
+ }
+ }
+
+
+ public void LoadAppPackageConfig()
+ {
+ StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("config.xml", UriKind.Relative));
+
+ if (streamInfo != null)
+ {
+ StreamReader sr = new StreamReader(streamInfo.Stream);
+ //This will Read Keys Collection for the xml file
+ XDocument document = XDocument.Parse(sr.ReadToEnd());
+
+ var plugins = from results in document.Descendants("plugin")
+ select new
+ {
+ name = (string)results.Attribute("name"),
+ autoLoad = results.Attribute("onload")
+ };
+
+ foreach (var plugin in plugins)
+ {
+ Debug.WriteLine("plugin " + plugin.name);
+ PluginConfig pConfig = new PluginConfig(plugin.name, plugin.autoLoad != null && plugin.autoLoad.Value == "true");
+ if (pConfig.Name == "*")
+ {
+ AllowAllPlugins = true;
+ // break; wait, don't, some still could be autoload
+ }
+ else
+ {
+ AllowedPlugins.Add(pConfig.Name, pConfig);
+ }
+ }
+
+ var preferences = from results in document.Descendants("preference")
+ select new
+ {
+ name = (string)results.Attribute("name"),
+ value = (string)results.Attribute("value")
+ };
+
+ foreach (var pref in preferences)
+ {
+ Debug.WriteLine("pref" + pref.name + ", " + pref.value);
+ }
+
+ var accessList = from results in document.Descendants("access")
+ select new
+ {
+ origin = (string)results.Attribute("origin"),
+ subdomains = (string)results.Attribute("subdomains") == "true"
+ };
+
+ foreach (var accessElem in accessList)
+ {
+ AddWhiteListEntry(accessElem.origin, accessElem.subdomains);
+ }
+ }
+ else
+ {
+ // no config.xml, allow all
+ AllowAllDomains = true;
+ AllowAllPlugins = true;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/CordovaCommandCall.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/CordovaCommandCall.cs b/lib/cordova-wp8/templates/standalone/cordovalib/CordovaCommandCall.cs
new file mode 100644
index 0000000..facc991
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/CordovaCommandCall.cs
@@ -0,0 +1,99 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+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.Linq;
+using System.Collections.Generic;
+
+namespace WPCordovaClassLib.Cordova
+{
+ /// <summary>
+ /// Represents Cordova native command call: action callback, etc
+ /// </summary>
+ public class CordovaCommandCall
+ {
+ public String Service { get; private set; }
+ public String Action { get; private set; }
+ public String CallbackId { get; private set; }
+ public String Args { get; private set; }
+
+ /// <summary>
+ /// Retrieves command call parameters and creates wrapper for them
+ /// </summary>
+ /// <param name="commandStr">Command string in the form 'service/action/callback/args'</param>
+ /// <returns>New class instance or null of string does not represent Cordova command</returns>
+ public static CordovaCommandCall Parse(string commandStr)
+ {
+ System.Diagnostics.Debug.WriteLine("CommandString : " + commandStr);
+ if (string.IsNullOrEmpty(commandStr))
+ {
+ return null;
+ }
+
+ string[] split = commandStr.Split('/');
+ if (split.Length < 3)
+ {
+ return null;
+ }
+
+ CordovaCommandCall commandCallParameters = new CordovaCommandCall();
+ commandCallParameters.Service = split[0];
+ commandCallParameters.Action = split[1];
+ commandCallParameters.CallbackId = split[2];
+
+ try
+ {
+ string arg = split.Length <= 3 ? "[]" : String.Join("/", split.Skip(3));
+ if (!arg.StartsWith("[")) // save the exception
+ {
+ arg = string.Format("[{0}]", arg);
+ }
+ List<string> args = JSON.JsonHelper.Deserialize<List<string>>(arg);
+ args.Add(commandCallParameters.CallbackId);
+ commandCallParameters.Args = JSON.JsonHelper.Serialize(args.ToArray());
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ // sanity check for illegal names
+ // was failing with ::
+ // CordovaCommandResult :: 1, Device1, {"status":1,"message":"{\"name\":\"XD.....
+ if (commandCallParameters.Service.IndexOfAny(new char[] { '@', ':', ',', '!', ' ' }) > -1)
+ {
+ return null;
+ }
+
+ return commandCallParameters;
+ }
+
+
+ /// <summary>
+ /// Private ctr to disable class creation.
+ /// New class instance must be initialized via CordovaCommandCall.Parse static method.
+ /// </summary>
+ private CordovaCommandCall() { }
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml b/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml
new file mode 100644
index 0000000..41d7631
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml
@@ -0,0 +1,65 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<UserControl x:Class="WPCordovaClassLib.CordovaView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d"
+ FontFamily="{StaticResource PhoneFontFamilyNormal}"
+ FontSize="{StaticResource PhoneFontSizeNormal}"
+ Foreground="{StaticResource PhoneForegroundBrush}"
+ d:DesignHeight="480" d:DesignWidth="480"
+ xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone">
+
+ <Grid x:Name="LayoutRoot" Background="Transparent">
+
+ <phone:WebBrowser x:Name="CordovaBrowser"
+ Opacity="0"
+ HorizontalAlignment="Stretch"
+ VerticalAlignment="Stretch"
+ IsScriptEnabled="True"
+ Foreground="White"
+ Background="Black"
+ Navigated="CordovaBrowser_Navigated"
+ Loaded="CordovaBrowser_Loaded"
+ Unloaded="CordovaBrowser_Unloaded"
+ ScriptNotify="CordovaBrowser_ScriptNotify"
+ LoadCompleted="CordovaBrowser_LoadCompleted"
+ Navigating="CordovaBrowser_Navigating"
+ NavigationFailed="CordovaBrowser_NavigationFailed"
+ IsGeolocationEnabled="True">
+ <phone:WebBrowser.Projection>
+ <PlaneProjection x:Name="BrowserProjector" CenterOfRotationX="0" RotationY="-180"/>
+ </phone:WebBrowser.Projection>
+ <phone:WebBrowser.Resources>
+ <Storyboard x:Name="RotateIn" BeginTime="0:0:0.5">
+ <DoubleAnimation
+ Storyboard.TargetName="BrowserProjector"
+ Storyboard.TargetProperty="RotationY"
+ To="0" Duration="0:0:0.6"/>
+ </Storyboard>
+ </phone:WebBrowser.Resources>
+
+ </phone:WebBrowser>
+
+ </Grid>
+</UserControl>
+
+
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml.cs b/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml.cs
new file mode 100644
index 0000000..7b92f65
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/CordovaView.xaml.cs
@@ -0,0 +1,503 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using Microsoft.Phone.Controls;
+using System.IO.IsolatedStorage;
+using System.Windows.Resources;
+using System.Windows.Interop;
+using System.Runtime.Serialization.Json;
+using System.IO;
+using System.ComponentModel;
+using System.Xml.Linq;
+using WPCordovaClassLib.Cordova.Commands;
+using System.Diagnostics;
+using System.Text;
+using WPCordovaClassLib.Cordova;
+using System.Threading;
+using Microsoft.Phone.Shell;
+using WPCordovaClassLib.Cordova.JSON;
+using WPCordovaClassLib.CordovaLib;
+
+
+
+namespace WPCordovaClassLib
+{
+ public partial class CordovaView : UserControl
+ {
+
+ /// <summary>
+ /// Indicates whether web control has been loaded and no additional initialization is needed.
+ /// Prevents data clearing during page transitions.
+ /// </summary>
+ private bool IsBrowserInitialized = false;
+
+ /// <summary>
+ /// Set when the user attaches a back button handler inside the WebBrowser
+ /// </summary>
+ private bool OverrideBackButton = false;
+
+ /// <summary>
+ /// Sentinal to keep track of page changes as a result of the hardware back button
+ /// Set to false when the back-button is pressed, which calls js window.history.back()
+ /// If the page changes as a result of the back button the event is cancelled.
+ /// </summary>
+ private bool PageDidChange = false;
+
+ private static string AppRoot = "";
+
+
+ /// <summary>
+ /// Handles native api calls
+ /// </summary>
+ private NativeExecution nativeExecution;
+
+ protected BrowserMouseHelper bmHelper;
+ protected DOMStorageHelper domStorageHelper;
+ protected OrientationHelper orientationHelper;
+
+ private ConfigHandler configHandler;
+
+ public System.Windows.Controls.Grid _LayoutRoot
+ {
+ get
+ {
+ return ((System.Windows.Controls.Grid)(this.FindName("LayoutRoot")));
+ }
+ }
+
+ public WebBrowser Browser
+ {
+ get
+ {
+ return CordovaBrowser;
+ }
+ }
+
+ /*
+ * Setting StartPageUri only has an effect if called before the view is loaded.
+ **/
+ protected Uri _startPageUri = null;
+ public Uri StartPageUri
+ {
+ get
+ {
+ if (_startPageUri == null)
+ {
+ // default
+ return new Uri(AppRoot + "www/index.html", UriKind.Relative);
+ }
+ else
+ {
+ return _startPageUri;
+ }
+ }
+ set
+ {
+ if (!this.IsBrowserInitialized)
+ {
+ _startPageUri = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether to suppress bouncy scrolling of
+ /// the WebBrowser control;
+ /// </summary>
+ public bool DisableBouncyScrolling
+ {
+ get;
+ set;
+ }
+
+ public CordovaView()
+ {
+
+ InitializeComponent();
+
+ if (DesignerProperties.IsInDesignTool)
+ {
+ return;
+ }
+
+
+ StartupMode mode = PhoneApplicationService.Current.StartupMode;
+
+ if (mode == StartupMode.Launch)
+ {
+ PhoneApplicationService service = PhoneApplicationService.Current;
+ service.Activated += new EventHandler<Microsoft.Phone.Shell.ActivatedEventArgs>(AppActivated);
+ service.Launching += new EventHandler<LaunchingEventArgs>(AppLaunching);
+ service.Deactivated += new EventHandler<DeactivatedEventArgs>(AppDeactivated);
+ service.Closing += new EventHandler<ClosingEventArgs>(AppClosing);
+ }
+ else
+ {
+
+ }
+
+ // initializes native execution logic
+ configHandler = new ConfigHandler();
+ configHandler.LoadAppPackageConfig();
+
+ nativeExecution = new NativeExecution(ref this.CordovaBrowser);
+ bmHelper = new BrowserMouseHelper(ref this.CordovaBrowser);
+ }
+
+
+
+ void AppClosing(object sender, ClosingEventArgs e)
+ {
+ Debug.WriteLine("AppClosing");
+ }
+
+ void AppDeactivated(object sender, DeactivatedEventArgs e)
+ {
+ Debug.WriteLine("INFO: AppDeactivated");
+
+ try
+ {
+ CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('pause');" });
+ }
+ catch (Exception)
+ {
+ Debug.WriteLine("ERROR: Pause event error");
+ }
+ }
+
+ void AppLaunching(object sender, LaunchingEventArgs e)
+ {
+ Debug.WriteLine("INFO: AppLaunching");
+ }
+
+ void AppActivated(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
+ {
+ Debug.WriteLine("INFO: AppActivated");
+ try
+ {
+ CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('resume');" });
+ }
+ catch (Exception)
+ {
+ Debug.WriteLine("ERROR: Resume event error");
+ }
+ }
+
+ void CordovaBrowser_Loaded(object sender, RoutedEventArgs e)
+ {
+ this.bmHelper.ScrollDisabled = this.DisableBouncyScrolling;
+
+ if (DesignerProperties.IsInDesignTool)
+ {
+ return;
+ }
+
+ // prevents refreshing web control to initial state during pages transitions
+ if (this.IsBrowserInitialized) return;
+
+
+
+ this.domStorageHelper = new DOMStorageHelper(this.CordovaBrowser);
+
+ try
+ {
+
+ // Before we possibly clean the ISO-Store, we need to grab our generated UUID, so we can rewrite it after.
+ string deviceUUID = "";
+
+ using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
+ {
+ try
+ {
+ IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Open, FileAccess.Read, appStorage);
+
+ using (StreamReader reader = new StreamReader(fileStream))
+ {
+ deviceUUID = reader.ReadLine();
+ }
+ }
+ catch (Exception /*ex*/)
+ {
+ deviceUUID = Guid.NewGuid().ToString();
+ }
+
+ Debug.WriteLine("Updating IsolatedStorage for APP:DeviceID :: " + deviceUUID);
+ IsolatedStorageFileStream file = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Create, FileAccess.Write, appStorage);
+ using (StreamWriter writeFile = new StreamWriter(file))
+ {
+ writeFile.WriteLine(deviceUUID);
+ writeFile.Close();
+ }
+
+ }
+
+ /*
+ * 11/08/12 Ruslan Kokorev
+ * Copying files to isolated storage is no more required in WP8. WebBrowser control now works with files located in XAP.
+ */
+
+ //StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("CordovaSourceDictionary.xml", UriKind.Relative));
+
+ //if (streamInfo != null)
+ //{
+ // StreamReader sr = new StreamReader(streamInfo.Stream);
+ // //This will Read Keys Collection for the xml file
+
+ // XDocument document = XDocument.Parse(sr.ReadToEnd());
+
+ // var files = from results in document.Descendants("FilePath")
+ // select new
+ // {
+ // path = (string)results.Attribute("Value")
+ // };
+ // StreamResourceInfo fileResourceStreamInfo;
+
+ // using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
+ // {
+
+ // foreach (var file in files)
+ // {
+ // fileResourceStreamInfo = Application.GetResourceStream(new Uri(file.path, UriKind.Relative));
+
+ // if (fileResourceStreamInfo != null)
+ // {
+ // using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream))
+ // {
+ // byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);
+
+ // string strBaseDir = AppRoot + file.path.Substring(0, file.path.LastIndexOf(System.IO.Path.DirectorySeparatorChar));
+
+ // if (!appStorage.DirectoryExists(strBaseDir))
+ // {
+ // Debug.WriteLine("INFO: Creating Directory :: " + strBaseDir);
+ // appStorage.CreateDirectory(strBaseDir);
+ // }
+
+ // // This will truncate/overwrite an existing file, or
+ // using (IsolatedStorageFileStream outFile = appStorage.OpenFile(AppRoot + file.path, FileMode.Create))
+ // {
+ // Debug.WriteLine("INFO: Writing data for " + AppRoot + file.path + " and length = " + data.Length);
+ // using (var writer = new BinaryWriter(outFile))
+ // {
+ // writer.Write(data);
+ // }
+ // }
+ // }
+ // }
+ // else
+ // {
+ // Debug.WriteLine("ERROR: Failed to write file :: " + file.path + " did you forget to add it to the project?");
+ // }
+ // }
+ // }
+ //}
+
+ CordovaBrowser.Navigate(StartPageUri);
+ IsBrowserInitialized = true;
+ AttachHardwareButtonHandlers();
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("ERROR: Exception in CordovaBrowser_Loaded :: {0}", ex.Message);
+ }
+ }
+
+ void AttachHardwareButtonHandlers()
+ {
+ PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
+ if (frame != null)
+ {
+ PhoneApplicationPage page = frame.Content as PhoneApplicationPage;
+
+ if (page != null)
+ {
+ page.BackKeyPress += new EventHandler<CancelEventArgs>(page_BackKeyPress);
+
+ this.orientationHelper = new OrientationHelper(this.CordovaBrowser, page);
+
+ }
+ }
+ }
+
+ void page_BackKeyPress(object sender, CancelEventArgs e)
+ {
+
+ if (OverrideBackButton)
+ {
+ try
+ {
+ CordovaBrowser.InvokeScript("eval", new string[] { "cordova.fireDocumentEvent('backbutton');" });
+ e.Cancel = true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Exception while invoking backbutton into cordova view: " + ex.Message);
+ }
+ }
+ else
+ {
+ try
+ {
+ PageDidChange = false;
+
+ Uri uriBefore = this.Browser.Source;
+ // calling js history.back with result in a page change if history was valid.
+ CordovaBrowser.InvokeScript("eval", new string[] { "(function(){window.history.back();})()" });
+
+ Uri uriAfter = this.Browser.Source;
+
+ e.Cancel = PageDidChange || (uriBefore != uriAfter);
+ }
+ catch (Exception)
+ {
+ e.Cancel = false; // exit the app ... ?
+ }
+ }
+ }
+
+ void CordovaBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
+ {
+ string[] autoloadPlugs = this.configHandler.AutoloadPlugins;
+ foreach (string plugName in autoloadPlugs)
+ {
+ // nativeExecution.ProcessCommand(commandCallParams);
+ }
+
+ string nativeReady = "(function(){ cordova.require('cordova/channel').onNativeReady.fire()})();";
+
+ try
+ {
+ CordovaBrowser.InvokeScript("execScript", new string[] { nativeReady });
+ }
+ catch (Exception /*ex*/)
+ {
+ Debug.WriteLine("Error calling js to fire nativeReady event. Did you include cordova-x.x.x.js in your html script tag?");
+ }
+
+ if (this.CordovaBrowser.Opacity < 1)
+ {
+ this.CordovaBrowser.Opacity = 1;
+ RotateIn.Begin();
+ }
+ }
+
+
+ void CordovaBrowser_Navigating(object sender, NavigatingEventArgs e)
+ {
+ if (!configHandler.URLIsAllowed(e.Uri.ToString()))
+ {
+ Debug.WriteLine("Whitelist exception: Stopping browser from navigating to :: " + e.Uri.ToString());
+ e.Cancel = true;
+ return;
+ }
+
+ this.PageDidChange = true;
+ this.nativeExecution.ResetAllCommands();
+ }
+
+ /*
+ * This method does the work of routing commands
+ * NotifyEventArgs.Value contains a string passed from JS
+ * If the command already exists in our map, we will just attempt to call the method(action) specified, and pass the args along
+ * Otherwise, we create a new instance of the command, add it to the map, and call it ...
+ * This method may also receive JS error messages caught by window.onerror, in any case where the commandStr does not appear to be a valid command
+ * it is simply output to the debugger output, and the method returns.
+ *
+ **/
+ void CordovaBrowser_ScriptNotify(object sender, NotifyEventArgs e)
+ {
+ string commandStr = e.Value;
+
+ if (commandStr.IndexOf("DOMStorage") == 0)
+ {
+ this.domStorageHelper.HandleStorageCommand(commandStr);
+ return;
+ }
+ else if (commandStr.IndexOf("Orientation") == 0)
+ {
+ this.orientationHelper.HandleCommand(commandStr);
+ return;
+ }
+
+ CordovaCommandCall commandCallParams = CordovaCommandCall.Parse(commandStr);
+
+ if (commandCallParams == null)
+ {
+ // ERROR
+ Debug.WriteLine("ScriptNotify :: " + commandStr);
+ }
+ else if (commandCallParams.Service == "CoreEvents")
+ {
+ switch (commandCallParams.Action.ToLower())
+ {
+ case "overridebackbutton":
+ string arg0 = JsonHelper.Deserialize<string[]>(commandCallParams.Args)[0];
+ this.OverrideBackButton = (arg0 != null && arg0.Length > 0 && arg0.ToLower() == "true");
+ break;
+ }
+ }
+ else
+ {
+ if (configHandler.IsPluginAllowed(commandCallParams.Service))
+ {
+ nativeExecution.ProcessCommand(commandCallParams);
+ }
+ else
+ {
+ Debug.WriteLine("Error::Plugin not allowed in config.xml. " + commandCallParams.Service);
+ }
+ }
+ }
+
+ public void LoadPage(string url)
+ {
+ if (this.configHandler.URLIsAllowed(url))
+ {
+ this.CordovaBrowser.Navigate(new Uri(url, UriKind.RelativeOrAbsolute));
+ }
+ else
+ {
+ Debug.WriteLine("Oops, Can't load url based on config.xml :: " + url);
+ }
+ }
+
+ private void CordovaBrowser_Unloaded(object sender, RoutedEventArgs e)
+ {
+
+ }
+
+ private void CordovaBrowser_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
+ {
+ Debug.WriteLine("CordovaBrowser_NavigationFailed :: " + e.Uri.ToString());
+ }
+
+ private void CordovaBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
+ {
+ Debug.WriteLine("CordovaBrowser_Navigated :: " + e.Uri.ToString());
+ }
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/DOMStorageHelper.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/DOMStorageHelper.cs b/lib/cordova-wp8/templates/standalone/cordovalib/DOMStorageHelper.cs
new file mode 100644
index 0000000..01b6273
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/DOMStorageHelper.cs
@@ -0,0 +1,145 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+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 WPCordovaClassLib.Cordova.JSON;
+
+/*
+ * Translates DOMStorage API between JS and Isolated Storage
+ * Missing pieces : QUOTA_EXCEEDED_ERR + StorageEvent
+ * */
+
+namespace WPCordovaClassLib
+{
+ public class DOMStorageHelper
+ {
+ protected WebBrowser webBrowser1;
+
+ public DOMStorageHelper(WebBrowser aBrowser)
+ {
+ this.webBrowser1 = aBrowser;
+ // 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;
+ }
+
+ }
+
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/JSON/JsonHelper.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/JSON/JsonHelper.cs b/lib/cordova-wp8/templates/standalone/cordovalib/JSON/JsonHelper.cs
new file mode 100644
index 0000000..44511f6
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/JSON/JsonHelper.cs
@@ -0,0 +1,97 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+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.Runtime.Serialization.Json;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace WPCordovaClassLib.Cordova.JSON
+{
+ /// <summary>
+ /// Provides JSON serialization/deserialization functionality.
+ /// </summary>
+ public static class JsonHelper
+ {
+ /// <summary>
+ /// Serializes object to JSON string representation
+ /// </summary>
+ /// <param name="obj">object to serialize</param>
+ /// <returns>JSON representation of the object. Returns 'null' string for null passed as argument</returns>
+ public static string Serialize(object obj)
+ {
+ if (obj == null)
+ {
+ return "null";
+ }
+
+ DataContractJsonSerializer ser = new DataContractJsonSerializer(obj.GetType());
+
+ MemoryStream ms = new MemoryStream();
+ ser.WriteObject(ms, obj);
+
+ ms.Position = 0;
+
+ string json = String.Empty;
+
+ using (StreamReader sr = new StreamReader(ms))
+ {
+ json = sr.ReadToEnd();
+ }
+
+ ms.Close();
+
+ return json;
+
+ }
+
+ /// <summary>
+ /// Parses json string to object instance
+ /// </summary>
+ /// <typeparam name="T">type of the object</typeparam>
+ /// <param name="json">json string representation of the object</param>
+ /// <returns>Deserialized object instance</returns>
+ public static T Deserialize<T>(string json)
+ {
+ DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T));
+ object result = null;
+ try
+ {
+ using (MemoryStream mem = new MemoryStream(Encoding.UTF8.GetBytes(json)))
+ {
+ result = deserializer.ReadObject(mem);
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message);
+ Debug.WriteLine("Failed to deserialize " + typeof(T) + " with JSON value :: " + json);
+ }
+
+ return (T)result;
+
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/NativeExecution.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/NativeExecution.cs b/lib/cordova-wp8/templates/standalone/cordovalib/NativeExecution.cs
new file mode 100644
index 0000000..af6b207
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/NativeExecution.cs
@@ -0,0 +1,246 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+using System;
+using System.Diagnostics;
+using System.Threading;
+using Microsoft.Devices;
+using Microsoft.Phone.Controls;
+using WPCordovaClassLib.Cordova.Commands;
+using System.Windows;
+
+namespace WPCordovaClassLib.Cordova
+{
+ /// <summary>
+ /// Implements logic to execute native command and return result back.
+ /// All commands are executed asynchronous.
+ /// </summary>
+ public class NativeExecution
+ {
+ /// <summary>
+ /// Reference to web part where application is hosted
+ /// </summary>
+ private readonly WebBrowser webBrowser;
+
+ /// <summary>
+ /// Creates new instance of a NativeExecution class.
+ /// </summary>
+ /// <param name="browser">Reference to web part where application is hosted</param>
+ public NativeExecution(ref WebBrowser browser)
+ {
+ if (browser == null)
+ {
+ throw new ArgumentNullException("browser");
+ }
+
+ this.webBrowser = browser;
+ }
+
+ /// <summary>
+ /// Returns where application is running on emulator
+ /// </summary>
+ /// <returns>True if running on emulator, otherwise False</returns>
+ public static bool IsRunningOnEmulator()
+ {
+ return Microsoft.Devices.Environment.DeviceType == DeviceType.Emulator;
+ }
+
+ public void ResetAllCommands()
+ {
+ CommandFactory.ResetAllCommands();
+ }
+
+ public void AutoLoadCommand(string commandService)
+ {
+ BaseCommand bc = CommandFactory.CreateByServiceName(commandService);
+ if (bc != null)
+ {
+ bc.OnInit();
+ }
+
+ }
+
+ /// <summary>
+ /// Executes command and returns result back.
+ /// </summary>
+ /// <param name="commandCallParams">Command to execute</param>
+ public void ProcessCommand(CordovaCommandCall commandCallParams)
+ {
+
+ if (commandCallParams == null)
+ {
+ throw new ArgumentNullException("commandCallParams");
+ }
+
+ try
+ {
+ BaseCommand bc = CommandFactory.CreateByServiceName(commandCallParams.Service);
+
+ if (bc == null)
+ {
+ this.OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION));
+ return;
+ }
+
+ EventHandler<PluginResult> OnCommandResultHandler = delegate(object o, PluginResult res)
+ {
+ if (res.CallbackId == null || res.CallbackId == commandCallParams.CallbackId)
+ {
+ this.OnCommandResult(commandCallParams.CallbackId, res);
+ if (!res.KeepCallback)
+ {
+ bc.RemoveResultHandler(commandCallParams.CallbackId);
+ }
+ }
+ };
+
+ //bc.OnCommandResult += OnCommandResultHandler;
+ bc.AddResultHandler(commandCallParams.CallbackId, OnCommandResultHandler);
+
+ EventHandler<ScriptCallback> OnCustomScriptHandler = delegate(object o, ScriptCallback script)
+ {
+ this.InvokeScriptCallback(script);
+ };
+
+ bc.OnCustomScript += OnCustomScriptHandler;
+
+ ThreadStart methodInvokation = () =>
+ {
+ try
+ {
+ bc.InvokeMethodNamed(commandCallParams.CallbackId,commandCallParams.Action, commandCallParams.Args);
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("ERROR: Exception in ProcessCommand :: " + ex.Message);
+ bc.RemoveResultHandler(commandCallParams.CallbackId);
+ bc.OnCustomScript -= OnCustomScriptHandler;
+
+ Debug.WriteLine("ERROR: failed to InvokeMethodNamed :: " + commandCallParams.Action + " on Object :: " + commandCallParams.Service);
+ this.OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.INVALID_ACTION));
+ return;
+ }
+ };
+
+ if ((bc is File) || (bc is Accelerometer))
+ {
+ // Due to some issues with the IsolatedStorage in current version of WP8 SDK we have to run all File Api commands synchronously.
+ // TODO: test this in WP8 RTM
+ methodInvokation.Invoke();
+ }
+ else
+ {
+ new Thread(methodInvokation).Start();
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ // ERROR
+ Debug.WriteLine(String.Format("ERROR: Unable to execute command :: {0}:{1}:{3} ",
+ commandCallParams.Service, commandCallParams.Action, ex.Message));
+
+ this.OnCommandResult(commandCallParams.CallbackId, new PluginResult(PluginResult.Status.ERROR));
+ return;
+ }
+ }
+
+ /// <summary>
+ /// Handles command execution result.
+ /// </summary>
+ /// <param name="callbackId">Command callback identifier on client side</param>
+ /// <param name="result">Execution result</param>
+ private void OnCommandResult(string callbackId, PluginResult result)
+ {
+ #region args checking
+
+ if (result == null)
+ {
+ Debug.WriteLine("ERROR: OnCommandResult missing result argument");
+ return;
+ }
+
+ if (String.IsNullOrEmpty(callbackId))
+ {
+ Debug.WriteLine("ERROR: OnCommandResult missing callbackId argument");
+ return;
+ }
+
+ if (!String.IsNullOrEmpty(result.CallbackId) && callbackId != result.CallbackId)
+ {
+ Debug.WriteLine("Multiple Overlapping Results :: " + result.CallbackId + " :: " + callbackId);
+ return;
+ }
+
+ #endregion
+
+ string jsonResult = result.ToJSONString();
+
+ string callback;
+ string args = string.Format("('{0}',{1});", callbackId, jsonResult);
+
+ if (result.Result == PluginResult.Status.NO_RESULT ||
+ result.Result == PluginResult.Status.OK)
+ {
+ callback = @"(function(callbackId,args) {
+ try { args.message = JSON.parse(args.message); } catch (ex) { }
+ cordova.callbackSuccess(callbackId,args);
+ })" + args;
+ }
+ else
+ {
+ callback = @"(function(callbackId,args) {
+ try { args.message = JSON.parse(args.message); } catch (ex) { }
+ cordova.callbackError(callbackId,args);
+ })" + args;
+ }
+ this.InvokeScriptCallback(new ScriptCallback("eval", new string[] { callback }));
+
+ }
+
+ /// <summary>
+ /// Executes client java script
+ /// </summary>
+ /// <param name="script">Script to execute on client side</param>
+ private void InvokeScriptCallback(ScriptCallback script)
+ {
+ if (script == null)
+ {
+ throw new ArgumentNullException("script");
+ }
+
+ if (String.IsNullOrEmpty(script.ScriptName))
+ {
+ throw new ArgumentNullException("ScriptName");
+ }
+
+ //Debug.WriteLine("INFO:: About to invoke ::" + script.ScriptName + " with args ::" + script.Args[0]);
+ this.webBrowser.Dispatcher.BeginInvoke((ThreadStart)delegate()
+ {
+ try
+ {
+ //Debug.WriteLine("INFO:: InvokingScript::" + script.ScriptName + " with args ::" + script.Args[0]);
+ this.webBrowser.InvokeScript(script.ScriptName, script.Args);
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("ERROR: Exception in InvokeScriptCallback :: " + ex.Message);
+ }
+
+ });
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/OrientationHelper.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/OrientationHelper.cs b/lib/cordova-wp8/templates/standalone/cordovalib/OrientationHelper.cs
new file mode 100644
index 0000000..0e29b22
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/OrientationHelper.cs
@@ -0,0 +1,128 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+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 Microsoft.Phone.Controls;
+
+namespace WPCordovaClassLib.Cordova
+{
+ public class OrientationHelper
+ {
+ protected WebBrowser CordovaBrowser;
+ protected PhoneApplicationPage Page;
+ // private PageOrientation CurrentOrientation = PageOrientation.PortraitUp;
+ //private PageOrientation[] SupportedOrientations; // TODO:
+
+ public OrientationHelper(WebBrowser browser, PhoneApplicationPage page)
+ {
+ CordovaBrowser = browser;
+ Page = page;
+
+ Page.OrientationChanged += new EventHandler<OrientationChangedEventArgs>(page_OrientationChanged);
+ CordovaBrowser.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(browser_LoadCompleted);
+
+
+ }
+
+ void browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
+ {
+ int i = 0;
+
+ switch (Page.Orientation)
+ {
+ case PageOrientation.Portrait: // intentional fall through
+ case PageOrientation.PortraitUp:
+ i = 0;
+ break;
+ case PageOrientation.PortraitDown:
+ i = 180;
+ break;
+ case PageOrientation.Landscape: // intentional fall through
+ case PageOrientation.LandscapeLeft:
+ i = -90;
+ break;
+ case PageOrientation.LandscapeRight:
+ i = 90;
+ break;
+ }
+ // Cordova.fireEvent('orientationchange', window);
+ string jsCallback = String.Format("window.orientation = {0};", i);
+
+ try
+ {
+ CordovaBrowser.InvokeScript("execScript", jsCallback);
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+ void page_OrientationChanged(object sender, OrientationChangedEventArgs e)
+ {
+ int i = 0;
+
+ switch (e.Orientation)
+ {
+ case PageOrientation.Portrait: // intentional fall through
+ case PageOrientation.PortraitUp:
+ i = 0;
+ break;
+ case PageOrientation.PortraitDown:
+ i = 180;
+ break;
+ case PageOrientation.Landscape: // intentional fall through
+ case PageOrientation.LandscapeLeft:
+ i = -90;
+ break;
+ case PageOrientation.LandscapeRight:
+ i = 90;
+ break;
+ }
+ // Cordova.fireEvent('orientationchange', window);
+ string jsCallback = String.Format("window.orientation = {0};", i);
+
+ try
+ {
+
+ CordovaBrowser.InvokeScript("execScript", 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);
+ }
+ catch (Exception)
+ {
+ }
+ }
+
+ public void HandleCommand(string commandStr)
+ {
+
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/PluginResult.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/PluginResult.cs b/lib/cordova-wp8/templates/standalone/cordovalib/PluginResult.cs
new file mode 100644
index 0000000..00017d2
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/PluginResult.cs
@@ -0,0 +1,139 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+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.Text;
+using System.Diagnostics;
+
+namespace WPCordovaClassLib.Cordova
+{
+ /// <summary>
+ /// Represents command execution result
+ /// </summary>
+ public class PluginResult : EventArgs
+ {
+ /// <summary>
+ /// Predefined resultant messages
+ /// </summary>
+ public static string[] StatusMessages = new string[]
+ {
+ "No result",
+ "OK",
+ "Class not found",
+ "Illegal access",
+ "Instantiation error",
+ "Malformed url",
+ "IO error",
+ "Invalid action",
+ "JSON error",
+ "Error"
+ };
+
+ /// <summary>
+ /// Possible command results status codes
+ /// </summary>
+ public enum Status : int
+ {
+ NO_RESULT = 0,
+ OK,
+ CLASS_NOT_FOUND_EXCEPTION,
+ ILLEGAL_ACCESS_EXCEPTION,
+ INSTANTIATION_EXCEPTION,
+ MALFORMED_URL_EXCEPTION,
+ IO_EXCEPTION,
+ INVALID_ACTION,
+ JSON_EXCEPTION,
+ ERROR
+ };
+
+ public Status Result { get; private set; }
+ public string Message { get; set; }
+ public bool KeepCallback { get; set; }
+ public string CallbackId { get; set; }
+
+ /// <summary>
+ /// Whether command succeded or not
+ /// </summary>
+ public bool IsSuccess
+ {
+ get
+ {
+ return this.Result == Status.OK || this.Result == Status.NO_RESULT;
+ }
+ }
+
+ /// <summary>
+ /// Creates new instance of the PluginResult class.
+ /// </summary>
+ /// <param name="status">Execution result</param>
+ public PluginResult(Status status)
+ : this(status, PluginResult.StatusMessages[(int)status])
+ {
+ }
+
+ /// <summary>
+ /// Creates new instance of the PluginResult class.
+ /// </summary>
+ /// <param name="status">Execution result</param>
+ /// <param name="message">The message</param>
+ public PluginResult(Status status, object message)
+ {
+ this.Result = status;
+ this.Message = JSON.JsonHelper.Serialize(message);
+ }
+
+ public string ToJSONString()
+ {
+ string res = String.Format("\"status\":{0},\"message\":{1},\"keepCallback\":{2}",
+ (int)this.Result,
+ this.Message,
+ this.KeepCallback.ToString().ToLower());
+
+ res = "{" + res + "}";
+ return res;
+
+ }
+
+ [Obsolete]
+ public string ToCallbackString(string callbackId, string successCallback, string errorCallback)
+ {
+ if (this.IsSuccess)
+ {
+ StringBuilder buf = new StringBuilder("");
+ buf.Append(String.Format("{0}('{1}',{2});", successCallback, callbackId, this.ToJSONString()));
+ return buf.ToString();
+ }
+ else
+ {
+ return String.Format("{0}('{1}',{2});", errorCallback, callbackId, this.ToJSONString());
+ }
+ }
+
+ public override String ToString()
+ {
+ return this.ToJSONString();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/ScriptCallback.cs
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/ScriptCallback.cs b/lib/cordova-wp8/templates/standalone/cordovalib/ScriptCallback.cs
new file mode 100644
index 0000000..7878134
--- /dev/null
+++ b/lib/cordova-wp8/templates/standalone/cordovalib/ScriptCallback.cs
@@ -0,0 +1,80 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+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 WPCordovaClassLib.Cordova.JSON;
+using System.Diagnostics;
+
+namespace WPCordovaClassLib.Cordova
+{
+ /// <summary>
+ /// Represents client script function to execute
+ /// </summary>
+ public class ScriptCallback : EventArgs
+ {
+ /// <summary>
+ /// The scripting function to execute.
+ /// </summary>
+ public string ScriptName { get; private set; }
+
+ /// <summary>
+ /// A variable number of strings to pass to the function as parameters.
+ /// </summary>
+ public string[] Args { get; private set; }
+
+ /// <summary>
+ /// Creates new instance of a ScriptCallback class.
+ /// </summary>
+ /// <param name="function">The scripting function to execute</param>
+ /// <param name="args">A variable number of strings to pass to the function as parameters</param>
+ public ScriptCallback(string function, string[] args)
+ {
+ this.ScriptName = function;
+ this.Args = args;
+ }
+
+ /// <summary>
+ /// Creates new instance of a ScriptCallback class.
+ /// </summary>
+ /// <param name="function">The scripting function to execute</param>
+ /// <param name="id">The id argument</param>
+ /// <param name="msg">The message argument</param>
+ /// <param name="value">The value argument</param>
+ public ScriptCallback(string function, string id, object msg, object value)
+ {
+ this.ScriptName = function;
+
+ String arg = String.Format("{{\"id\": {0}, \"msg\": {1}, \"value\": {2}}}",
+ JsonHelper.Serialize(id), JsonHelper.Serialize(msg), JsonHelper.Serialize(value));
+
+ this.Args = new string[] { arg };
+ }
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/cordovalib/resources/notification-beep.wav
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/cordovalib/resources/notification-beep.wav b/lib/cordova-wp8/templates/standalone/cordovalib/resources/notification-beep.wav
new file mode 100644
index 0000000..d0ad085
Binary files /dev/null and b/lib/cordova-wp8/templates/standalone/cordovalib/resources/notification-beep.wav differ
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/f59ddbbd/lib/cordova-wp8/templates/standalone/resources/notification-beep.wav
----------------------------------------------------------------------
diff --git a/lib/cordova-wp8/templates/standalone/resources/notification-beep.wav b/lib/cordova-wp8/templates/standalone/resources/notification-beep.wav
new file mode 100644
index 0000000..d0ad085
Binary files /dev/null and b/lib/cordova-wp8/templates/standalone/resources/notification-beep.wav differ