summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/_inc/postmessage.js')
-rw-r--r--plugins/jetpack/_inc/postmessage.js438
1 files changed, 438 insertions, 0 deletions
diff --git a/plugins/jetpack/_inc/postmessage.js b/plugins/jetpack/_inc/postmessage.js
new file mode 100644
index 00000000..51f8567b
--- /dev/null
+++ b/plugins/jetpack/_inc/postmessage.js
@@ -0,0 +1,438 @@
+/**
+ The MIT License
+
+ Copyright (c) 2010 Daniel Park (http://metaweb.com, http://postmessage.freebaseapps.com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ **/
+var NO_JQUERY = {};
+(function(window, $, undefined) {
+
+ if (!("console" in window)) {
+ var c = window.console = {};
+ c.log = c.warn = c.error = c.debug = function(){};
+ }
+
+ if ($ === NO_JQUERY) {
+ // jQuery is optional
+ $ = {
+ fn: {},
+ extend: function() {
+ var a = arguments[0];
+ for (var i=1,len=arguments.length; i<len; i++) {
+ var b = arguments[i];
+ for (var prop in b) {
+ a[prop] = b[prop];
+ }
+ }
+ return a;
+ }
+ };
+ }
+
+ $.fn.pm = function() {
+ console.log("usage: \nto send: $.pm(options)\nto receive: $.pm.bind(type, fn, [origin])");
+ return this;
+ };
+
+ // send postmessage
+ $.pm = window.pm = function(options) {
+ pm.send(options);
+ };
+
+ // bind postmessage handler
+ $.pm.bind = window.pm.bind = function(type, fn, origin, hash, async_reply) {
+ pm.bind(type, fn, origin, hash, async_reply === true);
+ };
+
+ // unbind postmessage handler
+ $.pm.unbind = window.pm.unbind = function(type, fn) {
+ pm.unbind(type, fn);
+ };
+
+ // default postmessage origin on bind
+ $.pm.origin = window.pm.origin = null;
+
+ // default postmessage polling if using location hash to pass postmessages
+ $.pm.poll = window.pm.poll = 200;
+
+ var pm = {
+
+ send: function(options) {
+ var o = $.extend({}, pm.defaults, options),
+ target = o.target;
+ if (!o.target) {
+ console.warn("postmessage target window required");
+ return;
+ }
+ if (!o.type) {
+ console.warn("postmessage type required");
+ return;
+ }
+ var msg = {data:o.data, type:o.type};
+ if (o.success) {
+ msg.callback = pm._callback(o.success);
+ }
+ if (o.error) {
+ msg.errback = pm._callback(o.error);
+ }
+ if (("postMessage" in target) && !o.hash) {
+ pm._bind();
+ target.postMessage(JSON.stringify(msg), o.origin || '*');
+ }
+ else {
+ pm.hash._bind();
+ pm.hash.send(o, msg);
+ }
+ },
+
+ bind: function(type, fn, origin, hash, async_reply) {
+ pm._replyBind ( type, fn, origin, hash, async_reply );
+ },
+
+ _replyBind: function(type, fn, origin, hash, isCallback) {
+ if (("postMessage" in window) && !hash) {
+ pm._bind();
+ }
+ else {
+ pm.hash._bind();
+ }
+ var l = pm.data("listeners.postmessage");
+ if (!l) {
+ l = {};
+ pm.data("listeners.postmessage", l);
+ }
+ var fns = l[type];
+ if (!fns) {
+ fns = [];
+ l[type] = fns;
+ }
+ fns.push({fn:fn, callback: isCallback, origin:origin || $.pm.origin});
+ },
+
+ unbind: function(type, fn) {
+ var l = pm.data("listeners.postmessage");
+ if (l) {
+ if (type) {
+ if (fn) {
+ // remove specific listener
+ var fns = l[type];
+ if (fns) {
+ var m = [];
+ for (var i=0,len=fns.length; i<len; i++) {
+ var o = fns[i];
+ if (o.fn !== fn) {
+ m.push(o);
+ }
+ }
+ l[type] = m;
+ }
+ }
+ else {
+ // remove all listeners by type
+ delete l[type];
+ }
+ }
+ else {
+ // unbind all listeners of all type
+ for (var i in l) {
+ delete l[i];
+ }
+ }
+ }
+ },
+
+ data: function(k, v) {
+ if (v === undefined) {
+ return pm._data[k];
+ }
+ pm._data[k] = v;
+ return v;
+ },
+
+ _data: {},
+
+ _CHARS: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''),
+
+ _random: function() {
+ var r = [];
+ for (var i=0; i<32; i++) {
+ r[i] = pm._CHARS[0 | Math.random() * 32];
+ };
+ return r.join("");
+ },
+
+ _callback: function(fn) {
+ var cbs = pm.data("callbacks.postmessage");
+ if (!cbs) {
+ cbs = {};
+ pm.data("callbacks.postmessage", cbs);
+ }
+ var r = pm._random();
+ cbs[r] = fn;
+ return r;
+ },
+
+ _bind: function() {
+ // are we already listening to message events on this w?
+ if (!pm.data("listening.postmessage")) {
+ if (window.addEventListener) {
+ window.addEventListener("message", pm._dispatch, false);
+ }
+ else if (window.attachEvent) {
+ window.attachEvent("onmessage", pm._dispatch);
+ }
+ pm.data("listening.postmessage", 1);
+ }
+ },
+
+ _dispatch: function(e) {
+ //console.log("$.pm.dispatch", e, this);
+ try {
+ var msg = JSON.parse(e.data);
+ }
+ catch (ex) {
+ //console.warn("postmessage data invalid json: ", ex); //message wasn't meant for pm
+ return;
+ }
+ if (!msg.type) {
+ //console.warn("postmessage message type required"); //message wasn't meant for pm
+ return;
+ }
+ var cbs = pm.data("callbacks.postmessage") || {},
+ cb = cbs[msg.type];
+ if (cb) {
+ cb(msg.data);
+ }
+ else {
+ var l = pm.data("listeners.postmessage") || {};
+ var fns = l[msg.type] || [];
+ for (var i=0,len=fns.length; i<len; i++) {
+ var o = fns[i];
+ if (o.origin && o.origin !== '*' && e.origin !== o.origin) {
+ console.warn("postmessage message origin mismatch", e.origin, o.origin);
+ if (msg.errback) {
+ // notify post message errback
+ var error = {
+ message: "postmessage origin mismatch",
+ origin: [e.origin, o.origin]
+ };
+ pm.send({target:e.source, data:error, type:msg.errback});
+ }
+ continue;
+ }
+
+ function sendReply ( data ) {
+ if (msg.callback) {
+ pm.send({target:e.source, data:data, type:msg.callback});
+ }
+ }
+
+ try {
+ if ( o.callback ) {
+ o.fn(msg.data, sendReply, e);
+ } else {
+ sendReply ( o.fn(msg.data, e) );
+ }
+ }
+ catch (ex) {
+ if (msg.errback) {
+ // notify post message errback
+ pm.send({target:e.source, data:ex, type:msg.errback});
+ } else {
+ throw ex;
+ }
+ }
+ };
+ }
+ }
+ };
+
+ // location hash polling
+ pm.hash = {
+
+ send: function(options, msg) {
+ //console.log("hash.send", target_window, options, msg);
+ var target_window = options.target,
+ target_url = options.url;
+ if (!target_url) {
+ console.warn("postmessage target window url is required");
+ return;
+ }
+ target_url = pm.hash._url(target_url);
+ var source_window,
+ source_url = pm.hash._url(window.location.href);
+ if (window == target_window.parent) {
+ source_window = "parent";
+ }
+ else {
+ try {
+ for (var i=0,len=parent.frames.length; i<len; i++) {
+ var f = parent.frames[i];
+ if (f == window) {
+ source_window = i;
+ break;
+ }
+ };
+ }
+ catch(ex) {
+ // Opera: security error trying to access parent.frames x-origin
+ // juse use window.name
+ source_window = window.name;
+ }
+ }
+ if (source_window == null) {
+ console.warn("postmessage windows must be direct parent/child windows and the child must be available through the parent window.frames list");
+ return;
+ }
+ var hashmessage = {
+ "x-requested-with": "postmessage",
+ source: {
+ name: source_window,
+ url: source_url
+ },
+ postmessage: msg
+ };
+ var hash_id = "#x-postmessage-id=" + pm._random();
+ target_window.location = target_url + hash_id + encodeURIComponent(JSON.stringify(hashmessage));
+ },
+
+ _regex: /^\#x\-postmessage\-id\=(\w{32})/,
+
+ _regex_len: "#x-postmessage-id=".length + 32,
+
+ _bind: function() {
+ // are we already listening to message events on this w?
+ if (!pm.data("polling.postmessage")) {
+ setInterval(function() {
+ var hash = "" + window.location.hash,
+ m = pm.hash._regex.exec(hash);
+ if (m) {
+ var id = m[1];
+ if (pm.hash._last !== id) {
+ pm.hash._last = id;
+ pm.hash._dispatch(hash.substring(pm.hash._regex_len));
+ }
+ }
+ }, $.pm.poll || 200);
+ pm.data("polling.postmessage", 1);
+ }
+ },
+
+ _dispatch: function(hash) {
+ if (!hash) {
+ return;
+ }
+ try {
+ hash = JSON.parse(decodeURIComponent(hash));
+ if (!(hash['x-requested-with'] === 'postmessage' &&
+ hash.source && hash.source.name != null && hash.source.url && hash.postmessage)) {
+ // ignore since hash could've come from somewhere else
+ return;
+ }
+ }
+ catch (ex) {
+ // ignore since hash could've come from somewhere else
+ return;
+ }
+ var msg = hash.postmessage,
+ cbs = pm.data("callbacks.postmessage") || {},
+ cb = cbs[msg.type];
+ if (cb) {
+ cb(msg.data);
+ }
+ else {
+ var source_window;
+ if (hash.source.name === "parent") {
+ source_window = window.parent;
+ }
+ else {
+ source_window = window.frames[hash.source.name];
+ }
+ var l = pm.data("listeners.postmessage") || {};
+ var fns = l[msg.type] || [];
+ for (var i=0,len=fns.length; i<len; i++) {
+ var o = fns[i];
+ if (o.origin) {
+ var origin = /https?\:\/\/[^\/]*/.exec(hash.source.url)[0];
+ if (o.origin !== '*' && origin !== o.origin) {
+ console.warn("postmessage message origin mismatch", origin, o.origin);
+ if (msg.errback) {
+ // notify post message errback
+ var error = {
+ message: "postmessage origin mismatch",
+ origin: [origin, o.origin]
+ };
+ pm.send({target:source_window, data:error, type:msg.errback, hash:true, url:hash.source.url});
+ }
+ continue;
+ }
+ }
+
+ function sendReply ( data ) {
+ if (msg.callback) {
+ pm.send({target:source_window, data:data, type:msg.callback, hash:true, url:hash.source.url});
+ }
+ }
+
+ try {
+ if ( o.callback ) {
+ o.fn(msg.data, sendReply);
+ } else {
+ sendReply ( o.fn(msg.data) );
+ }
+ }
+ catch (ex) {
+ if (msg.errback) {
+ // notify post message errback
+ pm.send({target:source_window, data:ex, type:msg.errback, hash:true, url:hash.source.url});
+ } else {
+ throw ex;
+ }
+ }
+ };
+ }
+ },
+
+ _url: function(url) {
+ // url minus hash part
+ return (""+url).replace(/#.*$/, "");
+ }
+
+ };
+
+ $.extend(pm, {
+ defaults: {
+ target: null, /* target window (required) */
+ url: null, /* target window url (required if no window.postMessage or hash == true) */
+ type: null, /* message type (required) */
+ data: null, /* message data (required) */
+ success: null, /* success callback (optional) */
+ error: null, /* error callback (optional) */
+ origin: "*", /* postmessage origin (optional) */
+ hash: false /* use location hash for message passing (optional) */
+ }
+ });
+
+ })(this, typeof jQuery === "undefined" ? NO_JQUERY : jQuery);
+
+/**
+ * http://www.JSON.org/json2.js
+ **/
+if (! ("JSON" in window && window.JSON)){JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z"};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());