mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound. a=merge
CLOSED TREE
This commit is contained in:
commit
aa61f50d35
@ -1287,7 +1287,7 @@ Accessible::NativeAttributes()
|
||||
// override properties on a widget they used in an iframe.
|
||||
nsIContent* startContent = mContent;
|
||||
while (startContent) {
|
||||
nsIDocument* doc = startContent->GetDocument();
|
||||
nsIDocument* doc = startContent->GetComposedDoc();
|
||||
if (!doc)
|
||||
break;
|
||||
|
||||
|
@ -1309,8 +1309,22 @@ DocAccessible::GetAccessibleOrContainer(nsINode* aNode) const
|
||||
|
||||
nsINode* currNode = aNode;
|
||||
Accessible* accessible = nullptr;
|
||||
while (!(accessible = GetAccessible(currNode)) &&
|
||||
(currNode = currNode->GetParentNode()));
|
||||
while (!(accessible = GetAccessible(currNode))) {
|
||||
nsINode* parent = nullptr;
|
||||
|
||||
// If this is a content node, try to get a flattened parent content node.
|
||||
// This will smartly skip from the shadow root to the host element,
|
||||
// over parentless document fragment
|
||||
if (currNode->IsContent())
|
||||
parent = currNode->AsContent()->GetFlattenedTreeParent();
|
||||
|
||||
// Fallback to just get parent node, in case there is no parent content
|
||||
// node. Or current node is not a content node.
|
||||
if (!parent)
|
||||
parent = currNode->GetParentNode();
|
||||
|
||||
if (!(currNode = parent)) break;
|
||||
}
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
if (navigator.platform.startsWith("Mac")) {
|
||||
SimpleTest.expectAssertions(0, 1);
|
||||
} else {
|
||||
SimpleTest.expectAssertions(1);
|
||||
SimpleTest.expectAssertions(0, 1);
|
||||
}
|
||||
|
||||
function doTest()
|
||||
|
@ -1,14 +0,0 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
The Reddit Panel example add-on displays Reddit in a panel you open
|
||||
by clicking a widget in the add-on bar. When you click a Reddit story
|
||||
in the panel, the story opens in a new tab.
|
||||
|
||||
The add-on demonstrates the Panel and Widget APIs as well as content scripts
|
||||
and using jQuery as a content script.
|
||||
|
||||
Due to a bug in Firefox 4.0b7, this example doesn't work in that version
|
||||
of Firefox and requires a recent Firefox 4.0b8pre nightly build, Firefox 4.0b8
|
||||
itself, or a newer version of Firefox.
|
@ -1,167 +0,0 @@
|
||||
/*!
|
||||
* jQuery JavaScript Library v1.4.4
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* http://sizzlejs.com/
|
||||
* Copyright 2010, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date: Thu Nov 11 19:04:53 2010 -0500
|
||||
*/
|
||||
(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h=
|
||||
h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;k<J.length;k++){h=J[k];h.origType.replace(X,"")===a.type?f.push(h.selector):J.splice(k--,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.length;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.selector===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;if(h.preType==="mouseenter"||
|
||||
h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarget).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleObj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La,
|
||||
"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,
|
||||
e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,
|
||||
"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+
|
||||
a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,
|
||||
C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j,
|
||||
s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,
|
||||
j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length},
|
||||
toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j===
|
||||
-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false;
|
||||
if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K<Q;K++)if((j=arguments[K])!=null)for(s in j){v=G[s];z=j[s];if(G!==z)if(ga&&z&&(b.isPlainObject(z)||(H=b.isArray(z)))){if(H){H=false;v=v&&b.isArray(v)?v:[]}else v=v&&b.isPlainObject(v)?v:{};G[s]=b.extend(ga,v,z)}else if(z!==B)G[s]=z}return G};b.extend({noConflict:function(j){E.$=e;if(j)E.jQuery=d;return b},isReady:false,readyWait:1,ready:function(j){j===true&&b.readyWait--;
|
||||
if(!b.readyWait||j!==true&&!b.isReady){if(!t.body)return setTimeout(b.ready,1);b.isReady=true;if(!(j!==true&&--b.readyWait>0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload",
|
||||
b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&&
|
||||
!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&&
|
||||
l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H<G;){if(s.apply(j[H++],v)===false)break}else if(K)for(z in j){if(s.call(j[z],
|
||||
z,j[z])===false)break}else for(v=j[0];H<G&&s.call(v,H,v)!==false;v=j[++H]);return j},trim:O?function(j){return j==null?"":O.call(j)}:function(j){return j==null?"":j.toString().replace(k,"").replace(o,"")},makeArray:function(j,s){var v=s||[];if(j!=null){var z=b.type(j);j.length==null||z==="string"||z==="function"||z==="regexp"||b.isWindow(j)?M.call(v,j):b.merge(v,j)}return v},inArray:function(j,s){if(s.indexOf)return s.indexOf(j);for(var v=0,z=s.length;v<z;v++)if(s[v]===j)return v;return-1},merge:function(j,
|
||||
s){var v=j.length,z=0;if(typeof s.length==="number")for(var H=s.length;z<H;z++)j[v++]=s[z];else for(;s[z]!==B;)j[v++]=s[z++];j.length=v;return j},grep:function(j,s,v){var z=[],H;v=!!v;for(var G=0,K=j.length;G<K;G++){H=!!s(j[G],G);v!==H&&z.push(j[G])}return z},map:function(j,s,v){for(var z=[],H,G=0,K=j.length;G<K;G++){H=s(j[G],G,v);if(H!=null)z[z.length]=H}return z.concat.apply([],z)},guid:1,proxy:function(j,s,v){if(arguments.length===2)if(typeof s==="string"){v=j;j=v[s];s=B}else if(s&&!b.isFunction(s)){v=
|
||||
s;s=B}if(!s&&j)s=function(){return j.apply(v||this,arguments)};if(j)s.guid=j.guid=j.guid||s.guid||b.guid++;return s},access:function(j,s,v,z,H,G){var K=j.length;if(typeof s==="object"){for(var Q in s)b.access(j,Q,s[Q],z,H,v);return j}if(v!==B){z=!G&&z&&b.isFunction(v);for(Q=0;Q<K;Q++)H(j[Q],s,z?v.call(j[Q],Q,H(j[Q],s)):v,G);return j}return K?H(j[0],s):B},now:function(){return(new Date).getTime()},uaMatch:function(j){j=j.toLowerCase();j=L.exec(j)||g.exec(j)||i.exec(j)||j.indexOf("compatible")<0&&n.exec(j)||
|
||||
[];return{browser:j[1]||"",version:j[2]||"0"}},browser:{}});b.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(j,s){R["[object "+s+"]"]=s.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=m.version}if(b.browser.webkit)b.browser.safari=true;if(D)b.inArray=function(j,s){return D.call(s,j)};if(!/\s/.test("\u00a0")){k=/^[\s\xA0]+/;o=/[\s\xA0]+$/}f=b(t);if(t.addEventListener)u=function(){t.removeEventListener("DOMContentLoaded",u,
|
||||
false);b.ready()};else if(t.attachEvent)u=function(){if(t.readyState==="complete"){t.detachEvent("onreadystatechange",u);b.ready()}};return E.jQuery=E.$=b}();(function(){c.support={};var a=t.documentElement,b=t.createElement("script"),d=t.createElement("div"),e="script"+c.now();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"),
|
||||
k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false,
|
||||
scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent=
|
||||
false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom=
|
||||
1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="<div style='width:4px;'></div>";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display=
|
||||
"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h=
|
||||
c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);
|
||||
else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h<l;h++){f=e[h].name;if(f.indexOf("data-")===0){f=f.substr(5);ka(this[0],f,d[f])}}}return d}else if(typeof a==="object")return this.each(function(){c.data(this,
|
||||
a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(b===B){d=this.triggerHandler("getData"+k[1]+"!",[k[0]]);if(d===B&&this.length){d=c.data(this[0],a);d=ka(this[0],a,d)}return d===B&&k[1]?this.data(k[0]):d}else return this.each(function(){var o=c(this),x=[k[0],b];o.triggerHandler("setData"+k[1]+"!",x);c.data(this,a,b);o.triggerHandler("changeData"+k[1]+"!",x)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=
|
||||
c.data(a,b);if(!d)return e||[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===B)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,
|
||||
a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var sa=/[\n\t]/g,ha=/\s+/,Sa=/\r/g,Ta=/^(?:href|src|style)$/,Ua=/^(?:button|input)$/i,Va=/^(?:button|input|object|select|textarea)$/i,Wa=/^a(?:rea)?$/i,ta=/^(?:radio|checkbox)$/i;c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",
|
||||
colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(x){var r=c(this);r.addClass(a.call(this,x,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===
|
||||
1)if(f.className){for(var h=" "+f.className+" ",l=f.className,k=0,o=b.length;k<o;k++)if(h.indexOf(" "+b[k]+" ")<0)l+=" "+b[k];f.className=c.trim(l)}else f.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var x=c(this);x.removeClass(a.call(this,o,x.attr("class")))});if(a&&typeof a==="string"||a===B)for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===1&&f.className)if(a){for(var h=(" "+f.className+" ").replace(sa," "),
|
||||
l=0,k=b.length;l<k;l++)h=h.replace(" "+b[l]+" "," ");f.className=c.trim(h)}else f.className=""}return this},toggleClass:function(a,b){var d=typeof a,e=typeof b==="boolean";if(c.isFunction(a))return this.each(function(f){var h=c(this);h.toggleClass(a.call(this,f,h.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var f,h=0,l=c(this),k=b,o=a.split(ha);f=o[h++];){k=e?k:!l.hasClass(f);l[k?"addClass":"removeClass"](f)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,
|
||||
"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(sa," ").indexOf(a)>-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";
|
||||
if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h<e;h++){var l=f[h];if(l.selected&&(c.support.optDisabled?!l.disabled:l.getAttribute("disabled")===null)&&(!l.parentNode.disabled||!c.nodeName(l.parentNode,"optgroup"))){a=c(l).val();if(b)return a;d.push(a)}}return d}if(ta.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Sa,"")}return B}var k=c.isFunction(a);return this.each(function(o){var x=c(this),r=a;if(this.nodeType===1){if(k)r=
|
||||
a.call(this,o,x.val());if(r==null)r="";else if(typeof r==="number")r+="";else if(c.isArray(r))r=c.map(r,function(C){return C==null?"":C+""});if(c.isArray(r)&&ta.test(this.type))this.checked=c.inArray(x.val(),r)>=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},
|
||||
attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&
|
||||
b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0};
|
||||
c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,
|
||||
arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid=
|
||||
d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+
|
||||
c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h<A.length;h++){C=A[h];if(d.guid===C.guid){if(k||x.test(C.namespace)){e==null&&A.splice(h--,1);r.remove&&r.remove.call(a,C)}if(e!=null)break}}if(A.length===0||e!=null&&A.length===1){if(!r.teardown||r.teardown.call(a,o)===false)c.removeEvent(a,f,w.handle);delete I[f]}}else for(h=0;h<A.length;h++){C=A[h];if(k||x.test(C.namespace)){c.event.remove(a,r,C.handler,h);A.splice(h--,1)}}}if(c.isEmptyObject(I)){if(b=
|
||||
w.handle)b.elem=null;delete w.events;delete w.handle;if(typeof w==="function")c.removeData(a,J);else c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var f=a.type||a;if(!e){a=typeof a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
|
||||
8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k===
|
||||
"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+
|
||||
d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f<l;f++){var k=d[f];if(b||e.test(k.namespace)){a.handler=k.handler;a.data=k.data;a.handleObj=k;k=k.handler.apply(this,h);if(k!==B){a.result=k;if(k===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||
fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement||t;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=t.documentElement;d=t.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(a.which==null&&(a.charCode!=null||a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==B)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ka,guid:a.handler.guid}))},remove:function(a){c.event.remove(this,
|
||||
Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=t.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=
|
||||
c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ca;var a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ca;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ca;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U};
|
||||
var va=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},wa=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?wa:va,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?wa:va)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!==
|
||||
"form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length){a.liveFired=B;return la("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=B;return la("submit",this,arguments)}})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var V,
|
||||
xa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired=
|
||||
B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type===
|
||||
"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]===
|
||||
0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h<k;h++)c.event.add(this[h],d,l,e)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d,
|
||||
a[d]);else{d=0;for(var e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,e){return this.live(b,d,e,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return d.result}},toggle:function(a){for(var b=arguments,d=
|
||||
1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return b[f].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var ya={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var l,k=0,o,x,r=h||this.selector;h=h?this:c(this.context);if(typeof d===
|
||||
"object"&&!d.preventDefault){for(l in d)h[b](l,e,d[l],r);return this}if(c.isFunction(e)){f=e;e=B}for(d=(d||"").split(" ");(l=d[k++])!=null;){o=X.exec(l);x="";if(o){x=o[0];l=l.replace(X,"")}if(l==="hover")d.push("mouseenter"+x,"mouseleave"+x);else{o=l;if(l==="focus"||l==="blur"){d.push(ya[l]+x);l+=x}else l=(ya[l]||l)+x;if(b==="live"){x=0;for(var A=h.length;x<A;x++)c.event.add(h[x],"live."+Y(l,r),{data:e,selector:r,handler:f,origType:l,origHandler:f,preType:o})}else h.unbind("live."+Y(l,r),f)}}return this}});
|
||||
c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return arguments.length>0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
|
||||
(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1&&!q){y.sizcache=n;y.sizset=p}if(y.nodeName.toLowerCase()===i){F=y;break}y=y[g]}m[p]=F}}}function b(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1){if(!q){y.sizcache=n;y.sizset=p}if(typeof i!=="string"){if(y===i){F=true;break}}else if(k.filter(i,
|
||||
[y]).length>0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3];
|
||||
break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr,
|
||||
q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h=
|
||||
l;g.sort(w);if(h)for(var i=1;i<g.length;i++)g[i]===g[i-1]&&g.splice(i--,1)}return g};k.matches=function(g,i){return k(g,null,null,i)};k.matchesSelector=function(g,i){return k(i,null,null,[g]).length>0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p<q;p++){var u,y=o.order[p];if(u=o.leftMatch[y].exec(g)){var F=u[1];u.splice(1,1);if(F.substr(F.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");m=o.find[y](u,i,n);if(m!=null){g=g.replace(o.match[y],"");break}}}}m||(m=i.getElementsByTagName("*"));
|
||||
return{set:m,expr:g}};k.filter=function(g,i,n,m){for(var p,q,u=g,y=[],F=i,M=i&&i[0]&&k.isXML(i[0]);g&&i.length;){for(var N in o.filter)if((p=o.leftMatch[N].exec(g))!=null&&p[2]){var O,D,R=o.filter[N];D=p[1];q=false;p.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(F===y)y=[];if(o.preFilter[N])if(p=o.preFilter[N](p,F,n,y,m,M)){if(p===true)continue}else q=O=true;if(p)for(var j=0;(D=F[j])!=null;j++)if(D){O=R(D,p,j,F);var s=m^!!O;if(n&&O!=null)if(s)q=true;else F[j]=false;else if(s){y.push(D);q=true}}if(O!==
|
||||
B){n||(F=y);g=g.replace(o.match[N],"");if(!q)return[];break}}}if(g===u)if(q==null)k.error(g);else break;u=g}return F};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var o=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
|
||||
POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,i){var n=typeof i==="string",m=n&&!/\W/.test(i);n=n&&!m;if(m)i=i.toLowerCase();m=0;for(var p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=n||q&&q.nodeName.toLowerCase()===
|
||||
i?q||false:q===i}n&&k.filter(i,g,true)},">":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p<q;p++){if(n=g[p]){n=n.parentNode;g[p]=n.nodeName.toLowerCase()===i?n:false}}else{for(;p<q;p++)if(n=g[p])g[p]=m?n.parentNode:n.parentNode===i;m&&k.filter(i,g,true)}},"":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=i=i.toLowerCase();q=a}q("parentNode",i,p,g,m,n)},"~":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=
|
||||
i=i.toLowerCase();q=a}q("previousSibling",i,p,g,m,n)}},find:{ID:function(g,i,n){if(typeof i.getElementById!=="undefined"&&!n)return(g=i.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,i){if(typeof i.getElementsByName!=="undefined"){for(var n=[],m=i.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&n.push(m[p]);return n.length===0?null:n}},TAG:function(g,i){return i.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,i,n,m,p,q){g=" "+g[1].replace(/\\/g,
|
||||
"")+" ";if(q)return g;q=0;for(var u;(u=i[q])!=null;q++)if(u)if(p^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n,
|
||||
m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===
|
||||
true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===
|
||||
g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return i<n[3]-0},gt:function(g,i,n){return i>n[3]-0},nth:function(g,i,n){return n[3]-
|
||||
0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n<m;n++)if(i[n]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+p)},CHILD:function(g,i){var n=i[1],m=g;switch(n){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(n===
|
||||
"first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":n=i[2];var p=i[3];if(n===1&&p===0)return true;var q=i[0],u=g.parentNode;if(u&&(u.sizcache!==q||!g.nodeIndex)){var y=0;for(m=u.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++y;u.sizcache=q}m=g.nodeIndex-p;return n===0?m===0:m%n===0&&m/n>=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===
|
||||
i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]];
|
||||
if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m,
|
||||
g);else if(typeof g.length==="number")for(var p=g.length;n<p;n++)m.push(g[n]);else for(;g[n];n++)m.push(g[n]);return m}}var w,I;if(t.documentElement.compareDocumentPosition)w=function(g,i){if(g===i){h=true;return 0}if(!g.compareDocumentPosition||!i.compareDocumentPosition)return g.compareDocumentPosition?-1:1;return g.compareDocumentPosition(i)&4?-1:1};else{w=function(g,i){var n,m,p=[],q=[];n=g.parentNode;m=i.parentNode;var u=n;if(g===i){h=true;return 0}else if(n===m)return I(g,i);else if(n){if(!m)return 1}else return-1;
|
||||
for(;u;){p.unshift(u);u=u.parentNode}for(u=m;u;){q.unshift(u);u=u.parentNode}n=p.length;m=q.length;for(u=0;u<n&&u<m;u++)if(p[u]!==q[u])return I(p[u],q[u]);return u===n?I(g,q[u],-1):I(p[u],i,1)};I=function(g,i,n){if(g===i)return n;for(g=g.nextSibling;g;){if(g===i)return-1;g=g.nextSibling}return 1}}k.getText=function(g){for(var i="",n,m=0;g[m];m++){n=g[m];if(n.nodeType===3||n.nodeType===4)i+=n.nodeValue;else if(n.nodeType!==8)i+=k.getText(n.childNodes)}return i};(function(){var g=t.createElement("div"),
|
||||
i="script"+(new Date).getTime(),n=t.documentElement;g.innerHTML="<a name='"+i+"'/>";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g);
|
||||
n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&&
|
||||
function(){var g=k,i=t.createElement("div");i.innerHTML="<p class='TEST'></p>";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F||
|
||||
p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g=
|
||||
t.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition?
|
||||
function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n<u;n++)k(g,q[n],m);return k.filter(p,m)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=k.getText;c.isXMLDoc=k.isXML;
|
||||
c.contains=k.contains})();var Za=/Until$/,$a=/^(?:parents|prevUntil|prevAll)/,ab=/,/,Na=/^.[^:#\[\.,]*$/,bb=Array.prototype.slice,cb=c.expr.match.POS;c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var h=d;h<b.length;h++)for(var l=0;l<d;l++)if(b[l]===b[h]){b.splice(h--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return true})},
|
||||
not:function(a){return this.pushStack(ma(this,a,false),"not",a)},filter:function(a){return this.pushStack(ma(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e<f;e++){l=a[e];k[l]||(k[l]=c.expr.match.POS.test(l)?c(l,b||this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in k){e=k[l];if(e.jquery?e.index(h)>-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h=
|
||||
h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e<f;e++)for(h=this[e];h;)if(l?l.index(h)>-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):
|
||||
c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,
|
||||
2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,
|
||||
b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&
|
||||
e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/<tbody/i,eb=/<|&#?\w+;/,Ca=/<(?:script|object|embed|option|style)/i,Da=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/\=([^="'>\s]+\/)>/g,P={option:[1,
|
||||
"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
|
||||
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
|
||||
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
|
||||
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
|
||||
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
|
||||
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null;
|
||||
else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1></$2>");try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else c.isFunction(a)?this.each(function(f){var h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=
|
||||
c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){var e,f,h,l=a[0],k=[];if(!c.support.checkClone&&arguments.length===3&&typeof l==="string"&&Da.test(l))return this.each(function(){c(this).domManip(a,
|
||||
b,d,true)});if(c.isFunction(l))return this.each(function(x){var r=c(this);a[0]=l.call(this,x,b?r.html():B);r.domManip(a,b,d)});if(this[0]){e=l&&l.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);h=e.fragment;if(f=h.childNodes.length===1?h=h.firstChild:h.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var o=this.length;f<o;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]||this[f].appendChild(this[f].ownerDocument.createElement("tbody")):
|
||||
this[f]:this[f],f>0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",
|
||||
prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f<h;f++){var l=(f>0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument||
|
||||
b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1></$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]==="<table>"&&!x?r.childNodes:[];for(o=k.length-
|
||||
1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
|
||||
d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
|
||||
jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
|
||||
zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
|
||||
h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
|
||||
if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
|
||||
d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
|
||||
e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
||||
ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b===
|
||||
"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("<div>").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&
|
||||
!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})},
|
||||
getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html",
|
||||
script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data||
|
||||
!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache=
|
||||
false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset;
|
||||
A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type",
|
||||
b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&&
|
||||
c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d||
|
||||
c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]=
|
||||
encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",
|
||||
[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),
|
||||
e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}});
|
||||
if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show",
|
||||
3),a,b,d);else{d=0;for(var e=this.length;d<e;d++){a=this[d];b=a.style.display;if(!c.data(a,"olddisplay")&&b==="none")b=a.style.display="";b===""&&c.css(a,"display")==="none"&&c.data(a,"olddisplay",qa(a.nodeName))}for(d=0;d<e;d++){a=this[d];b=a.style.display;if(b===""||b==="none")a.style.display=c.data(a,"olddisplay")||""}return this}},hide:function(a,b,d){if(a||a===0)return this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay",
|
||||
d)}for(a=0;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||e?this.each(function(){var f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return this},fadeTo:function(a,b,d,e){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var f=c.speed(b,
|
||||
d,e);if(c.isEmptyObject(a))return this.each(f.complete);return this[f.queue===false?"each":"queue"](function(){var h=c.extend({},f),l,k=this.nodeType===1,o=k&&c(this).is(":hidden"),x=this;for(l in a){var r=c.camelCase(l);if(l!==r){a[r]=a[l];delete a[l];l=r}if(a[l]==="hide"&&o||a[l]==="show"&&!o)return h.complete.call(this);if(k&&(l==="height"||l==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(qa(this.nodeName)===
|
||||
"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else this.style.display="inline-block"}if(c.isArray(a[l])){(h.specialEasing=h.specialEasing||{})[l]=a[l][1];a[l]=a[l][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(A,C){var J=new c.fx(x,h,A);if(vb.test(C))J[C==="toggle"?o?"show":"hide":C](a);else{var w=wb.exec(C),I=J.cur()||0;if(w){var L=parseFloat(w[2]),g=w[3]||"px";if(g!=="px"){c.style(x,A,(L||1)+g);I=(L||
|
||||
1)/J.cur()*I;c.style(x,A,I+g)}if(w[1])L=(w[1]==="-="?-1:1)*L+I;J.custom(I,L,g)}else J.custom(I,C,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var e=d.length-1;e>=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b,
|
||||
d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a*
|
||||
Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)}
|
||||
var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;
|
||||
this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide||
|
||||
this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=
|
||||
c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},interval:13,stop:function(){clearInterval(ba);ba=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===
|
||||
b.elem}).length};var xb=/^t(?:able|d|h)$/i,Ia=/^(?:body|html)$/i;c.fn.offset="getBoundingClientRect"in t.documentElement?function(a){var b=this[0],d;if(a)return this.each(function(l){c.offset.setOffset(this,a,l)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||{top:0,left:0};b=f.body;f=fa(f);return{top:d.top+(f.pageYOffset||c.support.boxModel&&
|
||||
h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(x){c.offset.setOffset(this,a,x)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d,e=b.offsetParent,f=b.ownerDocument,h=f.documentElement,l=f.body;d=(f=f.defaultView)?f.getComputedStyle(b,null):b.currentStyle;
|
||||
for(var k=b.offsetTop,o=b.offsetLeft;(b=b.parentNode)&&b!==l&&b!==h;){if(c.offset.supportsFixedPosition&&d.position==="fixed")break;d=f?f.getComputedStyle(b,null):b.currentStyle;k-=b.scrollTop;o-=b.scrollLeft;if(b===e){k+=b.offsetTop;o+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&xb.test(b.nodeName))){k+=parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}e=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"){k+=
|
||||
parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}d=d}if(d.position==="relative"||d.position==="static"){k+=l.offsetTop;o+=l.offsetLeft}if(c.offset.supportsFixedPosition&&d.position==="fixed"){k+=Math.max(h.scrollTop,l.scrollTop);o+=Math.max(h.scrollLeft,l.scrollLeft)}return{top:k,left:o}};c.offset={initialize:function(){var a=t.body,b=t.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",
|
||||
height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells=
|
||||
f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a,
|
||||
"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||0}return{top:b,left:d}},setOffset:function(a,b,d){var e=c.css(a,"position");if(e==="static")a.style.position="relative";var f=c(a),h=f.offset(),l=c.css(a,"top"),k=c.css(a,"left"),o=e==="absolute"&&c.inArray("auto",[l,k])>-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a,
|
||||
e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&&
|
||||
c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();
|
||||
c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+
|
||||
b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window);
|
@ -1,35 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This is a content script. It executes inside the context of the Reddit page
|
||||
// loaded into the panel and has access to that page's window object and other
|
||||
// global objects (although the page does not have access to globals defined by
|
||||
// this script unless they are explicitly attached to the window object).
|
||||
//
|
||||
// This content script is injected into the context of the Reddit page
|
||||
// by the Panel API, which is accessed by the main add-on script in lib/main.js.
|
||||
// See that script for more information about how the panel is created.
|
||||
|
||||
$(window).click(function (event) {
|
||||
var t = event.target;
|
||||
|
||||
// Don't intercept the click if it isn't on a link.
|
||||
if (t.nodeName != "A")
|
||||
return;
|
||||
|
||||
// Don't intercept the click if it was on one of the links in the header
|
||||
// or next/previous footer, since those links should load in the panel itself.
|
||||
if ($(t).parents('#header').length || $(t).parents('.nextprev').length)
|
||||
return;
|
||||
|
||||
// Intercept the click, passing it to the addon, which will load it in a tab.
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
self.port.emit('click', t.toString());
|
||||
});
|
||||
|
||||
// Panels have an OS-specific background color by default, and the Mac OS X
|
||||
// background color is dark grey, but Reddit expects its background to be white
|
||||
// and looks odd when it isn't, so set it to white.
|
||||
$("body").css("background", "white");
|
@ -1,49 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var { data } = require("sdk/self");
|
||||
var { ToggleButton } = require("sdk/ui");
|
||||
|
||||
var base64png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
|
||||
"AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
|
||||
"N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
|
||||
"bWRR9AAAAABJRU5ErkJggg%3D%3D";
|
||||
|
||||
var reddit_panel = require("sdk/panel").Panel({
|
||||
width: 240,
|
||||
height: 320,
|
||||
contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
|
||||
contentScriptFile: [data.url("jquery-1.4.4.min.js"),
|
||||
data.url("panel.js")],
|
||||
onHide: handleHide
|
||||
});
|
||||
|
||||
reddit_panel.port.on("click", function(url) {
|
||||
require("sdk/tabs").open(url);
|
||||
});
|
||||
|
||||
let button = ToggleButton({
|
||||
id: "open-reddit-btn",
|
||||
label: "Reddit",
|
||||
icon: base64png,
|
||||
onChange: handleChange
|
||||
});
|
||||
|
||||
exports.main = function(options, callbacks) {
|
||||
// If you run cfx with --static-args='{"quitWhenDone":true}' this program
|
||||
// will automatically quit Firefox when it's done.
|
||||
if (options.staticArgs.quitWhenDone)
|
||||
callbacks.quit();
|
||||
};
|
||||
|
||||
function handleChange(state) {
|
||||
if (state.checked) {
|
||||
reddit_panel.show({ position: button });
|
||||
}
|
||||
}
|
||||
|
||||
function handleHide() {
|
||||
button.state('window', { checked: false });
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"license": "MPL 2.0",
|
||||
"name": "reddit-panel",
|
||||
"contributors": [],
|
||||
"author": "Myk Melez",
|
||||
"keywords": [],
|
||||
"description": "Displays Reddit in a panel.",
|
||||
"id": "anonid0-reddit-panel"
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var m = require("main");
|
||||
var self = require("sdk/self");
|
||||
|
||||
exports.testMain = function(test) {
|
||||
var callbacks = { quit: function() {
|
||||
test.pass();
|
||||
test.done();
|
||||
} };
|
||||
|
||||
test.waitUntilDone();
|
||||
// Make sure it doesn't crash...
|
||||
m.main({ staticArgs: {quitWhenDone: true} }, callbacks);
|
||||
};
|
||||
|
||||
exports.testData = function(test) {
|
||||
test.assert(self.data.load("panel.js").length > 0);
|
||||
};
|
@ -8,10 +8,10 @@ module.metadata = {
|
||||
};
|
||||
|
||||
const { Ci } = require("chrome");
|
||||
const method = require("../../method/core");
|
||||
const { dispatcher } = require("../util/dispatcher");
|
||||
const { add, remove, iterator } = require("../lang/weak-set");
|
||||
|
||||
let getTargetWindow = method("getTargetWindow");
|
||||
let getTargetWindow = dispatcher("getTargetWindow");
|
||||
|
||||
getTargetWindow.define(function (target) {
|
||||
if (target instanceof Ci.nsIDOMWindow)
|
||||
@ -24,10 +24,10 @@ getTargetWindow.define(function (target) {
|
||||
|
||||
exports.getTargetWindow = getTargetWindow;
|
||||
|
||||
let attachTo = method("attachTo");
|
||||
let attachTo = dispatcher("attachTo");
|
||||
exports.attachTo = attachTo;
|
||||
|
||||
let detachFrom = method("detatchFrom");
|
||||
let detachFrom = dispatcher("detatchFrom");
|
||||
exports.detachFrom = detachFrom;
|
||||
|
||||
function attach(modification, target) {
|
||||
|
@ -17,7 +17,8 @@ const PROMISE_URI = 'resource://gre/modules/Promise.jsm';
|
||||
|
||||
getEnvironment.call(this, function ({ require, exports, module, Cu }) {
|
||||
|
||||
const { defer, resolve, all, reject, race } = Cu.import(PROMISE_URI, {}).Promise;
|
||||
const Promise = Cu.import(PROMISE_URI, {}).Promise;
|
||||
const { Debugging, defer, resolve, all, reject, race } = Promise;
|
||||
|
||||
module.metadata = {
|
||||
'stability': 'unstable'
|
||||
@ -75,7 +76,7 @@ exports.resolve = resolve;
|
||||
exports.reject = reject;
|
||||
exports.race = race;
|
||||
exports.Promise = Promise;
|
||||
|
||||
exports.Debugging = Debugging;
|
||||
});
|
||||
|
||||
function getEnvironment (callback) {
|
||||
|
@ -50,7 +50,7 @@ const removeDups = (array) => array.reduce((result, value) => {
|
||||
return result;
|
||||
}, []);
|
||||
|
||||
const getSuites = function getSuites({ id }) {
|
||||
const getSuites = function getSuites({ id, filter }) {
|
||||
return getAddon(id).then(addon => {
|
||||
let fileURI = addon.getResourceURI("tests/");
|
||||
let isPacked = fileURI.scheme == "jar";
|
||||
@ -58,9 +58,8 @@ const getSuites = function getSuites({ id }) {
|
||||
let file = xpiURI.QueryInterface(Ci.nsIFileURL).file;
|
||||
let suites = [];
|
||||
let addEntry = (entry) => {
|
||||
let pass = TEST_REGEX.test(entry);
|
||||
if (pass) {
|
||||
let suite = (isNative ? "./" : "") + RegExp.$2 + RegExp.$3;
|
||||
if (filter(entry) && TEST_REGEX.test(entry)) {
|
||||
let suite = (isNative ? "./" : "") + (RegExp.$2 || "") + RegExp.$3;
|
||||
suites.push(suite);
|
||||
}
|
||||
}
|
||||
@ -90,7 +89,9 @@ const getSuites = function getSuites({ id }) {
|
||||
}
|
||||
exports.getSuites = getSuites;
|
||||
|
||||
const makeFilter = function makeFilter(options) {
|
||||
const makeFilters = function makeFilters(options) {
|
||||
options = options || {};
|
||||
|
||||
// A filter string is {fileNameRegex}[:{testNameRegex}] - ie, a colon
|
||||
// optionally separates a regex for the test fileName from a regex for the
|
||||
// testName.
|
||||
@ -100,23 +101,24 @@ const makeFilter = function makeFilter(options) {
|
||||
|
||||
if (colonPos === -1) {
|
||||
filterFileRegex = new RegExp(options.filter);
|
||||
filterNameRegex = { test: () => true }
|
||||
} else {
|
||||
filterFileRegex = new RegExp(options.filter.substr(0, colonPos));
|
||||
filterNameRegex = new RegExp(options.filter.substr(colonPos + 1));
|
||||
}
|
||||
// This function will first be called with just the filename; if
|
||||
// it returns true the module will be loaded then the function
|
||||
// called again with both the filename and the testname.
|
||||
return (filename, testname) => {
|
||||
return filterFileRegex.test(filename) &&
|
||||
((testname && filterNameRegex) ? filterNameRegex.test(testname)
|
||||
: true);
|
||||
};
|
||||
|
||||
return {
|
||||
fileFilter: (name) => filterFileRegex.test(name),
|
||||
testFilter: (name) => filterNameRegex.test(name)
|
||||
}
|
||||
}
|
||||
|
||||
return () => true;
|
||||
return {
|
||||
fileFilter: () => true,
|
||||
testFilter: () => true
|
||||
};
|
||||
}
|
||||
exports.makeFilter = makeFilter;
|
||||
exports.makeFilters = makeFilters;
|
||||
|
||||
let loader = Loader(module);
|
||||
const NOT_TESTS = ['setup', 'teardown'];
|
||||
@ -130,8 +132,9 @@ var TestFinder = exports.TestFinder = function TestFinder(options) {
|
||||
|
||||
TestFinder.prototype = {
|
||||
findTests: function findTests() {
|
||||
return getSuites({ id: id }).then(suites => {
|
||||
let filter = makeFilter({ filter: this.filter });
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: this.filter });
|
||||
|
||||
return getSuites({ id: id, filter: fileFilter }).then(suites => {
|
||||
let tests = [];
|
||||
|
||||
suites.forEach(suite => {
|
||||
@ -158,7 +161,7 @@ TestFinder.prototype = {
|
||||
|
||||
if (this.testInProcess) {
|
||||
for (let name of Object.keys(suiteModule).sort()) {
|
||||
if (NOT_TESTS.indexOf(name) === -1 && filter(suite, name)) {
|
||||
if (NOT_TESTS.indexOf(name) === -1 && testFilter(name)) {
|
||||
tests.push({
|
||||
setup: suiteModule.setup,
|
||||
teardown: suiteModule.teardown,
|
||||
|
@ -10,9 +10,9 @@ module.metadata = {
|
||||
const memory = require("./memory");
|
||||
const timer = require("../timers");
|
||||
const cfxArgs = require("../test/options");
|
||||
const { getTabs, getURI } = require("../tabs/utils");
|
||||
const { getTabs, closeTab, getURI } = require("../tabs/utils");
|
||||
const { windows, isBrowser } = require("../window/utils");
|
||||
const { defer, all } = require("../core/promise");
|
||||
const { defer, all, Debugging: PromiseDebugging } = require("../core/promise");
|
||||
|
||||
const findAndRunTests = function findAndRunTests(options) {
|
||||
var TestFinder = require("./unit-test-finder").TestFinder;
|
||||
@ -48,7 +48,7 @@ const TestRunner = function TestRunner(options) {
|
||||
TestRunner.prototype = {
|
||||
toString: function toString() "[object TestRunner]",
|
||||
|
||||
DEFAULT_PAUSE_TIMEOUT: cfxArgs.parseable ? 5*60000 : 15000,
|
||||
DEFAULT_PAUSE_TIMEOUT: (cfxArgs.parseable ? 300000 : 15000), //Five minutes (5*60*1000ms)
|
||||
PAUSE_DELAY: 500,
|
||||
|
||||
_logTestFailed: function _logTestFailed(why) {
|
||||
@ -57,6 +57,10 @@ TestRunner.prototype = {
|
||||
this.test.errors[why]++;
|
||||
},
|
||||
|
||||
_uncaughtErrorObserver: function({message, date, fileName, stack, lineNumber}) {
|
||||
this.fail("There was an uncaught Promise rejection: " + stack);
|
||||
},
|
||||
|
||||
pass: function pass(message) {
|
||||
if(!this.expectFailure) {
|
||||
if ("testMessage" in this.console)
|
||||
@ -299,6 +303,8 @@ TestRunner.prototype = {
|
||||
return promise;
|
||||
});
|
||||
|
||||
PromiseDebugging.flushUncaughtErrors();
|
||||
|
||||
all(winPromises).then(_ => {
|
||||
let tabs = [];
|
||||
for (let win of wins.filter(isBrowser)) {
|
||||
@ -306,6 +312,7 @@ TestRunner.prototype = {
|
||||
tabs.push(tab);
|
||||
}
|
||||
}
|
||||
let leftover = tabs.slice(1);
|
||||
|
||||
if (wins.length != 1)
|
||||
this.fail("Should not be any unexpected windows open");
|
||||
@ -324,6 +331,8 @@ TestRunner.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
leftover.forEach(closeTab);
|
||||
|
||||
this.testRunSummary.push({
|
||||
name: this.test.name,
|
||||
passed: this.test.passed,
|
||||
@ -492,6 +501,8 @@ TestRunner.prototype = {
|
||||
this.test.passed = 0;
|
||||
this.test.failed = 0;
|
||||
this.test.errors = {};
|
||||
PromiseDebugging.clearUncaughtErrorObservers();
|
||||
PromiseDebugging.addUncaughtErrorObserver(this._uncaughtErrorObserver.bind(this));
|
||||
|
||||
this.isDone = false;
|
||||
this.onDone = function(self) {
|
||||
|
@ -90,7 +90,12 @@ function createBookmarkItem (data) {
|
||||
if (data.index === -1)
|
||||
data.index = bmsrv.getItemIndex(data.id);
|
||||
|
||||
data.updated = bmsrv.getItemLastModified(data.id);
|
||||
try {
|
||||
data.updated = bmsrv.getItemLastModified(data.id);
|
||||
}
|
||||
catch (e) {
|
||||
console.exception(e);
|
||||
}
|
||||
|
||||
return tag(data, true).then(() => data);
|
||||
}
|
||||
@ -194,34 +199,24 @@ exports.getChildren = getChildren;
|
||||
* Hook into host
|
||||
*/
|
||||
|
||||
let reqStream = filter(request, function (data) /sdk-places-bookmarks/.test(data.event));
|
||||
on(reqStream, 'data', function ({event, id, data}) {
|
||||
let reqStream = filter(request, (data) => /sdk-places-bookmarks/.test(data.event));
|
||||
on(reqStream, 'data', ({ event, id, data }) => {
|
||||
if (!EVENT_MAP[event]) return;
|
||||
|
||||
let resData = {
|
||||
id: id,
|
||||
event: event
|
||||
};
|
||||
let resData = { id: id, event: event };
|
||||
|
||||
promised(EVENT_MAP[event])(data).then(res => {
|
||||
resData.data = res;
|
||||
respond(resData);
|
||||
}, reason => {
|
||||
resData.error = reason;
|
||||
respond(resData);
|
||||
});
|
||||
promised(EVENT_MAP[event])(data).
|
||||
then(res => resData.data = res, e => resData.error = e).
|
||||
then(() => emit(response, 'data', resData));
|
||||
});
|
||||
|
||||
function respond (data) {
|
||||
emit(response, 'data', data);
|
||||
}
|
||||
|
||||
function tag (data, isNew) {
|
||||
// If a new item, we can skip checking what other tags
|
||||
// are on the item
|
||||
if (data.type !== 'bookmark') {
|
||||
return resolve();
|
||||
} else if (!isNew) {
|
||||
}
|
||||
else if (!isNew) {
|
||||
return send('sdk-places-tags-get-tags-by-url', { url: data.url })
|
||||
.then(tags => {
|
||||
return send('sdk-places-tags-untag', {
|
||||
|
@ -13,7 +13,7 @@ const { URL, isLocalURL } = require('../url');
|
||||
const events = require("../system/events");
|
||||
const { loadSheet, removeSheet, isTypeValid } = require("./utils");
|
||||
const { isString } = require("../lang/type");
|
||||
const { attachTo, detachFrom, getTargetWindow } = require("../content/mod");
|
||||
const { attachTo, detachFrom } = require("../content/mod");
|
||||
const { data } = require('../self');
|
||||
|
||||
const { freeze, create } = Object;
|
||||
|
@ -195,7 +195,7 @@ function execFile (file, ...args) {
|
||||
env: null,
|
||||
encoding: 'utf8',
|
||||
timeout: 0,
|
||||
maxBuffer: 200 * 1024,
|
||||
maxBuffer: 204800, //200 KB (200*1024 bytes)
|
||||
killSignal: 'SIGTERM'
|
||||
};
|
||||
|
||||
|
@ -11,9 +11,18 @@ module.metadata = {
|
||||
}
|
||||
};
|
||||
|
||||
const { getTargetWindow } = require("../content/mod");
|
||||
const { getTabContentWindow, isTab } = require("./utils");
|
||||
const { viewFor } = require("../view/core");
|
||||
|
||||
if (require('../system/xul-app').name == 'Fennec') {
|
||||
module.exports = require('./tab-fennec');
|
||||
}
|
||||
else {
|
||||
module.exports = require('./tab-firefox');
|
||||
}
|
||||
|
||||
getTargetWindow.when(isTab, tab => getTabContentWindow(tab));
|
||||
|
||||
getTargetWindow.when(x => x instanceof module.exports.Tab,
|
||||
tab => getTabContentWindow(viewFor(tab)));
|
||||
|
@ -253,6 +253,8 @@ function cleanup() {
|
||||
consoleListener.errorsLogged = 0;
|
||||
loader = null;
|
||||
|
||||
consoleListener.unregister();
|
||||
|
||||
memory.gc();
|
||||
}
|
||||
catch (e) {
|
||||
@ -354,7 +356,7 @@ function getPotentialLeaks() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (matches = windowRegexp.exec(path)) {
|
||||
if ((matches = windowRegexp.exec(path))) {
|
||||
if (matches[1] in windows)
|
||||
return;
|
||||
|
||||
@ -440,7 +442,24 @@ var POINTLESS_ERRORS = [
|
||||
];
|
||||
|
||||
var consoleListener = {
|
||||
registered: false,
|
||||
|
||||
register: function() {
|
||||
if (this.registered)
|
||||
return;
|
||||
cService.registerListener(this);
|
||||
this.registered = true;
|
||||
},
|
||||
|
||||
unregister: function() {
|
||||
if (!this.registered)
|
||||
return;
|
||||
cService.unregisterListener(this);
|
||||
this.registered = false;
|
||||
},
|
||||
|
||||
errorsLogged: 0,
|
||||
|
||||
observe: function(object) {
|
||||
if (!(object instanceof Ci.nsIScriptError))
|
||||
return;
|
||||
@ -572,7 +591,7 @@ var runTests = exports.runTests = function runTests(options) {
|
||||
findAndRunTests = options.findAndRunTests;
|
||||
|
||||
try {
|
||||
cService.registerListener(consoleListener);
|
||||
consoleListener.register();
|
||||
print("Running tests on " + system.name + " " + system.version +
|
||||
"/Gecko " + system.platformVersion + " (" +
|
||||
system.id + ") under " +
|
||||
@ -592,7 +611,8 @@ var runTests = exports.runTests = function runTests(options) {
|
||||
// memory when we check later
|
||||
require("../deprecated/unit-test");
|
||||
require("../deprecated/unit-test-finder");
|
||||
startLeaks = getPotentialLeaks();
|
||||
if (profileMemory)
|
||||
startLeaks = getPotentialLeaks();
|
||||
|
||||
nextIteration();
|
||||
} catch (e) {
|
||||
@ -621,4 +641,4 @@ var runTests = exports.runTests = function runTests(options) {
|
||||
}
|
||||
};
|
||||
|
||||
unload(_ => cService.unregisterListener(consoleListener));
|
||||
unload(_ => consoleListener.unregister());
|
||||
|
@ -15,8 +15,9 @@ const readPref = (key) => get("extensions." + id + ".sdk." + key);
|
||||
|
||||
exports.iterations = readPref("test.iterations") || options.iterations;
|
||||
exports.filter = readPref("test.filter") || options.filter;
|
||||
exports.profileMemory = readPref("profile.memory") || options.profileMemory,
|
||||
exports.stopOnError = readPref("test.stop") || options.stopOnError,
|
||||
exports.profileMemory = readPref("profile.memory") || options.profileMemory;
|
||||
exports.stopOnError = readPref("test.stop") || options.stopOnError;
|
||||
exports.keepOpen = readPref("test.keepOpen") || false;
|
||||
exports.verbose = (readPref("output.logLevel") == "verbose") || options.verbose;
|
||||
exports.parseable = (readPref("output.format") == "tbpl") || options.parseable;
|
||||
exports.checkMemory = readPref("profile.leaks") || options.check_memory;
|
||||
|
@ -9,6 +9,7 @@ module.metadata = {
|
||||
|
||||
var { exit, stdout } = require("../system");
|
||||
var cfxArgs = require("../test/options");
|
||||
var events = require("../system/events");
|
||||
|
||||
function runTests(findAndRunTests) {
|
||||
var harness = require("./harness");
|
||||
@ -18,14 +19,18 @@ function runTests(findAndRunTests) {
|
||||
var total = tests.passed + tests.failed;
|
||||
stdout.write(tests.passed + " of " + total + " tests passed.\n");
|
||||
|
||||
events.emit("sdk:test:results", { data: JSON.stringify(tests) });
|
||||
|
||||
if (tests.failed == 0) {
|
||||
if (tests.passed === 0)
|
||||
stdout.write("No tests were run\n");
|
||||
exit(0);
|
||||
if (!cfxArgs.keepOpen)
|
||||
exit(0);
|
||||
} else {
|
||||
if (cfxArgs.verbose || cfxArgs.parseable)
|
||||
printFailedTests(tests, stdout.write);
|
||||
exit(1);
|
||||
if (!cfxArgs.keepOpen)
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -87,7 +87,7 @@ const Sidebar = Class({
|
||||
|
||||
bar.addEventListener('command', function() {
|
||||
if (isSidebarShowing(window, self)) {
|
||||
hideSidebar(window, self);
|
||||
hideSidebar(window, self).catch(() => {});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@ const Sidebar = Class({
|
||||
return;
|
||||
|
||||
// hide the sidebar if it is showing
|
||||
hideSidebar(window, self);
|
||||
hideSidebar(window, self).catch(() => {});
|
||||
|
||||
// kill the menu item
|
||||
let { bar } = windowNS(window);
|
||||
@ -267,7 +267,7 @@ exports.Sidebar = Sidebar;
|
||||
|
||||
function validateTitleAndURLCombo(sidebar, title, url) {
|
||||
url = resolveURL(url);
|
||||
|
||||
|
||||
if (sidebar.title == title && sidebar.url == url) {
|
||||
return false;
|
||||
}
|
||||
|
@ -405,22 +405,23 @@ const nodeResolve = iced(function nodeResolve(id, requirer, { rootURI }) {
|
||||
// we assume that extensions are correct, i.e., a directory doesnt't have '.js'
|
||||
// and a js file isn't named 'file.json.js'
|
||||
let fullId = join(rootURI, id);
|
||||
|
||||
let resolvedPath;
|
||||
|
||||
if ((resolvedPath = loadAsFile(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
else if ((resolvedPath = loadAsDirectory(fullId)))
|
||||
|
||||
if ((resolvedPath = loadAsDirectory(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
|
||||
// If manifest has dependencies, attempt to look up node modules
|
||||
// in the `dependencies` list
|
||||
else {
|
||||
let dirs = getNodeModulePaths(dirname(join(rootURI, requirer))).map(dir => join(dir, id));
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
if ((resolvedPath = loadAsFile(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
if ((resolvedPath = loadAsDirectory(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
}
|
||||
let dirs = getNodeModulePaths(dirname(join(rootURI, requirer))).map(dir => join(dir, id));
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
if ((resolvedPath = loadAsFile(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
|
||||
if ((resolvedPath = loadAsDirectory(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
}
|
||||
|
||||
// We would not find lookup for things like `sdk/tabs`, as that's part of
|
||||
@ -452,14 +453,14 @@ function loadAsFile (path) {
|
||||
// Attempts to load `path/package.json`'s `main` entry,
|
||||
// followed by `path/index.js`, or `undefined` otherwise
|
||||
function loadAsDirectory (path) {
|
||||
let found;
|
||||
try {
|
||||
// If `path/package.json` exists, parse the `main` entry
|
||||
// and attempt to load that
|
||||
let main = getManifestMain(JSON.parse(readURI(path + '/package.json')));
|
||||
if (main != null) {
|
||||
let tmpPath = join(path, main);
|
||||
if ((found = loadAsFile(tmpPath)))
|
||||
let found = loadAsFile(tmpPath);
|
||||
if (found)
|
||||
return found
|
||||
}
|
||||
try {
|
||||
@ -533,7 +534,7 @@ exports.resolveURI = resolveURI;
|
||||
// with it during link time.
|
||||
const Require = iced(function Require(loader, requirer) {
|
||||
let {
|
||||
modules, mapping, resolve, load, manifest, rootURI, isNative, requireMap
|
||||
modules, mapping, resolve: loaderResolve, load, manifest, rootURI, isNative, requireMap
|
||||
} = loader;
|
||||
|
||||
function require(id) {
|
||||
@ -541,55 +542,7 @@ const Require = iced(function Require(loader, requirer) {
|
||||
throw Error('you must provide a module name when calling require() from '
|
||||
+ requirer.id, requirer.uri);
|
||||
|
||||
let requirement;
|
||||
let uri;
|
||||
|
||||
// TODO should get native Firefox modules before doing node-style lookups
|
||||
// to save on loading time
|
||||
if (isNative) {
|
||||
// If a requireMap is available from `generateMap`, use that to
|
||||
// immediately resolve the node-style mapping.
|
||||
if (requireMap && requireMap[requirer.id])
|
||||
requirement = requireMap[requirer.id][id];
|
||||
|
||||
// For native modules, we want to check if it's a module specified
|
||||
// in 'modules', like `chrome`, or `@loader` -- if it exists,
|
||||
// just set the uri to skip resolution
|
||||
if (!requirement && modules[id])
|
||||
uri = requirement = id;
|
||||
|
||||
// If no requireMap was provided, or resolution not found in
|
||||
// the requireMap, and not a npm dependency, attempt a runtime lookup
|
||||
if (!requirement && !isNodeModule(id)) {
|
||||
// If `isNative` defined, this is using the new, native-style
|
||||
// loader, not cuddlefish, so lets resolve using node's algorithm
|
||||
// and get back a path that needs to be resolved via paths mapping
|
||||
// in `resolveURI`
|
||||
requirement = resolve(id, requirer.id, {
|
||||
manifest: manifest,
|
||||
rootURI: rootURI
|
||||
});
|
||||
}
|
||||
|
||||
// If not found in the map, not a node module, and wasn't able to be
|
||||
// looked up, it's something
|
||||
// found in the paths most likely, like `sdk/tabs`, which should
|
||||
// be resolved relatively if needed using traditional resolve
|
||||
if (!requirement) {
|
||||
requirement = isRelative(id) ? exports.resolve(id, requirer.id) : id;
|
||||
}
|
||||
} else {
|
||||
// Resolve `id` to its requirer if it's relative.
|
||||
requirement = requirer ? resolve(id, requirer.id) : id;
|
||||
}
|
||||
|
||||
// Resolves `uri` of module using loaders resolve function.
|
||||
uri = uri || resolveURI(requirement, mapping);
|
||||
|
||||
if (!uri) // Throw if `uri` can not be resolved.
|
||||
throw Error('Module: Can not resolve "' + id + '" module required by ' +
|
||||
requirer.id + ' located at ' + requirer.uri, requirer.uri);
|
||||
|
||||
let { uri, requirement } = getRequirements(id);
|
||||
let module = null;
|
||||
// If module is already cached by loader then just use it.
|
||||
if (uri in modules) {
|
||||
@ -643,6 +596,73 @@ const Require = iced(function Require(loader, requirer) {
|
||||
|
||||
return module.exports;
|
||||
}
|
||||
|
||||
// Resolution function taking a module name/path and
|
||||
// returning a resourceURI and a `requirement` used by the loader.
|
||||
// Used by both `require` and `require.resolve`.
|
||||
function getRequirements(id) {
|
||||
if (!id) // Throw if `id` is not passed.
|
||||
throw Error('you must provide a module name when calling require() from '
|
||||
+ requirer.id, requirer.uri);
|
||||
|
||||
let requirement;
|
||||
let uri;
|
||||
|
||||
// TODO should get native Firefox modules before doing node-style lookups
|
||||
// to save on loading time
|
||||
if (isNative) {
|
||||
// If a requireMap is available from `generateMap`, use that to
|
||||
// immediately resolve the node-style mapping.
|
||||
if (requireMap && requireMap[requirer.id])
|
||||
requirement = requireMap[requirer.id][id];
|
||||
|
||||
// For native modules, we want to check if it's a module specified
|
||||
// in 'modules', like `chrome`, or `@loader` -- if it exists,
|
||||
// just set the uri to skip resolution
|
||||
if (!requirement && modules[id])
|
||||
uri = requirement = id;
|
||||
|
||||
// If no requireMap was provided, or resolution not found in
|
||||
// the requireMap, and not a npm dependency, attempt a runtime lookup
|
||||
if (!requirement && !isNodeModule(id)) {
|
||||
// If `isNative` defined, this is using the new, native-style
|
||||
// loader, not cuddlefish, so lets resolve using node's algorithm
|
||||
// and get back a path that needs to be resolved via paths mapping
|
||||
// in `resolveURI`
|
||||
requirement = loaderResolve(id, requirer.id, {
|
||||
manifest: manifest,
|
||||
rootURI: rootURI
|
||||
});
|
||||
}
|
||||
|
||||
// If not found in the map, not a node module, and wasn't able to be
|
||||
// looked up, it's something
|
||||
// found in the paths most likely, like `sdk/tabs`, which should
|
||||
// be resolved relatively if needed using traditional resolve
|
||||
if (!requirement) {
|
||||
requirement = isRelative(id) ? exports.resolve(id, requirer.id) : id;
|
||||
}
|
||||
} else {
|
||||
// Resolve `id` to its requirer if it's relative.
|
||||
requirement = requirer ? loaderResolve(id, requirer.id) : id;
|
||||
}
|
||||
|
||||
// Resolves `uri` of module using loaders resolve function.
|
||||
uri = uri || resolveURI(requirement, mapping);
|
||||
|
||||
if (!uri) // Throw if `uri` can not be resolved.
|
||||
throw Error('Module: Can not resolve "' + id + '" module required by ' +
|
||||
requirer.id + ' located at ' + requirer.uri, requirer.uri);
|
||||
|
||||
return { uri: uri, requirement: requirement };
|
||||
}
|
||||
|
||||
// Expose the `resolve` function for this `Require` instance
|
||||
require.resolve = function resolve(id) {
|
||||
let { uri } = getRequirements(id);
|
||||
return uri;
|
||||
}
|
||||
|
||||
// Make `require.main === module` evaluate to true in main module scope.
|
||||
require.main = loader.main === requirer ? requirer : undefined;
|
||||
return iced(require);
|
||||
@ -864,14 +884,14 @@ function findAllModuleIncludes (uri, options, results, callback) {
|
||||
// Abort if JSON or JSM
|
||||
if (isJSONURI(uri) || isJSMURI(uri)) {
|
||||
callback(results);
|
||||
return void 0;
|
||||
return;
|
||||
}
|
||||
|
||||
findModuleIncludes(join(rootURI, uri), modules => {
|
||||
// If no modules are included in the file, just call callback immediately
|
||||
if (!modules.length) {
|
||||
callback(results);
|
||||
return void 0;
|
||||
return;
|
||||
}
|
||||
|
||||
results[uri] = modules.reduce((agg, mod) => {
|
||||
|
@ -239,6 +239,13 @@ parser_groups = (
|
||||
action="store_true",
|
||||
default=False,
|
||||
cmds=['test', 'run', 'xpi', 'testpkgs'])),
|
||||
(("", "--no-connections",), dict(dest="no_connections",
|
||||
help="disable/enable remote connections (on for cfx run only by default)",
|
||||
type="choice",
|
||||
choices=["on", "off", "default"],
|
||||
default="default",
|
||||
cmds=['test', 'run', 'testpkgs',
|
||||
'testall', 'testaddons', 'testex'])),
|
||||
]
|
||||
),
|
||||
|
||||
@ -746,14 +753,10 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
"lib", "sdk", "loader", "cuddlefish.js")
|
||||
loader_modules = [("addon-sdk", "lib", "sdk/loader/cuddlefish", cuddlefish_js_path)]
|
||||
scan_tests = command == "test"
|
||||
test_filter_re = None
|
||||
if scan_tests and options.filter:
|
||||
test_filter_re = options.filter
|
||||
if ":" in options.filter:
|
||||
test_filter_re = options.filter.split(":")[0]
|
||||
|
||||
try:
|
||||
manifest = build_manifest(target_cfg, pkg_cfg, deps, scan_tests,
|
||||
test_filter_re, loader_modules,
|
||||
None, loader_modules,
|
||||
abort_on_missing=options.abort_on_missing)
|
||||
except ModuleNotFoundError, e:
|
||||
print str(e)
|
||||
@ -899,6 +902,16 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
else:
|
||||
from cuddlefish.runner import run_app
|
||||
|
||||
if options.no_connections == "default":
|
||||
if command == "run":
|
||||
no_connections = False
|
||||
else:
|
||||
no_connections = True
|
||||
elif options.no_connections == "on":
|
||||
no_connections = True
|
||||
else:
|
||||
no_connections = False
|
||||
|
||||
if options.profiledir:
|
||||
options.profiledir = os.path.expanduser(options.profiledir)
|
||||
options.profiledir = os.path.abspath(options.profiledir)
|
||||
@ -931,7 +944,8 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
|
||||
overload_modules=options.overload_modules,
|
||||
bundle_sdk=options.bundle_sdk,
|
||||
pkgdir=options.pkgdir,
|
||||
enable_e10s=enable_e10s)
|
||||
enable_e10s=enable_e10s,
|
||||
no_connections=no_connections)
|
||||
except ValueError, e:
|
||||
print ""
|
||||
print "A given cfx option has an inappropriate value:"
|
||||
|
@ -19,6 +19,7 @@ DEFAULT_COMMON_PREFS = {
|
||||
|
||||
# Disable extension updates and notifications.
|
||||
'extensions.update.enabled' : False,
|
||||
'lightweightThemes.update.enabled' : False,
|
||||
'extensions.update.notifyUser' : False,
|
||||
|
||||
# From:
|
||||
@ -33,6 +34,24 @@ DEFAULT_COMMON_PREFS = {
|
||||
# Allow installing extensions dropped into the profile folder
|
||||
'extensions.autoDisableScopes' : 10,
|
||||
|
||||
}
|
||||
|
||||
DEFAULT_NO_CONNECTIONS_PREFS = {
|
||||
'toolkit.telemetry.enabled': False,
|
||||
'app.update.auto' : False,
|
||||
'app.update.url': 'http://localhost/app-dummy/update',
|
||||
'media.gmp-gmpopenh264.autoupdate' : False,
|
||||
'media.gmp-manager.cert.checkAttributes' : False,
|
||||
'media.gmp-manager.cert.requireBuiltIn' : False,
|
||||
'media.gmp-manager.url' : 'http://localhost/media-dummy/gmpmanager',
|
||||
'browser.newtab.url' : 'about:blank',
|
||||
'browser.search.update': False,
|
||||
'browser.safebrowsing.enabled' : False,
|
||||
'browser.safebrowsing.updateURL': 'http://localhost/safebrowsing-dummy/update',
|
||||
'browser.safebrowsing.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
|
||||
'browser.safebrowsing.reportURL': 'http://localhost/safebrowsing-dummy/report',
|
||||
'browser.safebrowsing.malware.reportURL': 'http://localhost/safebrowsing-dummy/malwarereport',
|
||||
|
||||
# Disable app update
|
||||
'app.update.enabled' : False,
|
||||
|
||||
|
@ -17,6 +17,7 @@ from cuddlefish.prefs import DEFAULT_COMMON_PREFS
|
||||
from cuddlefish.prefs import DEFAULT_FIREFOX_PREFS
|
||||
from cuddlefish.prefs import DEFAULT_THUNDERBIRD_PREFS
|
||||
from cuddlefish.prefs import DEFAULT_FENNEC_PREFS
|
||||
from cuddlefish.prefs import DEFAULT_NO_CONNECTIONS_PREFS
|
||||
|
||||
# Used to remove noise from ADB output
|
||||
CLEANUP_ADB = re.compile(r'^(I|E)/(stdout|stderr|GeckoConsole)\s*\(\s*\d+\):\s*(.*)$')
|
||||
@ -30,12 +31,12 @@ PARSEABLE_TEST_NAME = re.compile(r'TEST-START \| ([^\n]+)\n')
|
||||
# The purpose of this timeout is to recover from infinite loops. It should be
|
||||
# longer than the amount of time any test run takes, including those on slow
|
||||
# machines running slow (debug) versions of Firefox.
|
||||
RUN_TIMEOUT = 1.5 * 60 * 60 # 1.5 Hour
|
||||
RUN_TIMEOUT = 5400 #1.5 hours (1.5 * 60 * 60 sec)
|
||||
|
||||
# Maximum time we'll wait for tests to emit output, in seconds.
|
||||
# The purpose of this timeout is to recover from hangs. It should be longer
|
||||
# than the amount of time any test takes to report results.
|
||||
OUTPUT_TIMEOUT = 60 * 5 # five minutes
|
||||
OUTPUT_TIMEOUT = 300 #five minutes (60 * 5 sec)
|
||||
|
||||
def follow_file(filename):
|
||||
"""
|
||||
@ -419,7 +420,8 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
overload_modules=False,
|
||||
bundle_sdk=True,
|
||||
pkgdir="",
|
||||
enable_e10s=False):
|
||||
enable_e10s=False,
|
||||
no_connections=False):
|
||||
if binary:
|
||||
binary = os.path.expanduser(binary)
|
||||
|
||||
@ -431,6 +433,9 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
cmdargs = []
|
||||
preferences = dict(DEFAULT_COMMON_PREFS)
|
||||
|
||||
if no_connections:
|
||||
preferences.update(DEFAULT_NO_CONNECTIONS_PREFS)
|
||||
|
||||
if enable_e10s:
|
||||
preferences['browser.tabs.remote.autostart'] = True
|
||||
|
||||
@ -507,6 +512,8 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
|
||||
|
||||
env = {}
|
||||
env.update(os.environ)
|
||||
if no_connections:
|
||||
env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
|
||||
env['MOZ_NO_REMOTE'] = '1'
|
||||
env['XPCOM_DEBUG_BREAK'] = 'stack'
|
||||
env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
|
||||
|
@ -33,17 +33,15 @@ def build_xpi(template_root_dir, manifest, xpi_path,
|
||||
|
||||
zf = zipfile.ZipFile(xpi_path, "w", zipfile.ZIP_DEFLATED)
|
||||
|
||||
open('.install.rdf', 'w').write(str(manifest))
|
||||
zf.write('.install.rdf', 'install.rdf')
|
||||
os.remove('.install.rdf')
|
||||
zf.writestr('install.rdf', str(manifest))
|
||||
|
||||
# Handle add-on icon
|
||||
if 'icon' in harness_options:
|
||||
zf.write(str(harness_options['icon']), 'icon.png')
|
||||
zf.write(os.path.join(str(harness_options['icon'])), 'icon.png')
|
||||
del harness_options['icon']
|
||||
|
||||
if 'icon64' in harness_options:
|
||||
zf.write(str(harness_options['icon64']), 'icon64.png')
|
||||
zf.write(os.path.join(str(harness_options['icon64'])), 'icon64.png')
|
||||
del harness_options['icon64']
|
||||
|
||||
# chrome.manifest
|
||||
@ -161,9 +159,7 @@ def build_xpi(template_root_dir, manifest, xpi_path,
|
||||
harness_options[key] = value
|
||||
|
||||
# Write harness-options.json
|
||||
open('.options.json', 'w').write(json.dumps(harness_options, indent=1,
|
||||
sort_keys=True))
|
||||
zf.write('.options.json', 'harness-options.json')
|
||||
os.remove('.options.json')
|
||||
zf.writestr('harness-options.json', json.dumps(harness_options, indent=1,
|
||||
sort_keys=True))
|
||||
|
||||
zf.close()
|
||||
|
@ -126,7 +126,7 @@ class Popen(subprocess.Popen):
|
||||
|
||||
if not isinstance(args, types.StringTypes):
|
||||
args = subprocess.list2cmdline(args)
|
||||
|
||||
|
||||
# Always or in the create new process group
|
||||
creationflags |= winprocess.CREATE_NEW_PROCESS_GROUP
|
||||
|
||||
@ -135,7 +135,7 @@ class Popen(subprocess.Popen):
|
||||
|
||||
if None not in (p2cread, c2pwrite, errwrite):
|
||||
startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
|
||||
|
||||
|
||||
startupinfo.hStdInput = int(p2cread)
|
||||
startupinfo.hStdOutput = int(c2pwrite)
|
||||
startupinfo.hStdError = int(errwrite)
|
||||
@ -172,7 +172,7 @@ class Popen(subprocess.Popen):
|
||||
|
||||
if canCreateJob:
|
||||
# We create a new job for this process, so that we can kill
|
||||
# the process and any sub-processes
|
||||
# the process and any sub-processes
|
||||
self._job = winprocess.CreateJobObject()
|
||||
winprocess.AssignProcessToJobObject(self._job, int(hp))
|
||||
else:
|
||||
@ -198,7 +198,7 @@ class Popen(subprocess.Popen):
|
||||
winprocess.TerminateJobObject(self._job, 127)
|
||||
else:
|
||||
winprocess.TerminateProcess(self._handle, 127)
|
||||
self.returncode = 127
|
||||
self.returncode = 127
|
||||
else:
|
||||
if group:
|
||||
try:
|
||||
@ -223,7 +223,7 @@ class Popen(subprocess.Popen):
|
||||
if timeout is None:
|
||||
timeout = -1
|
||||
rc = winprocess.WaitForSingleObject(self._handle, timeout)
|
||||
|
||||
|
||||
if (rc == winprocess.WAIT_OBJECT_0 or
|
||||
rc == winprocess.WAIT_ABANDONED or
|
||||
rc == winprocess.WAIT_FAILED):
|
||||
@ -232,11 +232,11 @@ class Popen(subprocess.Popen):
|
||||
# and supply a little time before we start shooting processes
|
||||
# with an M-16.
|
||||
|
||||
# Returns 1 if running, 0 if not, -1 if timed out
|
||||
# Returns 1 if running, 0 if not, -1 if timed out
|
||||
def check():
|
||||
now = datetime.datetime.now()
|
||||
diff = now - starttime
|
||||
if (diff.seconds * 1000 * 1000 + diff.microseconds) < (timeout * 1000):
|
||||
if (diff.seconds * 1000000 + diff.microseconds) < (timeout * 1000): # (1000*1000)
|
||||
if self._job:
|
||||
if (winprocess.QueryInformationJobObject(self._job, 8)['BasicInfo']['ActiveProcesses'] > 0):
|
||||
# Job Object is still containing active processes
|
||||
@ -314,14 +314,14 @@ class Popen(subprocess.Popen):
|
||||
now = datetime.datetime.now()
|
||||
diff = now - starttime
|
||||
return self.returncode
|
||||
|
||||
|
||||
return self.returncode
|
||||
# We get random maxint errors from subprocesses __del__
|
||||
__del__ = lambda self: None
|
||||
|
||||
def setpgid_preexec_fn():
|
||||
os.setpgid(0, 0)
|
||||
|
||||
|
||||
def runCommand(cmd, **kwargs):
|
||||
if sys.platform != "win32":
|
||||
return Popen(cmd, preexec_fn=setpgid_preexec_fn, **kwargs)
|
||||
|
@ -4,16 +4,47 @@
|
||||
'use strict';
|
||||
|
||||
const { merge } = require('sdk/util/object');
|
||||
const { get } = require('sdk/preferences/service');
|
||||
const { version, platform } = require('sdk/system');
|
||||
const { getMostRecentBrowserWindow, isBrowser } = require('sdk/window/utils');
|
||||
const { WindowTracker } = require('sdk/deprecated/window-utils');
|
||||
const { close, focus } = require('sdk/window/helpers');
|
||||
const { when } = require('sdk/system/unload');
|
||||
|
||||
merge(module.exports, require('./test-tab'));
|
||||
function replaceWindow(remote) {
|
||||
let next = null;
|
||||
let old = getMostRecentBrowserWindow();
|
||||
let promise = new Promise(resolve => {
|
||||
let tracker = WindowTracker({
|
||||
onTrack: window => {
|
||||
if (window !== next)
|
||||
return;
|
||||
resolve(window);
|
||||
tracker.unload();
|
||||
}
|
||||
});
|
||||
})
|
||||
next = old.OpenBrowserWindow({ remote });
|
||||
return promise.then(focus).then(_ => close(old));
|
||||
}
|
||||
|
||||
// merge(module.exports, require('./test-tab'));
|
||||
merge(module.exports, require('./test-tab-events'));
|
||||
merge(module.exports, require('./test-tab-observer'));
|
||||
merge(module.exports, require('./test-tab-utils'));
|
||||
|
||||
// e10s tests should not ride the train to aurora
|
||||
if (get('app.update.channel') !== 'nightly') {
|
||||
// run e10s tests only on builds from trunk, fx-team, Nightly..
|
||||
if (!version.endsWith('a1')) {
|
||||
module.exports = {};
|
||||
}
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
// bug 1054482 - e10s test addons time out on linux
|
||||
if (platform === 'linux') {
|
||||
module.exports = {};
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
}
|
||||
else {
|
||||
replaceWindow(true).then(_ =>
|
||||
require('sdk/test/runner').runTestsFromModule(module));
|
||||
|
||||
when(_ => replaceWindow(false));
|
||||
}
|
||||
|
@ -5,6 +5,5 @@
|
||||
"description": "run tab tests in e10s mode",
|
||||
"author": "Tomislav Jovanovic",
|
||||
"license": "MPL 2.0",
|
||||
"version": "0.1",
|
||||
"e10s": true
|
||||
"version": "0.1"
|
||||
}
|
||||
|
@ -3,16 +3,14 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
'use strict';
|
||||
|
||||
const { get: getPref } = require('sdk/preferences/service');
|
||||
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
|
||||
const { getMostRecentBrowserWindow, isBrowser } = require('sdk/window/utils');
|
||||
const { promise: windowPromise, close, focus } = require('sdk/window/helpers');
|
||||
const { openTab, closeTab, getBrowserForTab } = require('sdk/tabs/utils');
|
||||
const { WindowTracker } = require('sdk/deprecated/window-utils');
|
||||
const { version, platform } = require('sdk/system');
|
||||
const { when } = require('sdk/system/unload');
|
||||
const tabs = require('sdk/tabs');
|
||||
|
||||
exports.testRemotePrefIsSet = function(assert) {
|
||||
assert.ok(getPref('browser.tabs.remote.autostart'),
|
||||
"Electrolysis remote tabs pref should be set");
|
||||
}
|
||||
|
||||
exports.testTabIsRemote = function(assert, done) {
|
||||
const url = 'data:text/html,test-tab-is-remote';
|
||||
let tab = openTab(getMostRecentBrowserWindow(), url);
|
||||
@ -28,9 +26,36 @@ exports.testTabIsRemote = function(assert, done) {
|
||||
mm.loadFrameScript('data:,sendAsyncMessage("7")', true);
|
||||
}
|
||||
|
||||
// e10s tests should not ride the train to aurora, beta
|
||||
if (getPref('app.update.channel') !== 'nightly') {
|
||||
// run e10s tests only on builds from trunk, fx-team, Nightly..
|
||||
if (!version.endsWith('a1')) {
|
||||
module.exports = {};
|
||||
}
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
function replaceWindow(remote) {
|
||||
let next = null;
|
||||
let old = getMostRecentBrowserWindow();
|
||||
let promise = new Promise(resolve => {
|
||||
let tracker = WindowTracker({
|
||||
onTrack: window => {
|
||||
if (window !== next)
|
||||
return;
|
||||
resolve(window);
|
||||
tracker.unload();
|
||||
}
|
||||
});
|
||||
})
|
||||
next = old.OpenBrowserWindow({ remote });
|
||||
return promise.then(focus).then(_ => close(old));
|
||||
}
|
||||
|
||||
// bug 1054482 - e10s test addons time out on linux
|
||||
if (platform === 'linux') {
|
||||
module.exports = {};
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
}
|
||||
else {
|
||||
replaceWindow(true).then(_ =>
|
||||
require('sdk/test/runner').runTestsFromModule(module));
|
||||
|
||||
when(_ => replaceWindow(false));
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
{
|
||||
"name": "e10s-flag",
|
||||
"title": "e10s-flag",
|
||||
"name": "e10s",
|
||||
"title": "e10s",
|
||||
"id": "jid1-DYaXFHAPlHwbgw",
|
||||
"description": "a basic e10s test add-on",
|
||||
"author": "Tomislav Jovanovic",
|
||||
"license": "MPL 2.0",
|
||||
"version": "0.1",
|
||||
"e10s": true
|
||||
"version": "0.1"
|
||||
}
|
||||
|
@ -132,4 +132,7 @@ function closeConnection() {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// bug 1042976 - temporary test disable
|
||||
module.exports = {};
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
|
@ -127,4 +127,7 @@ function closeConnection() {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// bug 1042976 - temporary test disable
|
||||
module.exports = {};
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule(module);
|
||||
|
@ -25,9 +25,7 @@ const isOSX10_6 = (() => {
|
||||
return vString && /darwin/.test(platform()) && /10\.6/.test(vString);
|
||||
})();
|
||||
|
||||
const {
|
||||
search
|
||||
} = require('sdk/places/history');
|
||||
const { search } = require('sdk/places/history');
|
||||
const {
|
||||
invalidResolve, invalidReject, createTree, createBookmark,
|
||||
compareWithHost, addVisits, resetPlaces, createBookmarkItem,
|
||||
@ -37,21 +35,20 @@ const { save, MENU, UNSORTED } = require('sdk/places/bookmarks');
|
||||
const { promisedEmitter } = require('sdk/places/utils');
|
||||
|
||||
exports['test bookmark-item-added'] = function (assert, done) {
|
||||
function handler ({type, data}) {
|
||||
events.on('data', function handler ({type, data}) {
|
||||
if (type !== 'bookmark-item-added') return;
|
||||
if (data.title !== 'bookmark-added-title') return;
|
||||
events.off('data', handler);
|
||||
|
||||
assert.equal(type, 'bookmark-item-added', 'correct type in bookmark-added event');
|
||||
assert.equal(data.type, 'bookmark', 'correct data in bookmark-added event');
|
||||
assert.ok(data.id != null, 'correct data in bookmark-added event');
|
||||
assert.ok(data.parentId != null, 'correct data in bookmark-added event');
|
||||
assert.ok(data.index != null, 'correct data in bookmark-added event');
|
||||
assert.equal(data.url, 'http://moz.com/', 'correct data in bookmark-added event');
|
||||
assert.ok(data.dateAdded != null, 'correct data in bookmark-added event');
|
||||
events.off('data', handler);
|
||||
assert.equal(data.type, 'bookmark', 'correct data.type in bookmark-added event');
|
||||
assert.ok(data.id != null, 'correct data.id in bookmark-added event');
|
||||
assert.notEqual(data.parentId, null, 'correct data.parentId in bookmark-added event');
|
||||
assert.ok(data.index >= 0, 'correct data.index in bookmark-added event');
|
||||
assert.equal(data.url, 'http://moz.com/', 'correct data.url in bookmark-added event');
|
||||
assert.notEqual(data.dateAdded, null, 'correct data.dateAdded in bookmark-added event');
|
||||
done();
|
||||
}
|
||||
events.on('data', handler);
|
||||
});
|
||||
createBookmark({ title: 'bookmark-added-title' });
|
||||
};
|
||||
|
||||
@ -62,7 +59,7 @@ exports['test bookmark-item-changed'] = function (assert, done) {
|
||||
// Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only
|
||||
// in debug builds) to prevent intermittent failures
|
||||
if (isOSX10_6) {
|
||||
assert.ok(true, 'skipping test in OSX 10.6');
|
||||
assert.pass('skipping test in OSX 10.6');
|
||||
return done();
|
||||
}
|
||||
|
||||
@ -94,7 +91,7 @@ exports['test bookmark-item-changed'] = function (assert, done) {
|
||||
id = item.id;
|
||||
item.title = 'bookmark-changed-title-2';
|
||||
return saveP(item);
|
||||
}).then(complete);
|
||||
}).then(complete).catch(assert.fail);
|
||||
};
|
||||
|
||||
exports['test bookmark-item-moved'] = function (assert, done) {
|
||||
@ -105,7 +102,7 @@ exports['test bookmark-item-moved'] = function (assert, done) {
|
||||
// Due to bug 969616 and bug 971964, disabling tests in 10.6 (happens only
|
||||
// in debug builds) to prevent intermittent failures
|
||||
if (isOSX10_6) {
|
||||
assert.ok(true, 'skipping test in OSX 10.6');
|
||||
assert.ok(true, 'skipping test in OSX 10.6');
|
||||
return done();
|
||||
}
|
||||
|
||||
@ -138,7 +135,7 @@ exports['test bookmark-item-moved'] = function (assert, done) {
|
||||
previousParentId = bmsrv.getFolderIdForItem(id);
|
||||
item.group = MENU;
|
||||
return saveP(item);
|
||||
}).then(complete);
|
||||
}).then(complete).catch(assert.fail);
|
||||
};
|
||||
|
||||
exports['test bookmark-item-removed'] = function (assert, done) {
|
||||
@ -171,7 +168,7 @@ exports['test bookmark-item-removed'] = function (assert, done) {
|
||||
id = item.id;
|
||||
item.remove = true;
|
||||
return saveP(item);
|
||||
}).then(complete);
|
||||
}).then(complete).catch(assert.fail);
|
||||
};
|
||||
|
||||
exports['test bookmark-item-visited'] = function (assert, done) {
|
||||
@ -205,7 +202,7 @@ exports['test bookmark-item-visited'] = function (assert, done) {
|
||||
}).then(item => {
|
||||
id = item.id;
|
||||
return addVisits('http://bookmark-item-visited.com/');
|
||||
}).then(complete);
|
||||
}).then(complete).catch(assert.fail);
|
||||
};
|
||||
|
||||
exports['test history-start-batch, history-end-batch, history-start-clear'] = function (assert, done) {
|
||||
|
@ -19,6 +19,7 @@ exports.promise = require('sdk/core/promise');
|
||||
|
||||
exports.localJSM = require('./dir/test.jsm');
|
||||
exports.promisejsm = require('modules/Promise.jsm').Promise;
|
||||
exports.require = require;
|
||||
|
||||
let math = require('test-math');
|
||||
exports.areModulesCached = (math === exports.math);
|
||||
|
1
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/index.js
generated
vendored
Normal file
1
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = "assets!"
|
6
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/package.json
generated
vendored
Normal file
6
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/package.json
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "test-assets",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
3
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/styles.css
generated
vendored
Normal file
3
addon-sdk/source/test/fixtures/native-addon-test/node_modules/test-assets/styles.css
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
body {
|
||||
background-color: #ff0077;
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
"test-math": "*",
|
||||
"test-custom-main": "*",
|
||||
"test-custom-main-relative": "*",
|
||||
"test-default-main": "*"
|
||||
"test-default-main": "*",
|
||||
"test-assets": "*"
|
||||
}
|
||||
}
|
||||
|
@ -366,4 +366,12 @@ exports['test shared globals'] = function(assert) {
|
||||
unload(loader);
|
||||
}
|
||||
|
||||
exports["test require#resolve"] = function(assert) {
|
||||
let root = require.resolve("sdk/tabs").replace(/commonjs\.path\/(.*)$/, "") + "commonjs.path/";
|
||||
assert.ok(/^resource:\/\/extensions\.modules\.[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}-at-jetpack\.commonjs\.path\/$/.test(root), "correct resolution root");
|
||||
|
||||
assert.equal(root + "sdk/tabs.js", require.resolve("sdk/tabs"), "correct resolution of sdk module");
|
||||
assert.equal(root + "toolkit/loader.js", require.resolve("toolkit/loader"), "correct resolution of sdk module");
|
||||
};
|
||||
|
||||
require('test').run(exports);
|
||||
|
@ -85,13 +85,13 @@ exports['test JSM loading'] = function (assert, done) {
|
||||
manifest: manifest,
|
||||
isNative: true
|
||||
});
|
||||
|
||||
|
||||
let program = main(loader);
|
||||
assert.ok(program.localJSMCached, 'local relative JSMs are cached');
|
||||
assert.ok(program.isCachedJSAbsolute , 'absolute resource:// js are cached');
|
||||
assert.ok(program.isCachedPath, 'JSMs resolved in paths are cached');
|
||||
assert.ok(program.isCachedAbsolute, 'absolute resource:// JSMs are cached');
|
||||
|
||||
|
||||
assert.ok(program.localJSM, 'able to load local relative JSMs');
|
||||
all([
|
||||
program.isLoadedPath(10),
|
||||
@ -152,6 +152,35 @@ exports['test native Loader without mappings'] = function (assert, done) {
|
||||
}).then(null, (reason) => console.error(reason));
|
||||
};
|
||||
|
||||
exports["test require#resolve with relative, dependencies"] = function(assert, done) {
|
||||
getJSON('/fixtures/native-addon-test/package.json').then(manifest => {
|
||||
let rootURI = root + '/fixtures/native-addon-test/';
|
||||
let loader = Loader({
|
||||
paths: makePaths(rootURI),
|
||||
rootURI: rootURI,
|
||||
manifest: manifest,
|
||||
isNative: true
|
||||
});
|
||||
|
||||
let program = main(loader);
|
||||
let fixtureRoot = program.require.resolve("./").replace(/native-addon-test\/(.*)/, "") + "native-addon-test/";
|
||||
|
||||
assert.ok(/^resource:\/\/[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}-at-jetpack\/addon-sdk\/tests\/fixtures\/native-addon-test\/$/.test(fixtureRoot),
|
||||
"correct resolution root");
|
||||
assert.equal(program.require.resolve("test-math"), fixtureRoot + "node_modules/test-math/index.js", "works with node_modules");
|
||||
assert.equal(program.require.resolve("./newmodule"), fixtureRoot + "newmodule/lib/file.js", "works with directory mains");
|
||||
assert.equal(program.require.resolve("./dir/a"), fixtureRoot + "dir/a.js", "works with normal relative module lookups");
|
||||
assert.equal(program.require.resolve("modules/Promise.jsm"), "resource://gre/modules/Promise.jsm", "works with path lookups");
|
||||
|
||||
// TODO bug 1050422, handle loading non JS/JSM file paths
|
||||
// assert.equal(program.require.resolve("test-assets/styles.css"), fixtureRoot + "node_modules/test-assets/styles.css",
|
||||
// "works with different file extension lookups in dependencies");
|
||||
|
||||
unload(loader);
|
||||
done();
|
||||
}).then(null, (reason) => console.error(reason));
|
||||
};
|
||||
|
||||
function testLoader (program, assert) {
|
||||
// Test 'main' entries
|
||||
// no relative custom main `lib/index.js`
|
||||
|
@ -12,6 +12,11 @@ const { isWindowPrivate } = require('sdk/window/utils');
|
||||
const { setTimeout } = require('sdk/timers');
|
||||
const { openWebpage } = require('./private-browsing/helper');
|
||||
const { isTabPBSupported, isWindowPBSupported } = require('sdk/private-browsing/utils');
|
||||
const { getTabContentWindow } = require('sdk/tabs/utils');
|
||||
const { attach, detach } = require('sdk/content/mod');
|
||||
const { Style } = require('sdk/stylesheet/style');
|
||||
const fixtures = require('./fixtures');
|
||||
const { viewFor } = require('sdk/view/core');
|
||||
const app = require("sdk/system/xul-app");
|
||||
|
||||
const URL = 'data:text/html;charset=utf-8,<html><head><title>#title#</title></head></html>';
|
||||
@ -47,7 +52,7 @@ exports.testTabRelativePath = function(assert, done) {
|
||||
let loader = Loader(module, null, null, {
|
||||
modules: {
|
||||
"sdk/self": merge({}, self, {
|
||||
data: merge({}, self.data, require("./fixtures"))
|
||||
data: merge({}, self.data, fixtures)
|
||||
})
|
||||
}
|
||||
});
|
||||
@ -550,4 +555,55 @@ exports.testOnPageShowEventDeclarative = function (assert, done) {
|
||||
});
|
||||
};
|
||||
|
||||
exports.testAttachStyleToTab = function(assert, done) {
|
||||
let style = Style({
|
||||
source: "div { height: 100px; }",
|
||||
uri: fixtures.url("include-file.css")
|
||||
});
|
||||
|
||||
tabs.open({
|
||||
url: "data:text/html;charset=utf-8,<div style='background: silver'>css test</div>",
|
||||
onReady: (tab) => {
|
||||
let xulTab = viewFor(tab);
|
||||
|
||||
attach(style, tab)
|
||||
|
||||
let { document } = getTabContentWindow(xulTab);
|
||||
let div = document.querySelector("div");
|
||||
|
||||
assert.equal(div.clientHeight, 100,
|
||||
"Style.source properly attached to tab");
|
||||
|
||||
assert.equal(div.offsetHeight, 120,
|
||||
"Style.uri properly attached to tab");
|
||||
|
||||
detach(style, tab);
|
||||
|
||||
assert.notEqual(div.clientHeight, 100,
|
||||
"Style.source properly detached from tab");
|
||||
|
||||
assert.notEqual(div.offsetHeight, 120,
|
||||
"Style.uri properly detached from tab");
|
||||
|
||||
attach(style, xulTab);
|
||||
|
||||
assert.equal(div.clientHeight, 100,
|
||||
"Style.source properly attached to xul tab");
|
||||
|
||||
assert.equal(div.offsetHeight, 120,
|
||||
"Style.uri properly attached to xul tab");
|
||||
|
||||
detach(style, tab);
|
||||
|
||||
assert.notEqual(div.clientHeight, 100,
|
||||
"Style.source properly detached from xul tab");
|
||||
|
||||
assert.notEqual(div.offsetHeight, 120,
|
||||
"Style.uri properly detached from xul tab");
|
||||
|
||||
tab.close(done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
require('sdk/test').run(exports);
|
||||
|
@ -22,6 +22,7 @@ const { URL } = require('sdk/url');
|
||||
const { once, off, emit } = require('sdk/event/core');
|
||||
const { defer, all } = require('sdk/core/promise');
|
||||
const { modelFor } = require('sdk/model/core');
|
||||
require('sdk/windows');
|
||||
|
||||
const { BUILTIN_SIDEBAR_MENUITEMS, isSidebarShowing,
|
||||
getSidebarMenuitems, getExtraSidebarMenuitems, makeID, simulateCommand,
|
||||
|
57
addon-sdk/source/test/test-unit-test-finder.js
Normal file
57
addon-sdk/source/test/test-unit-test-finder.js
Normal file
@ -0,0 +1,57 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { makeFilters } = require("sdk/deprecated/unit-test-finder");
|
||||
|
||||
const testFiles = [ "test-clipboard", "test-timers" ]
|
||||
const testMethods = [ "test set clipboard", "test setTimeout" ]
|
||||
|
||||
exports["test makeFilters no options"] = (assert) => {
|
||||
let { fileFilter, testFilter } = makeFilters();
|
||||
testFiles.forEach(f => assert.ok(fileFilter(f), "using no options on filename " + f + " works"));
|
||||
testMethods.forEach(m => assert.ok(testFilter(m), "using no options on method name " + m + " works"));
|
||||
}
|
||||
|
||||
exports["test makeFilters no filter"] = (assert) => {
|
||||
let { fileFilter, testFilter } = makeFilters({});
|
||||
testFiles.forEach(f => assert.ok(fileFilter(f), "using no options on filename " + f + " works"));
|
||||
testMethods.forEach(m => assert.ok(testFilter(m), "using no options on method name " + m + " works"));
|
||||
}
|
||||
|
||||
exports["test makeFilters no method filter"] = (assert) => {
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: "i" });
|
||||
testFiles.forEach(f => assert.ok(fileFilter(f), "using filter 'i' on filename " + f + " works"));
|
||||
testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'i' on method name " + m + " works"));
|
||||
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: "i:" });
|
||||
testFiles.forEach(f => assert.ok(fileFilter(f), "using filter 'i:' on filename " + f + " works"));
|
||||
testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'i:' on method name " + m + " works"));
|
||||
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: "z:" });
|
||||
testFiles.forEach(f => assert.ok(!fileFilter(f), "using filter 'z:' on filename " + f + " dnw"));
|
||||
testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'z:' on method name " + m + " works"));
|
||||
}
|
||||
|
||||
exports["test makeFilters no file filter"] = (assert) => {
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: ":i" });
|
||||
testFiles.forEach(f => assert.ok(fileFilter(f), "using filter ':i' on filename " + f + " works"));
|
||||
testMethods.forEach(m => assert.ok(testFilter(m), "using filter ':i' on method name " + m + " works"));
|
||||
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: ":z" });
|
||||
testFiles.forEach(f => assert.ok(fileFilter(f), "using filter ':z' on filename " + f + " works"));
|
||||
testMethods.forEach(m => assert.ok(!testFilter(m), "using filter ':z' on method name " + m + " dnw"));
|
||||
}
|
||||
|
||||
exports["test makeFilters both filters"] = (assert) => {
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: "i:i" });
|
||||
testFiles.forEach(f => assert.ok(fileFilter(f), "using filter 'i:i' on filename " + f + " works"));
|
||||
testMethods.forEach(m => assert.ok(testFilter(m), "using filter 'i:i' on method name " + m + " works"));
|
||||
|
||||
let { fileFilter, testFilter } = makeFilters({ filter: "z:z" });
|
||||
testFiles.forEach(f => assert.ok(!fileFilter(f), "using filter 'z:z' on filename " + f + " dnw"));
|
||||
testMethods.forEach(m => assert.ok(!testFilter(m), "using filter 'z:z' on method name " + m + " dnw"));
|
||||
}
|
||||
|
||||
require("sdk/test").run(exports);
|
@ -6,8 +6,8 @@
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 166407,
|
||||
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
|
||||
"size": 166485,
|
||||
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 166407,
|
||||
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
|
||||
"size": 166485,
|
||||
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
"filename": "clang.tar.bz2"
|
||||
},
|
||||
{
|
||||
"size": 166407,
|
||||
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
|
||||
"size": 166485,
|
||||
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1407886026000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1408662916000">
|
||||
<emItems>
|
||||
<emItem blockID="i454" id="sqlmoz@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
@ -227,6 +227,12 @@
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i698" id="{6b2a75c8-6e2e-4267-b955-43e25b54e575}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i498" id="hoverst@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
@ -1074,8 +1080,8 @@
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i474" id="{906000a4-88d9-4d52-b209-7a772970d91f}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
<emItem blockID="i700" id="2bbadf1f-a5af-499f-9642-9942fcdb7c76@f05a14cc-8842-4eee-be17-744677a917ed.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
@ -1184,8 +1190,8 @@
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i83" id="flash@adobee.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
<emItem blockID="i694" id="59D317DB041748fdB89B47E6F96058F3@jetpack">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
@ -1304,6 +1310,12 @@
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i83" id="flash@adobee.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i566" id="{77BEC163-D389-42c1-91A4-C758846296A5}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
@ -1633,6 +1645,14 @@
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i696" id="/^({fa95f577-07cb-4470-ac90-e843f5f83c52}|ffxtlbr@speedial\.com)$/">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
<pref>browser.startup.homepage</pref>
|
||||
<pref>browser.search.defaultenginename</pref>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i544" id="/^(93abedcf-8e3a-4d02-b761-d1441e437c09@243f129d-aee2-42c2-bcd1-48858e1c22fd\.com|9acfc440-ac2d-417a-a64c-f6f14653b712@09f9a966-9258-4b12-af32-da29bdcc28c5\.com|58ad0086-1cfb-48bb-8ad2-33a8905572bc@5715d2be-69b9-4930-8f7e-64bdeb961cfd\.com)$/">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
@ -1671,6 +1691,12 @@
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i474" id="{906000a4-88d9-4d52-b209-7a772970d91f}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
<prefs>
|
||||
</prefs>
|
||||
</emItem>
|
||||
<emItem blockID="i496" id="{ACAA314B-EEBA-48e4-AD47-84E31C44796C}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
|
@ -1518,12 +1518,12 @@ pref("browser.newtab.url", "about:newtab");
|
||||
// Activates preloading of the new tab url.
|
||||
pref("browser.newtab.preload", true);
|
||||
|
||||
// Remembers if the about:newtab intro has been shown
|
||||
pref("browser.newtabpage.introShown", false);
|
||||
|
||||
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
|
||||
pref("browser.newtabpage.enabled", true);
|
||||
|
||||
// Toggles the enhancement of history content of 'about:newtab'
|
||||
pref("browser.newtabpage.enhanced", false);
|
||||
|
||||
// number of rows of newtab grid
|
||||
pref("browser.newtabpage.rows", 3);
|
||||
|
||||
@ -1531,10 +1531,10 @@ pref("browser.newtabpage.rows", 3);
|
||||
pref("browser.newtabpage.columns", 5);
|
||||
|
||||
// directory tiles download URL
|
||||
pref("browser.newtabpage.directory.source", "chrome://global/content/directoryLinks.json");
|
||||
pref("browser.newtabpage.directory.source", "https://tiles.up.mozillalabs.com/v2/links/fetch");
|
||||
|
||||
// endpoint to send newtab click reports
|
||||
pref("browser.newtabpage.directory.reportClickEndPoint", "https://tiles.up.mozillalabs.com/ping/click");
|
||||
// endpoint to send newtab click and view pings
|
||||
pref("browser.newtabpage.directory.ping", "https://tiles.up.mozillalabs.com/v2/links/");
|
||||
|
||||
// Enable the DOM fullscreen API.
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
@ -2,6 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const SEARCH_ENGINES = {
|
||||
"Google": {
|
||||
// This is the "2x" image designed for OS X retina resolution, Windows at 192dpi, etc.;
|
||||
@ -269,13 +271,13 @@ function ensureSnippetsMapThen(aCallback)
|
||||
|
||||
// The cache has been filled up, create the snippets map.
|
||||
gSnippetsMap = Object.freeze({
|
||||
get: function (aKey) cache.get(aKey),
|
||||
get: (aKey) => cache.get(aKey),
|
||||
set: function (aKey, aValue) {
|
||||
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
|
||||
.objectStore(SNIPPETS_OBJECTSTORE_NAME).put(aValue, aKey);
|
||||
return cache.set(aKey, aValue);
|
||||
},
|
||||
has: function (aKey) cache.has(aKey),
|
||||
has: (aKey) => cache.has(aKey),
|
||||
delete: function (aKey) {
|
||||
db.transaction(SNIPPETS_OBJECTSTORE_NAME, "readwrite")
|
||||
.objectStore(SNIPPETS_OBJECTSTORE_NAME).delete(aKey);
|
||||
@ -286,7 +288,7 @@ function ensureSnippetsMapThen(aCallback)
|
||||
.objectStore(SNIPPETS_OBJECTSTORE_NAME).clear();
|
||||
return cache.clear();
|
||||
},
|
||||
get size() cache.size
|
||||
get size() { return cache.size; },
|
||||
});
|
||||
|
||||
setTimeout(invokeCallbacks, 0);
|
||||
|
@ -201,7 +201,8 @@
|
||||
command="Tools:DevAppMgr"/>
|
||||
<broadcaster id="devtoolsMenuBroadcaster_webide"
|
||||
label="&webide.label;"
|
||||
command="Tools:WebIDE"/>
|
||||
command="Tools:WebIDE"
|
||||
key="key_webide"/>
|
||||
<broadcaster id="devtoolsMenuBroadcaster_BrowserToolbox"
|
||||
label="&browserToolboxMenu.label;"
|
||||
command="Tools:BrowserToolbox"/>
|
||||
@ -292,7 +293,8 @@
|
||||
modifiers="accel,shift"
|
||||
#endif
|
||||
/>
|
||||
|
||||
<key id="key_webide" keycode="&webide.keycode;" command="Tools:WebIDE"
|
||||
modifiers="shift" keytext="&webide.keytext;"/>
|
||||
<key id="key_devToolboxMenuItem" keytext="&devToolboxMenuItem.keytext;"
|
||||
command="Tools:DevToolbox" key="&devToolboxMenuItem.keytext;"
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -698,6 +698,10 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#identity-request-notification");
|
||||
}
|
||||
|
||||
#bad-content-notification {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#bad-content-notification");
|
||||
}
|
||||
|
||||
#click-to-play-plugins-notification {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
|
||||
}
|
||||
|
@ -6485,50 +6485,46 @@ var gIdentityHandler = {
|
||||
this.setMode(this.IDENTITY_MODE_UNKNOWN);
|
||||
}
|
||||
|
||||
// Ensure the doorhanger is shown when mixed active content is blocked.
|
||||
if (state & nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT)
|
||||
this.showMixedContentDoorhanger();
|
||||
// Show the doorhanger when:
|
||||
// - mixed active content is blocked
|
||||
// - mixed active content is loaded (detected but not blocked)
|
||||
// - tracking content is blocked
|
||||
// - tracking content is not blocked
|
||||
if (state &
|
||||
(nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT |
|
||||
nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
|
||||
nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT |
|
||||
nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)) {
|
||||
this.showBadContentDoorhanger(state);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Display the Mixed Content Blocker doohanger, providing an option
|
||||
* to the user to override mixed content blocking
|
||||
*/
|
||||
showMixedContentDoorhanger : function() {
|
||||
// If we've already got an active notification, bail out to avoid showing it repeatedly.
|
||||
if (PopupNotifications.getNotification("mixed-content-blocked", gBrowser.selectedBrowser))
|
||||
showBadContentDoorhanger : function(state) {
|
||||
var currentNotification =
|
||||
PopupNotifications.getNotification("bad-content",
|
||||
gBrowser.selectedBrowser);
|
||||
|
||||
// Avoid showing the same notification (same state) repeatedly.
|
||||
if (currentNotification && currentNotification.options.state == state)
|
||||
return;
|
||||
|
||||
let brandBundle = document.getElementById("bundle_brand");
|
||||
let brandShortName = brandBundle.getString("brandShortName");
|
||||
let messageString = gNavigatorBundle.getFormattedString("mixedContentBlocked.message", [brandShortName]);
|
||||
let action = {
|
||||
label: gNavigatorBundle.getString("mixedContentBlocked.keepBlockingButton.label"),
|
||||
accessKey: gNavigatorBundle.getString("mixedContentBlocked.keepBlockingButton.accesskey"),
|
||||
callback: function() { /* NOP */ }
|
||||
};
|
||||
let secondaryActions = [
|
||||
{
|
||||
label: gNavigatorBundle.getString("mixedContentBlocked.unblock.label"),
|
||||
accessKey: gNavigatorBundle.getString("mixedContentBlocked.unblock.accesskey"),
|
||||
callback: function() {
|
||||
// Use telemetry to measure how often unblocking happens
|
||||
const kMIXED_CONTENT_UNBLOCK_EVENT = 2;
|
||||
let histogram =
|
||||
Services.telemetry.getHistogramById("MIXED_CONTENT_UNBLOCK_COUNTER");
|
||||
histogram.add(kMIXED_CONTENT_UNBLOCK_EVENT);
|
||||
// Reload the page with the content unblocked
|
||||
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
|
||||
}
|
||||
}
|
||||
];
|
||||
let options = {
|
||||
/* keep doorhanger collapsed */
|
||||
dismissed: true,
|
||||
learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "mixed-content",
|
||||
state: state
|
||||
};
|
||||
PopupNotifications.show(gBrowser.selectedBrowser, "mixed-content-blocked",
|
||||
messageString, "mixed-content-blocked-notification-icon",
|
||||
action, secondaryActions, options);
|
||||
|
||||
// default
|
||||
let iconState = "bad-content-blocked-notification-icon";
|
||||
|
||||
if (state &
|
||||
(Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
|
||||
Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)) {
|
||||
iconState = "bad-content-unblocked-notification-icon";
|
||||
}
|
||||
|
||||
PopupNotifications.show(gBrowser.selectedBrowser, "bad-content",
|
||||
"", iconState, null, null, options);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -712,7 +712,7 @@
|
||||
ontextreverted="return this.handleRevert();"
|
||||
pageproxystate="invalid"
|
||||
onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
|
||||
onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
|
||||
onblur="setTimeout(() => { document.getElementById('identity-box').style.MozUserFocus = ''; }, 0);">
|
||||
<box id="notification-popup-box" hidden="true" align="center">
|
||||
<image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
@ -724,7 +724,8 @@
|
||||
<image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="plugin-install-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="bad-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="bad-content-unblocked-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="webRTC-shareMicrophone-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
|
@ -11,6 +11,7 @@ let gCustomize = {
|
||||
"classic",
|
||||
"enhanced",
|
||||
"panel",
|
||||
"what",
|
||||
],
|
||||
|
||||
_nodes: {},
|
||||
@ -32,18 +33,33 @@ let gCustomize = {
|
||||
gAllPages.enabled = true;
|
||||
gAllPages.enhanced = true;
|
||||
});
|
||||
this._nodes.what.addEventListener("click", e => {
|
||||
gIntro.showPanel();
|
||||
});
|
||||
|
||||
this.updateSelected();
|
||||
},
|
||||
|
||||
showPanel: function() {
|
||||
let {button, panel} = this._nodes;
|
||||
let nodes = this._nodes;
|
||||
let {button, panel} = nodes;
|
||||
if (button.hasAttribute("active")) {
|
||||
return Promise.resolve(nodes);
|
||||
}
|
||||
|
||||
panel.openPopup(button);
|
||||
button.setAttribute("active", true);
|
||||
panel.addEventListener("popuphidden", function onHidden() {
|
||||
panel.removeEventListener("popuphidden", onHidden);
|
||||
button.removeAttribute("active");
|
||||
});
|
||||
|
||||
return new Promise(resolve => {
|
||||
panel.addEventListener("popupshown", function onShown() {
|
||||
panel.removeEventListener("popupshown", onShown);
|
||||
resolve(nodes);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
updateSelected: function() {
|
||||
|
54
browser/base/content/newtab/intro.js
Normal file
54
browser/base/content/newtab/intro.js
Normal file
@ -0,0 +1,54 @@
|
||||
#ifdef 0
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#endif
|
||||
|
||||
const PREF_INTRO_SHOWN = "browser.newtabpage.introShown";
|
||||
|
||||
let gIntro = {
|
||||
_introShown: Services.prefs.getBoolPref(PREF_INTRO_SHOWN),
|
||||
|
||||
_nodeIDSuffixes: [
|
||||
"panel",
|
||||
],
|
||||
|
||||
_nodes: {},
|
||||
|
||||
init: function() {
|
||||
for (let idSuffix of this._nodeIDSuffixes) {
|
||||
this._nodes[idSuffix] = document.getElementById("newtab-intro-" + idSuffix);
|
||||
}
|
||||
|
||||
this._nodes.panel.addEventListener("popupshowing", e => this._setUpPanel());
|
||||
},
|
||||
|
||||
showIfNecessary: function() {
|
||||
if (!this._introShown) {
|
||||
Services.prefs.setBoolPref(PREF_INTRO_SHOWN, true);
|
||||
this.showPanel();
|
||||
}
|
||||
},
|
||||
|
||||
showPanel: function() {
|
||||
// Open the customize menu first
|
||||
gCustomize.showPanel().then(nodes => {
|
||||
// Point the panel at the 'what' menu item
|
||||
this._nodes.panel.openPopup(nodes.what);
|
||||
});
|
||||
},
|
||||
|
||||
_setUpPanel: function() {
|
||||
// Build the panel if necessary
|
||||
if (this._nodes.panel.childNodes.length == 1) {
|
||||
['<a href="' + TILES_EXPLAIN_LINK + '">' + newTabString("learn.link") + "</a>",
|
||||
'<a href="' + TILES_PRIVACY_LINK + '">' + newTabString("privacy.link") + "</a>",
|
||||
'<input type="button" class="newtab-customize"/>',
|
||||
].forEach((arg, index) => {
|
||||
let paragraph = document.createElementNS(HTML_NAMESPACE, "p");
|
||||
this._nodes.panel.appendChild(paragraph);
|
||||
paragraph.innerHTML = newTabString("intro.paragraph" + (index + 1), [arg]);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
@ -49,6 +49,25 @@ input[type=button] {
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#newtab-intro-panel {
|
||||
color: #737373;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
margin-top: -32px;
|
||||
padding: 10px;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
#newtab-intro-panel h1 {
|
||||
color: #343f48;
|
||||
font-family: Open Sans, sans-serif;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
#newtab-intro-panel a {
|
||||
color: #4a90e2;
|
||||
}
|
||||
|
||||
/* MARGINS */
|
||||
#newtab-vertical-margin {
|
||||
display: -moz-box;
|
||||
@ -211,6 +230,7 @@ input[type=button] {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#newtab-intro-panel input,
|
||||
.sponsored-explain input {
|
||||
background-size: 20px;
|
||||
height: 20px;
|
||||
|
@ -51,6 +51,7 @@ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
const TILES_EXPLAIN_LINK = "https://support.mozilla.org/kb/how-do-sponsored-tiles-work";
|
||||
const TILES_PRIVACY_LINK = "https://www.mozilla.org/privacy/";
|
||||
|
||||
#include transformations.js
|
||||
#include page.js
|
||||
@ -66,6 +67,7 @@ const TILES_EXPLAIN_LINK = "https://support.mozilla.org/kb/how-do-sponsored-tile
|
||||
#include undo.js
|
||||
#include search.js
|
||||
#include customize.js
|
||||
#include intro.js
|
||||
|
||||
// Everything is loaded. Initialize the New Tab Page.
|
||||
gPage.init();
|
||||
|
@ -20,6 +20,11 @@
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&newtab.pageTitle;">
|
||||
|
||||
<xul:panel id="newtab-intro-panel" orient="vertical" type="arrow"
|
||||
noautohide="true" position="leftcenter topright">
|
||||
<h1>&newtab.intro.header;</h1>
|
||||
</xul:panel>
|
||||
|
||||
<xul:panel id="newtab-search-panel" orient="vertical" type="arrow"
|
||||
noautohide="true">
|
||||
<xul:hbox id="newtab-search-manage" class="newtab-search-panel-engine">
|
||||
@ -38,6 +43,9 @@
|
||||
<xul:hbox id="newtab-customize-blank" class="newtab-customize-panel-item">
|
||||
<xul:label>&newtab.customize.blank;</xul:label>
|
||||
</xul:hbox>
|
||||
<xul:hbox id="newtab-customize-what" class="newtab-customize-panel-item">
|
||||
<xul:label>&newtab.customize.what;</xul:label>
|
||||
</xul:hbox>
|
||||
</xul:panel>
|
||||
|
||||
<div id="newtab-scrollbox">
|
||||
|
@ -33,6 +33,9 @@ let gPage = {
|
||||
|
||||
// Initialize customize controls.
|
||||
gCustomize.init();
|
||||
|
||||
// Initialize intro panel.
|
||||
gIntro.init();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -94,7 +97,7 @@ let gPage = {
|
||||
if (document.hidden) {
|
||||
addEventListener("visibilitychange", this);
|
||||
} else {
|
||||
this.onPageFirstVisible();
|
||||
setTimeout(_ => this.onPageFirstVisible());
|
||||
}
|
||||
|
||||
// Initialize and render the grid.
|
||||
@ -174,42 +177,45 @@ let gPage = {
|
||||
// Record another page impression.
|
||||
Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
|
||||
|
||||
// Initialize type counting with the types we want to count
|
||||
let directoryCount = {};
|
||||
for (let type of DirectoryLinksProvider.linkTypes) {
|
||||
directoryCount[type] = 0;
|
||||
}
|
||||
|
||||
for (let site of gGrid.sites) {
|
||||
if (site) {
|
||||
site.captureIfMissing();
|
||||
}
|
||||
}
|
||||
|
||||
// Record which tile index a directory link was shown
|
||||
let {directoryIndex, type} = site.link;
|
||||
if (directoryIndex !== undefined) {
|
||||
let tileIndex = site.cell.index;
|
||||
// For telemetry, only handle the first 9 links in the first 9 cells
|
||||
if (directoryIndex < 9) {
|
||||
let shownId = "NEWTAB_PAGE_DIRECTORY_LINK" + directoryIndex + "_SHOWN";
|
||||
Services.telemetry.getHistogramById(shownId).add(Math.min(9, tileIndex));
|
||||
}
|
||||
}
|
||||
// Allow the document to reflow so the page has sizing info
|
||||
let i = 0;
|
||||
let checkSizing = _ => setTimeout(_ => {
|
||||
if (document.documentElement.clientWidth == 0) {
|
||||
checkSizing();
|
||||
}
|
||||
else {
|
||||
this.onPageFirstSized();
|
||||
}
|
||||
});
|
||||
checkSizing();
|
||||
},
|
||||
|
||||
// Aggregate tile impression counts into directory types
|
||||
if (type in directoryCount) {
|
||||
directoryCount[type]++;
|
||||
onPageFirstSized: function() {
|
||||
// Work backwards to find the first visible site from the end
|
||||
let {sites} = gGrid;
|
||||
let lastIndex = sites.length;
|
||||
while (lastIndex-- > 0) {
|
||||
let site = sites[lastIndex];
|
||||
if (site) {
|
||||
let {node} = site;
|
||||
let rect = node.getBoundingClientRect();
|
||||
let target = document.elementFromPoint(rect.x + rect.width / 2,
|
||||
rect.y + rect.height / 2);
|
||||
if (node.contains(target)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DirectoryLinksProvider.reportShownCount(directoryCount);
|
||||
// Record how many directory sites were shown, but place counts over the
|
||||
// default 9 in the same bucket
|
||||
for (let type of Object.keys(directoryCount)) {
|
||||
let count = directoryCount[type];
|
||||
let shownId = "NEWTAB_PAGE_DIRECTORY_" + type.toUpperCase() + "_SHOWN";
|
||||
let shownCount = Math.min(10, count);
|
||||
Services.telemetry.getHistogramById(shownId).add(shownCount);
|
||||
}
|
||||
DirectoryLinksProvider.reportSitesAction(gGrid.sites, "view", lastIndex);
|
||||
|
||||
// Show the panel now that anchors are sized
|
||||
gIntro.showIfNecessary();
|
||||
}
|
||||
};
|
||||
|
@ -172,6 +172,7 @@ Site.prototype = {
|
||||
|
||||
if (this.link.type != link.type) {
|
||||
this.node.setAttribute("type", "enhanced");
|
||||
this.enhancedId = link.directoryId;
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -287,15 +288,8 @@ Site.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// Specially count click actions for directory tiles
|
||||
let typeIndex = DirectoryLinksProvider.linkTypes.indexOf(this.link.type);
|
||||
if (action !== undefined && typeIndex != -1) {
|
||||
if (action == "click") {
|
||||
Services.telemetry.getHistogramById("NEWTAB_PAGE_DIRECTORY_TYPE_CLICKED")
|
||||
.add(typeIndex);
|
||||
}
|
||||
DirectoryLinksProvider.reportLinkAction(this.link, action, tileIndex, pinned);
|
||||
}
|
||||
// Report all link click actions
|
||||
DirectoryLinksProvider.reportSitesAction(gGrid.sites, action, tileIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -60,10 +60,3 @@
|
||||
<label id="pointerLock-cancel" value="&pointerLock.notification.message;"/>
|
||||
</popupnotificationcontent>
|
||||
</popupnotification>
|
||||
|
||||
<popupnotification id="mixed-content-blocked-notification" hidden="true">
|
||||
<popupnotificationcontent orient="vertical" align="start">
|
||||
<separator/>
|
||||
<description id="mixed-content-blocked-moreinfo">&mixedContentBlocked.moreinfo;</description>
|
||||
</popupnotificationcontent>
|
||||
</popupnotification>
|
||||
|
12
browser/base/content/test/general/benignPage.html
Normal file
12
browser/base/content/test/general/benignPage.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://not-tracking.example.com/"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -86,6 +86,8 @@ support-files =
|
||||
test_no_mcb_on_http_site_font2.html
|
||||
test_no_mcb_on_http_site_font2.css
|
||||
xul_tooltiptext.xhtml
|
||||
file_bug1045809_1.html
|
||||
file_bug1045809_2.html
|
||||
|
||||
[browser_URLBarSetURI.js]
|
||||
skip-if = (os == "linux" || os == "mac") && debug # bug 970052, bug 970053
|
||||
@ -411,6 +413,10 @@ skip-if = e10s # Bug ?????? - test needs to be updated for e10s (captures a stac
|
||||
[browser_tabs_isActive.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (tries to get/set attributes directly on content docshell)
|
||||
[browser_tabs_owner.js]
|
||||
[browser_trackingUI.js]
|
||||
support-files =
|
||||
trackingPage.html
|
||||
benignPage.html
|
||||
[browser_typeAheadFind.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 921935 - focusmanager issues with e10s (test calls waitForFocus)
|
||||
[browser_unloaddialogs.js]
|
||||
@ -459,3 +465,4 @@ skip-if = e10s # Bug 516755 - SessionStore disabled for e10s
|
||||
[browser_bug1025195_switchToTabHavingURI_ignoreFragment.js]
|
||||
[browser_addCertException.js]
|
||||
skip-if = e10s # Bug ?????? - test directly manipulates content (content.document.getElementById)
|
||||
[browser_bug1045809.js]
|
||||
|
77
browser/base/content/test/general/browser_bug1045809.js
Normal file
77
browser/base/content/test/general/browser_bug1045809.js
Normal file
@ -0,0 +1,77 @@
|
||||
// Test that the Mixed Content Doorhanger Action to re-enable protection works
|
||||
|
||||
const PREF_ACTIVE = "security.mixed_content.block_active_content";
|
||||
|
||||
var origBlockActive;
|
||||
|
||||
add_task(function* () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.setBoolPref(PREF_ACTIVE, origBlockActive);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Store original preferences so we can restore settings after testing
|
||||
origBlockActive = Services.prefs.getBoolPref(PREF_ACTIVE);
|
||||
|
||||
// Make sure mixed content blocking is on
|
||||
Services.prefs.setBoolPref(PREF_ACTIVE, true);
|
||||
|
||||
var url =
|
||||
"https://test1.example.com/browser/browser/base/content/test/general/" +
|
||||
"file_bug1045809_1.html";
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
// Test 1: mixed content must be blocked
|
||||
yield promiseTabLoadEvent(tab, url);
|
||||
test1(gBrowser.getBrowserForTab(tab));
|
||||
|
||||
yield promiseTabLoadEvent(tab);
|
||||
// Test 2: mixed content must NOT be blocked
|
||||
test2(gBrowser.getBrowserForTab(tab));
|
||||
|
||||
// Test 3: mixed content must be blocked again
|
||||
yield promiseTabLoadEvent(tab);
|
||||
test3(gBrowser.getBrowserForTab(tab));
|
||||
});
|
||||
|
||||
function test1(gTestBrowser) {
|
||||
var notification =
|
||||
PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
isnot(notification, null, "Mixed Content Doorhanger did appear in Test1");
|
||||
notification.reshow();
|
||||
isnot(PopupNotifications.panel.firstChild.isMixedContentBlocked, 0,
|
||||
"Mixed Content is being blocked in Test1");
|
||||
|
||||
var x = content.document.getElementsByTagName('iframe')[0].contentDocument.getElementById('mixedContentContainer');
|
||||
is(x, null, "Mixed Content is NOT to be found in Test1");
|
||||
|
||||
// Disable Mixed Content Protection for the page (and reload)
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
}
|
||||
|
||||
function test2(gTestBrowser) {
|
||||
var notification =
|
||||
PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
isnot(notification, null, "Mixed Content Doorhanger did appear in Test2");
|
||||
notification.reshow();
|
||||
is(PopupNotifications.panel.firstChild.isMixedContentBlocked, 0,
|
||||
"Mixed Content is NOT being blocked in Test2");
|
||||
|
||||
var x = content.document.getElementsByTagName('iframe')[0].contentDocument.getElementById('mixedContentContainer');
|
||||
isnot(x, null, "Mixed Content is to be found in Test2");
|
||||
|
||||
// Re-enable Mixed Content Protection for the page (and reload)
|
||||
PopupNotifications.panel.firstChild.enableMixedContentProtection();
|
||||
}
|
||||
|
||||
function test3(gTestBrowser) {
|
||||
var notification =
|
||||
PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
isnot(notification, null, "Mixed Content Doorhanger did appear in Test3");
|
||||
notification.reshow();
|
||||
isnot(PopupNotifications.panel.firstChild.isMixedContentBlocked, 0,
|
||||
"Mixed Content is being blocked in Test3");
|
||||
|
||||
var x = content.document.getElementsByTagName('iframe')[0].contentDocument.getElementById('mixedContentContainer');
|
||||
is(x, null, "Mixed Content is NOT to be found in Test3");
|
||||
}
|
@ -50,9 +50,11 @@ function test() {
|
||||
function MixedTest1A() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest1A, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest1B, true);
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger didn't appear");
|
||||
notification.secondaryActions[0].callback();
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger did appear");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked");
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
}
|
||||
function MixedTest1B() {
|
||||
waitForCondition(function() content.document.getElementById('p1').innerHTML == "hello", MixedTest1C, "Waited too long for mixed script to run in Test 1");
|
||||
@ -71,8 +73,8 @@ function MixedTest2() {
|
||||
}
|
||||
|
||||
function MixedTest2A() {
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(!notification, "Mixed Content Doorhanger appears for mixed display content!");
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(!notification, "Mixed Content Doorhanger did not appear for mixed display content!");
|
||||
MixedTest3();
|
||||
}
|
||||
|
||||
@ -86,9 +88,11 @@ function MixedTest3() {
|
||||
function MixedTest3A() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest3A, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest3B, true);
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger doesn't appear for test 3");
|
||||
notification.secondaryActions[0].callback();
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger did appear for test 3");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in test 3");
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
}
|
||||
function MixedTest3B() {
|
||||
waitForCondition(function() content.document.getElementById('p1').innerHTML == "hello", MixedTest3C, "Waited too long for mixed script to run in Test 3");
|
||||
@ -112,17 +116,22 @@ function MixedTest4() {
|
||||
function MixedTest4A() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest4A, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest4B, true);
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger doesn't appear for Test 4");
|
||||
notification.secondaryActions[0].callback();
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger did appear for Test 4");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 4");
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
}
|
||||
function MixedTest4B() {
|
||||
waitForCondition(function() content.document.location == gHttpTestRoot + "file_bug822367_4B.html", MixedTest4C, "Waited too long for mixed script to run in Test 4");
|
||||
}
|
||||
function MixedTest4C() {
|
||||
ok(content.document.location == gHttpTestRoot + "file_bug822367_4B.html", "Location didn't change in test 4");
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger doesn't appear after location change in Test 4");
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger did appear after location change in Test 4");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in test 4");
|
||||
notification.remove();
|
||||
waitForCondition(function() content.document.getElementById('p1').innerHTML == "", MixedTest4D, "Mixed script loaded in test 4 after location change!");
|
||||
}
|
||||
function MixedTest4D() {
|
||||
@ -140,9 +149,11 @@ function MixedTest5() {
|
||||
function MixedTest5A() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest5A, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest5B, true);
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger doesn't appear for Test 5");
|
||||
notification.secondaryActions[0].callback();
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger did appear for Test 5");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 5");
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
}
|
||||
function MixedTest5B() {
|
||||
waitForCondition(function() content.document.getElementById('p1').innerHTML == "hello", MixedTest5C, "Waited too long for mixed script to run in Test 5");
|
||||
@ -161,14 +172,16 @@ function MixedTest6() {
|
||||
}
|
||||
function MixedTest6A() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest6A, true);
|
||||
waitForCondition(function() PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser), MixedTest6B, "waited to long for doorhanger");
|
||||
waitForCondition(function() PopupNotifications.getNotification("bad-content", gTestBrowser), MixedTest6B, "waited too long for doorhanger");
|
||||
}
|
||||
|
||||
function MixedTest6B() {
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger doesn't appear for Test 6");
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger did appear for Test 6");
|
||||
gTestBrowser.addEventListener("load", MixedTest6C, true);
|
||||
notification.secondaryActions[0].callback();
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 6");
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
}
|
||||
|
||||
function MixedTest6C() {
|
||||
|
@ -7,7 +7,7 @@
|
||||
* - Doorhanger to disable protection appears - we disable it
|
||||
* - Load a new page from the same origin using document.location
|
||||
* - Doorhanger should not appear anymore!
|
||||
*
|
||||
*
|
||||
* 2. Navigate to the same domain via simulateclick for a link on the page
|
||||
* - Load a html page which has mixed content
|
||||
* - Doorhanger to disable protection appears - we disable it
|
||||
@ -49,12 +49,15 @@ function test1A() {
|
||||
// one once the page is loaded with mixed content blocker disabled
|
||||
gTestBrowser.removeEventListener("load", test1A, true);
|
||||
gTestBrowser.addEventListener("load", test1B, true);
|
||||
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger appeared in Test1A!");
|
||||
|
||||
// Disable Mixed Content Protection for the page
|
||||
notification.secondaryActions[0].callback();
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test1A!");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test1A!");
|
||||
|
||||
// Disable Mixed Content Protection for the page (and reload)
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
notification.remove();
|
||||
}
|
||||
|
||||
function test1B() {
|
||||
@ -80,10 +83,13 @@ function test1C() {
|
||||
function test1D() {
|
||||
gTestBrowser.removeEventListener("load", test1D, true);
|
||||
|
||||
// The Doorhanger should not appear, because our decision of disabling the
|
||||
// mixed content blocker is persistent.
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(!notification, "OK: Mixed Content Doorhanger did not appear again in Test1D!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be NOT true,
|
||||
// because our decision of disabling the mixed content blocker is persistent.
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test1D!");
|
||||
notification.reshow();
|
||||
ok(!PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked in Test1D!");
|
||||
notification.remove();
|
||||
|
||||
var actual = content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 1D");
|
||||
@ -105,12 +111,15 @@ function test2A() {
|
||||
// one once the page is loaded with mixed content blocker disabled
|
||||
gTestBrowser.removeEventListener("load", test2A, true);
|
||||
gTestBrowser.addEventListener("load", test2B, true);
|
||||
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger appeared in Test 2A!");
|
||||
|
||||
// Disable Mixed Content Protection for the page
|
||||
notification.secondaryActions[0].callback();
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 2A!");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 2A!");
|
||||
|
||||
// Disable Mixed Content Protection for the page (and reload)
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
notification.remove();
|
||||
}
|
||||
|
||||
function test2B() {
|
||||
@ -137,10 +146,13 @@ function test2C() {
|
||||
function test2D() {
|
||||
gTestBrowser.removeEventListener("load", test2D, true);
|
||||
|
||||
// The Doorhanger should not appear, because our decision of disabling the
|
||||
// mixed content blocker is persistent.
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(!notification, "OK: Mixed Content Doorhanger did not appear again in Test2D!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be NOT true,
|
||||
// because our decision of disabling the mixed content blocker is persistent.
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test2D!");
|
||||
notification.reshow();
|
||||
ok(!PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked");
|
||||
notification.remove();
|
||||
|
||||
var actual = content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 2D");
|
||||
@ -161,9 +173,12 @@ function test3A() {
|
||||
// Removing EventListener because we have to register a new
|
||||
// one once the page is loaded with mixed content blocker disabled
|
||||
gTestBrowser.removeEventListener("load", test3A, true);
|
||||
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger appeared in Test 3A!");
|
||||
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 3A!");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 3A");
|
||||
notification.remove();
|
||||
|
||||
// We are done with tests, clean up
|
||||
cleanUpAfterTests();
|
||||
|
@ -131,11 +131,14 @@ function checkPopUpNotification() {
|
||||
gTestWin.gBrowser.removeEventListener("load", checkPopUpNotification, true);
|
||||
gTestWin.gBrowser.addEventListener("load", reloadedTabAfterDisablingMCB, true);
|
||||
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger appeared in " + curTestName + "!");
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in " + curTestName + "!");
|
||||
notification.reshow();
|
||||
ok(gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in " + curTestName + "!");
|
||||
|
||||
// Disable Mixed Content Protection for the page
|
||||
notification.secondaryActions[0].callback();
|
||||
// Disable Mixed Content Protection for the page (and reload page)
|
||||
gTestWin.PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
notification.remove();
|
||||
}
|
||||
|
||||
function reloadedTabAfterDisablingMCB() {
|
||||
@ -177,10 +180,13 @@ function test1A() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test1A, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger should >> NOT << appear, because our decision of disabling the
|
||||
// mixed content blocker is persistent across tabs.
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(!notification, "OK: Mixed Content Doorhanger did not appear again in Test 1A!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true,
|
||||
// because our decision of disabling the mixed content blocker is persistent across tabs.
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 1A!");
|
||||
notification.reshow();
|
||||
ok(!gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked in Test 1A!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 1A");
|
||||
@ -203,10 +209,13 @@ function test1C() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test1C, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger should >> NOT << appear, because our decision of disabling the
|
||||
// mixed content blocker is persistent across tabs.
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(!notification, "OK: Mixed Content Doorhanger did not appear again in Test 1C!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true,
|
||||
// because our decision of disabling the mixed content blocker is persistent across tabs.
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 1C!");
|
||||
notification.reshow();
|
||||
ok(!gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked in Test 1C!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 1C");
|
||||
@ -235,10 +244,13 @@ function test2A() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test2A, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger >> SHOULD << appear, because our decision of disabling the
|
||||
// mixed content blocker should only persist if pages are from the same domain.
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear again in Test 2A!");
|
||||
// The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<,
|
||||
// because our decision of disabling the mixed content blocker should only persist if pages are from the same domain.
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 2A!");
|
||||
notification.reshow();
|
||||
ok(gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 2A!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker enabled", "OK: Blocked mixed script in Test 2A");
|
||||
@ -261,10 +273,13 @@ function test2C() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test2C, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger >> SHOULD << appear, because our decision of disabling the
|
||||
// mixed content blocker should only persist if pages are from the same domain.
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear again in Test 2C!");
|
||||
// The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<,
|
||||
// because our decision of disabling the mixed content blocker should only persist if pages are from the same domain.
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 2C!");
|
||||
notification.reshow();
|
||||
ok(gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 2C!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker enabled", "OK: Blocked mixed script in Test 2C");
|
||||
@ -299,9 +314,12 @@ function test3B() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test3B, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger should >> NOT << appear!
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(!notification, "OK: Mixed Content Doorhanger did appear again in Test 3B!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true!
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 3B!");
|
||||
notification.reshow();
|
||||
ok(!gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked in Test 3B!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 3B");
|
||||
@ -330,9 +348,12 @@ function test3E() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test3E, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger should >> NOT << appear!
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(!notification, "OK: Mixed Content Doorhanger did appear again in Test 3E!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true!
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 3E!");
|
||||
notification.reshow();
|
||||
ok(!gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked in Test 3E!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 3E");
|
||||
@ -367,9 +388,12 @@ function test4B() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test4B, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger >> SHOULD << appear!
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear again in Test 4B!");
|
||||
// The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 4B!");
|
||||
notification.reshow();
|
||||
ok(gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 4B!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker enabled", "OK: Blocked mixed script in Test 4B");
|
||||
@ -398,9 +422,12 @@ function test4E() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test4E, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger >> SHOULD << appear!
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear again in Test 4E!");
|
||||
// The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 4E!");
|
||||
notification.reshow();
|
||||
ok(gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 4E!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker enabled", "OK: Blocked mixed script in Test 4E");
|
||||
@ -430,10 +457,13 @@ function test5A() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test5A, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger should >> NOT << appear
|
||||
// Currently it >> APPEARS << - see follow up bug 914860
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
todo(!notification, "OK: Mixed Content Doorhanger did not appear again in Test 5A!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true
|
||||
// Currently it is >> TRUE << - see follow up bug 914860
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 5A!");
|
||||
notification.reshow();
|
||||
todo(!gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked in Test 5A!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
todo_is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 5A!");
|
||||
@ -457,10 +487,13 @@ function test5C() {
|
||||
// move the tab again
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger should >> NOT << appear
|
||||
// Currently it >> APPEARS << - see follow up bug 914860
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
todo(!notification, "OK: Mixed Content Doorhanger did not appear again in Test 5C!");
|
||||
// The Doorhanger should appear but isMixedContentBlocked should be >> NOT << true
|
||||
// Currently it is >> TRUE << - see follow up bug 914860
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 5C!");
|
||||
notification.reshow();
|
||||
todo(!gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is NOT being blocked in Test 5C!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
todo_is(actual, "Mixed Content Blocker disabled", "OK: Executed mixed script in Test 5C!");
|
||||
@ -490,9 +523,12 @@ function test6A() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test6A, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger >> SHOULD << appear!
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear again in Test 6A!");
|
||||
// The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 6A!");
|
||||
notification.reshow();
|
||||
ok(gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 6A!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker enabled", "OK: Blocked mixed script in Test 6A");
|
||||
@ -515,9 +551,12 @@ function test6C() {
|
||||
gTestWin.gBrowser.removeEventListener("load", test6C, true);
|
||||
gTestWin.gBrowser.selectTabAtIndex(2);
|
||||
|
||||
// The Doorhanger >> SHOULD << appear!
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear again in Test 6C!");
|
||||
// The Doorhanger should appear and isMixedContentBlocked should be >> TRUE <<
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestWin.gBrowser.selectedBrowser);
|
||||
ok(notification, "OK: Mixed Content Doorhanger did appear in Test 6C!");
|
||||
notification.reshow();
|
||||
ok(gTestWin.PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked in Test 6C!");
|
||||
notification.remove();
|
||||
|
||||
var actual = gTestWin.content.document.getElementById('mctestdiv').innerHTML;
|
||||
is(actual, "Mixed Content Blocker enabled", "OK: Blocked mixed script in Test 6C");
|
||||
|
@ -185,7 +185,7 @@ function closeStream(aAlreadyClosed) {
|
||||
if (!aAlreadyClosed)
|
||||
expectObserverCalled("recording-window-ended");
|
||||
|
||||
assertWebRTCIndicatorStatus(false);
|
||||
assertWebRTCIndicatorStatus(null);
|
||||
}
|
||||
|
||||
function checkDeviceSelectors(aAudio, aVideo) {
|
||||
@ -202,10 +202,10 @@ function checkDeviceSelectors(aAudio, aVideo) {
|
||||
ok(cameraSelector.hidden, "camera selector hidden");
|
||||
}
|
||||
|
||||
function checkSharingUI() {
|
||||
function checkSharingUI(aExpected) {
|
||||
yield promisePopupNotification("webRTC-sharingDevices");
|
||||
|
||||
assertWebRTCIndicatorStatus(true);
|
||||
assertWebRTCIndicatorStatus(aExpected);
|
||||
}
|
||||
|
||||
function checkNotSharing() {
|
||||
@ -214,7 +214,7 @@ function checkNotSharing() {
|
||||
ok(!PopupNotifications.getNotification("webRTC-sharingDevices"),
|
||||
"no webRTC-sharingDevices popup notification");
|
||||
|
||||
assertWebRTCIndicatorStatus(false);
|
||||
assertWebRTCIndicatorStatus(null);
|
||||
}
|
||||
|
||||
let gTests = [
|
||||
@ -242,7 +242,7 @@ let gTests = [
|
||||
is(getMediaCaptureState(), "CameraAndMicrophone",
|
||||
"expected camera and microphone to be shared");
|
||||
|
||||
yield checkSharingUI();
|
||||
yield checkSharingUI({audio: true, video: true});
|
||||
yield closeStream();
|
||||
}
|
||||
},
|
||||
@ -269,7 +269,7 @@ let gTests = [
|
||||
expectObserverCalled("recording-device-events");
|
||||
is(getMediaCaptureState(), "Microphone", "expected microphone to be shared");
|
||||
|
||||
yield checkSharingUI();
|
||||
yield checkSharingUI({audio: true});
|
||||
yield closeStream();
|
||||
}
|
||||
},
|
||||
@ -296,7 +296,7 @@ let gTests = [
|
||||
expectObserverCalled("recording-device-events");
|
||||
is(getMediaCaptureState(), "Camera", "expected camera to be shared");
|
||||
|
||||
yield checkSharingUI();
|
||||
yield checkSharingUI({video: true});
|
||||
yield closeStream();
|
||||
}
|
||||
},
|
||||
@ -326,7 +326,7 @@ let gTests = [
|
||||
is(getMediaCaptureState(), "Microphone",
|
||||
"expected microphone to be shared");
|
||||
|
||||
yield checkSharingUI();
|
||||
yield checkSharingUI({audio: true});
|
||||
yield closeStream();
|
||||
}
|
||||
},
|
||||
@ -356,7 +356,7 @@ let gTests = [
|
||||
is(getMediaCaptureState(), "Camera",
|
||||
"expected microphone to be shared");
|
||||
|
||||
yield checkSharingUI();
|
||||
yield checkSharingUI({video: true});
|
||||
yield closeStream();
|
||||
}
|
||||
},
|
||||
@ -427,7 +427,7 @@ let gTests = [
|
||||
is(getMediaCaptureState(), "CameraAndMicrophone",
|
||||
"expected camera and microphone to be shared");
|
||||
|
||||
yield checkSharingUI();
|
||||
yield checkSharingUI({video: true, audio: true});
|
||||
|
||||
PopupNotifications.getNotification("webRTC-sharingDevices").reshow();
|
||||
activateSecondaryAction(kActionDeny);
|
||||
@ -692,7 +692,7 @@ let gTests = [
|
||||
expectObserverCalled("getUserMedia:request");
|
||||
expectObserverCalled("getUserMedia:response:allow");
|
||||
expectObserverCalled("recording-device-events");
|
||||
yield checkSharingUI();
|
||||
yield checkSharingUI({video: aRequestVideo, audio: aRequestAudio});
|
||||
|
||||
PopupNotifications.getNotification("webRTC-sharingDevices").reshow();
|
||||
let expectedIcon = "webRTC-sharingDevices";
|
||||
@ -746,6 +746,46 @@ let gTests = [
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "test showSharingDoorhanger",
|
||||
run: function checkShowSharingDoorhanger() {
|
||||
yield promisePopupNotificationShown("webRTC-shareDevices", () => {
|
||||
info("requesting devices");
|
||||
content.wrappedJSObject.requestDevice(false, true);
|
||||
});
|
||||
expectObserverCalled("getUserMedia:request");
|
||||
checkDeviceSelectors(false, true);
|
||||
|
||||
yield promiseMessage("ok", () => {
|
||||
PopupNotifications.panel.firstChild.button.click();
|
||||
});
|
||||
expectObserverCalled("getUserMedia:response:allow");
|
||||
expectObserverCalled("recording-device-events");
|
||||
is(getMediaCaptureState(), "Camera", "expected camera to be shared");
|
||||
|
||||
yield checkSharingUI({video: true});
|
||||
|
||||
yield promisePopupNotificationShown("webRTC-sharingDevices", () => {
|
||||
if ("nsISystemStatusBar" in Ci) {
|
||||
let activeStreams = gWebRTCUI.getActiveStreams(true, false, false);
|
||||
gWebRTCUI.showSharingDoorhanger(activeStreams[0], "Devices");
|
||||
}
|
||||
else {
|
||||
let win =
|
||||
Services.wm.getMostRecentWindow("Browser:WebRTCGlobalIndicator");
|
||||
let elt = win.document.getElementById("audioVideoButton");
|
||||
EventUtils.synthesizeMouseAtCenter(elt, {}, win);
|
||||
}
|
||||
});
|
||||
|
||||
PopupNotifications.panel.firstChild.button.click();
|
||||
ok(!PopupNotifications.isPanelOpen, "notification panel closed");
|
||||
expectNoObserverCalled();
|
||||
|
||||
yield closeStream();
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "'Always Allow' ignored and not shown on http pages",
|
||||
run: function checkNoAlwaysOnHttp() {
|
||||
|
@ -122,7 +122,7 @@ function closeStream(aAlreadyClosed) {
|
||||
if (!aAlreadyClosed)
|
||||
expectObserverCalled("recording-window-ended");
|
||||
|
||||
assertWebRTCIndicatorStatus(false);
|
||||
assertWebRTCIndicatorStatus(null);
|
||||
}
|
||||
|
||||
function loadPage(aUrl) {
|
||||
|
@ -37,11 +37,15 @@ function blockMixedContentTest()
|
||||
|
||||
function overrideMCB()
|
||||
{
|
||||
// test mixed content flags on load (reload)
|
||||
gTestBrowser.addEventListener("load", mixedContentOverrideTest, true);
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger didn't appear");
|
||||
// Click on the doorhanger to allow mixed content.
|
||||
notification.secondaryActions[0].callback(mixedContentOverrideTest);
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
ok(notification, "Mixed Content Doorhanger should appear");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked");
|
||||
// Click on the doorhanger to allow mixed content (and reload page)
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
notification.remove();
|
||||
}
|
||||
|
||||
function mixedContentOverrideTest()
|
||||
|
@ -23,6 +23,9 @@ const EXPECTED_REFLOWS = [
|
||||
"openUILinkIn@chrome://browser/content/utilityOverlay.js|" +
|
||||
"BrowserOpenTab@chrome://browser/content/browser.js|",
|
||||
|
||||
// unpreloaded newtab pages explicitly waits for reflows for sizing
|
||||
"gPage.onPageFirstVisible/checkSizing/<@chrome://browser/content/newtab/newTab.js|",
|
||||
|
||||
// accessing element.scrollPosition in _fillTrailingGap() flushes layout
|
||||
"get_scrollPosition@chrome://global/content/bindings/scrollbox.xml|" +
|
||||
"_fillTrailingGap@chrome://browser/content/tabbrowser.xml|" +
|
||||
@ -86,9 +89,10 @@ function test() {
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
let gOrigDirectorySource = Services.prefs.getCharPref(PREF_NEWTAB_DIRECTORYSOURCE);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(PREF_PRELOAD);
|
||||
Services.prefs.clearUserPref(PREF_NEWTAB_DIRECTORYSOURCE);
|
||||
Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, gOrigDirectorySource);
|
||||
return watchLinksChangeOnce();
|
||||
});
|
||||
|
||||
|
139
browser/base/content/test/general/browser_trackingUI.js
Normal file
139
browser/base/content/test/general/browser_trackingUI.js
Normal file
@ -0,0 +1,139 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Test that the Tracking Protection Doorhanger appears
|
||||
// and has the correct state when tracking content is blocked (Bug 1043801)
|
||||
|
||||
var PREF = "privacy.trackingprotection.enabled";
|
||||
var TABLE = "urlclassifier.trackingTable";
|
||||
|
||||
// Update tracking database
|
||||
function doUpdate() {
|
||||
// Add some URLs to the tracking database (to be blocked)
|
||||
var testData = "tracking.example.com/";
|
||||
var testUpdate =
|
||||
"n:1000\ni:test-track-simple\nad:1\n" +
|
||||
"a:524:32:" + testData.length + "\n" +
|
||||
testData;
|
||||
|
||||
var dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
|
||||
.getService(Ci.nsIUrlClassifierDBService);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
|
||||
var listener = {
|
||||
QueryInterface: function(iid)
|
||||
{
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsIUrlClassifierUpdateObserver))
|
||||
return this;
|
||||
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
updateUrlRequested: function(url) { },
|
||||
streamFinished: function(status) { },
|
||||
updateError: function(errorCode) {
|
||||
ok(false, "Couldn't update classifier.");
|
||||
deferred.resolve();
|
||||
},
|
||||
updateSuccess: function(requestedTimeout) {
|
||||
deferred.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
dbService.beginUpdate(listener, "test-track-simple", "");
|
||||
dbService.beginStream("", "");
|
||||
dbService.updateStream(testUpdate);
|
||||
dbService.finishStream();
|
||||
dbService.finishUpdate();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testBenignPage(gTestBrowser)
|
||||
{
|
||||
// Make sure the doorhanger does NOT appear
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was ON and tracking was NOT present");
|
||||
}
|
||||
|
||||
function testTrackingPage(gTestBrowser)
|
||||
{
|
||||
// Make sure the doorhanger appears
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
isnot(notification, null, "Tracking Content Doorhanger did appear when protection was ON and tracking was present");
|
||||
notification.reshow();
|
||||
// Make sure the state of the doorhanger includes blocking tracking elements
|
||||
isnot(PopupNotifications.panel.firstChild.isTrackingContentBlocked, 0,
|
||||
"Tracking Content is being blocked");
|
||||
|
||||
// Disable Tracking Content Protection for the page (which reloads the page)
|
||||
PopupNotifications.panel.firstChild.disableTrackingContentProtection();
|
||||
}
|
||||
|
||||
function testTrackingPageWhitelisted(gTestBrowser)
|
||||
{
|
||||
// Make sure the doorhanger appears
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
isnot(notification, null, "Tracking Content Doorhanger did appear when protection was ON and tracking was present but white-listed");
|
||||
notification.reshow();
|
||||
// Make sure the state of the doorhanger does NOT include blocking tracking elements
|
||||
is(PopupNotifications.panel.firstChild.isTrackingContentBlocked, 0,
|
||||
"Tracking Content is NOT being blocked");
|
||||
}
|
||||
|
||||
function testTrackingPageOFF(gTestBrowser)
|
||||
{
|
||||
// Make sure the doorhanger does NOT appear
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was OFF and tracking was present");
|
||||
}
|
||||
|
||||
function testBenignPageOFF(gTestBrowser)
|
||||
{
|
||||
// Make sure the doorhanger does NOT appear
|
||||
var notification = PopupNotifications.getNotification("bad-content", gTestBrowser);
|
||||
is(notification, null, "Tracking Content Doorhanger did NOT appear when protection was OFF and tracking was NOT present");
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF);
|
||||
Services.prefs.clearUserPref(TABLE);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
// Populate and use 'test-track-simple' for tracking protection lookups
|
||||
Services.prefs.setCharPref(TABLE, "test-track-simple");
|
||||
yield doUpdate();
|
||||
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
// Enable Tracking Protection
|
||||
Services.prefs.setBoolPref(PREF, true);
|
||||
|
||||
// Point tab to a test page NOT containing tracking elements
|
||||
yield promiseTabLoadEvent(tab, "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html");
|
||||
testBenignPage(gBrowser.getBrowserForTab(tab));
|
||||
|
||||
// Point tab to a test page containing tracking elements
|
||||
yield promiseTabLoadEvent(tab, "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html");
|
||||
testTrackingPage(gBrowser.getBrowserForTab(tab));
|
||||
|
||||
// Wait for tab to reload following tracking-protection page white-listing
|
||||
yield promiseTabLoadEvent(tab);
|
||||
// Tracking content must be white-listed (NOT blocked)
|
||||
testTrackingPageWhitelisted(gBrowser.getBrowserForTab(tab));
|
||||
|
||||
// Disable Tracking Protection
|
||||
Services.prefs.setBoolPref(PREF, false);
|
||||
|
||||
// Point tab to a test page containing tracking elements
|
||||
yield promiseTabLoadEvent(tab, "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html");
|
||||
testTrackingPageOFF(gBrowser.getBrowserForTab(tab));
|
||||
|
||||
// Point tab to a test page NOT containing tracking elements
|
||||
yield promiseTabLoadEvent(tab, "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html");
|
||||
testBenignPageOFF(gBrowser.getBrowserForTab(tab));
|
||||
});
|
7
browser/base/content/test/general/file_bug1045809_1.html
Normal file
7
browser/base/content/test/general/file_bug1045809_1.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://test1.example.com/browser/browser/base/content/test/general/file_bug1045809_2.html"></iframe>
|
||||
</body>
|
||||
</html>
|
7
browser/base/content/test/general/file_bug1045809_2.html
Normal file
7
browser/base/content/test/general/file_bug1045809_2.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mixedContentContainer">Mixed Content is here</div>
|
||||
</body>
|
||||
</html>
|
@ -573,12 +573,41 @@ function assertWebRTCIndicatorStatus(expected) {
|
||||
let ui = Cu.import("resource:///modules/webrtcUI.jsm", {}).webrtcUI;
|
||||
let expectedState = expected ? "visible" : "hidden";
|
||||
let msg = "WebRTC indicator " + expectedState;
|
||||
is(ui.showGlobalIndicator, expected, msg);
|
||||
is(ui.showGlobalIndicator, !!expected, msg);
|
||||
|
||||
let expectVideo = false, expectAudio = false, expectScreen = false;
|
||||
if (expected) {
|
||||
if (expected.video)
|
||||
expectVideo = true;
|
||||
if (expected.audio)
|
||||
expectAudio = true;
|
||||
if (expected.screen)
|
||||
expectScreen = true;
|
||||
}
|
||||
is(ui.showCameraIndicator, expectVideo, "camera global indicator as expected");
|
||||
is(ui.showMicrophoneIndicator, expectAudio, "microphone global indicator as expected");
|
||||
is(ui.showScreenSharingIndicator, expectScreen, "screen global indicator as expected");
|
||||
|
||||
let windows = Services.wm.getEnumerator("navigator:browser");
|
||||
while (windows.hasMoreElements()) {
|
||||
let win = windows.getNext();
|
||||
let menu = win.document.getElementById("tabSharingMenu");
|
||||
is(menu && !menu.hidden, expected, "WebRTC menu should be " + expectedState);
|
||||
is(menu && !menu.hidden, !!expected, "WebRTC menu should be " + expectedState);
|
||||
}
|
||||
|
||||
if (!("nsISystemStatusBar" in Ci)) {
|
||||
let indicator = Services.wm.getEnumerator("Browser:WebRTCGlobalIndicator");
|
||||
let hasWindow = indicator.hasMoreElements();
|
||||
is(hasWindow, !!expected, "popup " + msg);
|
||||
if (hasWindow) {
|
||||
let docElt = indicator.getNext().document.documentElement;
|
||||
for (let item of ["video", "audio", "screen"]) {
|
||||
let expectedValue = (expected && expected[item]) ? "true" : "";
|
||||
is(docElt.getAttribute("sharing" + item), expectedValue,
|
||||
item + " global indicator attribute as expected");
|
||||
}
|
||||
|
||||
ok(!indicator.hasMoreElements(), "only one global indicator window");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
browser/base/content/test/general/trackingPage.html
Normal file
12
browser/base/content/test/general/trackingPage.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<html dir="ltr" xml:lang="en-US" lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://tracking.example.com/"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -25,6 +25,7 @@ skip-if = os == "mac" # Intermittent failures, bug 898317
|
||||
[browser_newtab_drop_preview.js]
|
||||
[browser_newtab_enhanced.js]
|
||||
[browser_newtab_focus.js]
|
||||
[browser_newtab_intro.js]
|
||||
[browser_newtab_perwindow_private_browsing.js]
|
||||
[browser_newtab_reportLinkAction.js]
|
||||
[browser_newtab_reset.js]
|
||||
|
51
browser/base/content/test/newtab/browser_newtab_intro.js
Normal file
51
browser/base/content/test/newtab/browser_newtab_intro.js
Normal file
@ -0,0 +1,51 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const INTRO_PREF = "browser.newtabpage.introShown";
|
||||
const PRELOAD_PREF = "browser.newtab.preload";
|
||||
|
||||
function runTests() {
|
||||
let origIntro = Services.prefs.getBoolPref(INTRO_PREF);
|
||||
let origPreload = Services.prefs.getBoolPref(PRELOAD_PREF);
|
||||
registerCleanupFunction(_ => {
|
||||
Services.prefs.setBoolPref(INTRO_PREF, origIntro);
|
||||
Services.prefs.setBoolPref(PRELOAD_PREF, origPreload);
|
||||
});
|
||||
|
||||
// Test with preload false
|
||||
Services.prefs.setBoolPref(INTRO_PREF, false);
|
||||
Services.prefs.setBoolPref(PRELOAD_PREF, false);
|
||||
|
||||
let panel;
|
||||
function maybeWaitForPanel() {
|
||||
// If already open, no need to wait
|
||||
if (panel.state == "open") {
|
||||
executeSoon(TestRunner.next);
|
||||
return;
|
||||
}
|
||||
|
||||
// We're expecting the panel to open, so wait for it
|
||||
panel.addEventListener("popupshown", TestRunner.next);
|
||||
isnot(panel.state, "open", "intro panel can be slow to show");
|
||||
}
|
||||
|
||||
yield addNewTabPageTab();
|
||||
panel = getContentDocument().getElementById("newtab-intro-panel");
|
||||
yield maybeWaitForPanel();
|
||||
is(panel.state, "open", "intro automatically shown on first opening");
|
||||
is(Services.prefs.getBoolPref(INTRO_PREF), true, "newtab remembers that the intro was shown");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
panel = getContentDocument().getElementById("newtab-intro-panel");
|
||||
is(panel.state, "closed", "intro not shown on second opening");
|
||||
|
||||
// Test with preload true
|
||||
Services.prefs.setBoolPref(INTRO_PREF, false);
|
||||
Services.prefs.setBoolPref(PRELOAD_PREF, true);
|
||||
|
||||
yield addNewTabPageTab();
|
||||
panel = getContentDocument().getElementById("newtab-intro-panel");
|
||||
yield maybeWaitForPanel();
|
||||
is(panel.state, "open", "intro automatically shown on preloaded opening");
|
||||
is(Services.prefs.getBoolPref(INTRO_PREF), true, "newtab remembers that the intro was shown");
|
||||
}
|
@ -15,37 +15,39 @@ gDirectorySource = "data:application/json," + JSON.stringify({
|
||||
|
||||
function runTests() {
|
||||
Services.prefs.setBoolPref(PRELOAD_PREF, false);
|
||||
yield addNewTabPageTab();
|
||||
|
||||
let originalReportLinkAction = DirectoryLinksProvider.reportLinkAction;
|
||||
let originalReportSitesAction = DirectoryLinksProvider.reportSitesAction;
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(PRELOAD_PREF);
|
||||
DirectoryLinksProvider.reportLinkAction = originalReportLinkAction;
|
||||
DirectoryLinksProvider.reportSitesAction = originalReportSitesAction;
|
||||
});
|
||||
|
||||
let expected = {};
|
||||
DirectoryLinksProvider.reportLinkAction = function(link, action, tileIndex, pinned) {
|
||||
DirectoryLinksProvider.reportSitesAction = function(sites, action, siteIndex) {
|
||||
let {link} = sites[siteIndex];
|
||||
is(link.type, expected.type, "got expected type");
|
||||
is(link.directoryIndex, expected.link, "got expected link index");
|
||||
is(action, expected.action, "got expected action");
|
||||
is(tileIndex, expected.tile, "got expected tile index");
|
||||
is(pinned, expected.pinned, "got expected pinned");
|
||||
is(NewTabUtils.pinnedLinks.isPinned(link), expected.pinned, "got expected pinned");
|
||||
executeSoon(TestRunner.next);
|
||||
}
|
||||
|
||||
// Test that the last visible site (index 1) is reported
|
||||
expected.type = "sponsored";
|
||||
expected.action = "view";
|
||||
expected.pinned = false;
|
||||
yield addNewTabPageTab();
|
||||
yield null; // wait for reportSitesAction
|
||||
|
||||
// Click the pin button on the link in the 1th tile spot
|
||||
let siteNode = getCell(1).node.querySelector(".newtab-site");
|
||||
let pinButton = siteNode.querySelector(".newtab-control-pin");
|
||||
expected.type = "sponsored";
|
||||
expected.link = 1;
|
||||
expected.action = "pin";
|
||||
expected.tile = 1;
|
||||
expected.pinned = false;
|
||||
expected.pinned = true;
|
||||
yield EventUtils.synthesizeMouseAtCenter(pinButton, {}, getContentWindow());
|
||||
|
||||
// Unpin that link
|
||||
expected.action = "unpin";
|
||||
expected.pinned = true;
|
||||
expected.pinned = false;
|
||||
yield EventUtils.synthesizeMouseAtCenter(pinButton, {}, getContentWindow());
|
||||
yield whenPagesUpdated();
|
||||
|
||||
@ -53,16 +55,13 @@ function runTests() {
|
||||
let blockedSite = getCell(0).node.querySelector(".newtab-site");
|
||||
let blockButton = blockedSite.querySelector(".newtab-control-block");
|
||||
expected.type = "organic";
|
||||
expected.link = 0;
|
||||
expected.action = "block";
|
||||
expected.tile = 0;
|
||||
expected.pinned = false;
|
||||
yield EventUtils.synthesizeMouseAtCenter(blockButton, {}, getContentWindow());
|
||||
yield whenPagesUpdated();
|
||||
|
||||
// Click the 1th link now in the 0th tile spot
|
||||
expected.type = "sponsored";
|
||||
expected.link = 1;
|
||||
expected.action = "click";
|
||||
yield EventUtils.synthesizeMouseAtCenter(siteNode, {}, getContentWindow());
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ let gWindow = window;
|
||||
|
||||
// Default to dummy/empty directory links
|
||||
let gDirectorySource = 'data:application/json,{"test":1}';
|
||||
let gOrigDirectorySource;
|
||||
|
||||
// The tests assume all 3 rows and all 3 columns of sites are shown, but the
|
||||
// window may be too small to actually show everything. Resize it if necessary.
|
||||
@ -88,7 +89,7 @@ registerCleanupFunction(function () {
|
||||
}
|
||||
|
||||
Services.prefs.clearUserPref(PREF_NEWTAB_ENABLED);
|
||||
Services.prefs.clearUserPref(PREF_NEWTAB_DIRECTORYSOURCE);
|
||||
Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, gOrigDirectorySource);
|
||||
|
||||
return watchLinksChangeOnce();
|
||||
});
|
||||
@ -119,6 +120,9 @@ function test() {
|
||||
// Wait for hidden page to update with the desired links
|
||||
whenPagesUpdated(() => TestRunner.run(), true);
|
||||
});
|
||||
|
||||
// Save the original directory source (which is set globally for tests)
|
||||
gOrigDirectorySource = Services.prefs.getCharPref(PREF_NEWTAB_DIRECTORYSOURCE);
|
||||
Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, gDirectorySource);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
%notificationDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
]>
|
||||
|
||||
<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl"
|
||||
@ -1572,6 +1574,259 @@
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="bad-content-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
|
||||
<content>
|
||||
<xul:hbox align="start">
|
||||
<xul:image class="popup-notification-icon" xbl:inherits="popupid"/>
|
||||
<xul:vbox>
|
||||
<!-- header -->
|
||||
<xul:vbox>
|
||||
<xul:description anonid="badContentBlocked.title"
|
||||
class="popup-notification-item-title" xbl:inherits="popupid">
|
||||
</xul:description>
|
||||
<xul:description class="popup-notification-item-message"
|
||||
xbl:inherits="popupid">
|
||||
&badContentBlocked.moreinfo;
|
||||
</xul:description>
|
||||
</xul:vbox>
|
||||
<!-- mixed content -->
|
||||
<xul:vbox anonid="mixedContent" hidden="true">
|
||||
<xul:separator class="groove"/>
|
||||
<xul:hbox align="start">
|
||||
<xul:vbox>
|
||||
<xul:description class="popup-notification-item-title"
|
||||
xbl:inherits="popupid">
|
||||
&mixedContentBlocked2.message;
|
||||
</xul:description>
|
||||
<xul:description class="popup-notification-item-message"
|
||||
xbl:inherits="popupid">
|
||||
&mixedContentBlocked2.moreinfo;
|
||||
</xul:description>
|
||||
<xul:label anonid="mixedContent.helplink"
|
||||
class="text-link plain" href=""
|
||||
value="&mixedContentBlocked2.learnMore;"/>
|
||||
</xul:vbox>
|
||||
<xul:button
|
||||
type="menu" label="&mixedContentBlocked2.options;"
|
||||
sizetopopup="none">
|
||||
<xul:menupopup>
|
||||
<xul:menuitem anonid="mixedContentAction.unblock"
|
||||
hidden="true" label="&mixedContentBlocked2.unblock.label;"
|
||||
accesskey="&mixedContentBlocked2.unblock.accesskey;"
|
||||
oncommand="document.getBindingParent(this).disableMixedContentProtection();"/>
|
||||
<xul:menuitem anonid="mixedContentAction.block"
|
||||
hidden="true" label="&mixedContentBlocked2.block.label;"
|
||||
accesskey="&mixedContentBlocked2.block.accesskey;"
|
||||
oncommand="document.getBindingParent(this).enableMixedContentProtection();"/>
|
||||
</xul:menupopup>
|
||||
</xul:button>
|
||||
</xul:hbox>
|
||||
<xul:hbox anonid="mixedContentProtectionDisabled" hidden="true"
|
||||
class="popup-notification-footer" xbl:inherits="popupid">
|
||||
<xul:description class="popup-notification-item-message popup-notification-item-message-critical" xbl:inherits="popupid">
|
||||
&mixedContentBlocked2.disabled.message;
|
||||
</xul:description>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
<!-- tracking content -->
|
||||
<xul:vbox anonid="trackingContent" hidden="true">
|
||||
<xul:separator class="groove"/>
|
||||
<xul:hbox align="start">
|
||||
<xul:vbox>
|
||||
<xul:description class="popup-notification-item-title"
|
||||
xbl:inherits="popupid">
|
||||
&trackingContentBlocked.message;
|
||||
</xul:description>
|
||||
<xul:description class="popup-notification-item-message"
|
||||
xbl:inherits="popupid">
|
||||
&trackingContentBlocked.moreinfo;
|
||||
</xul:description>
|
||||
<xul:label anonid="trackingContent.helplink"
|
||||
class="text-link plain" href=""
|
||||
value="&trackingContentBlocked.learnMore;"/>
|
||||
</xul:vbox>
|
||||
<xul:button
|
||||
type="menu" label="&trackingContentBlocked.options;"
|
||||
sizetopopup="none">
|
||||
<xul:menupopup>
|
||||
<xul:menuitem anonid="trackingContentAction.unblock"
|
||||
hidden="true" label="&trackingContentBlocked.unblock.label;"
|
||||
oncommand="document.getBindingParent(this).disableTrackingContentProtection();"/>
|
||||
<xul:menuitem anonid="trackingContentAction.block"
|
||||
hidden="true" label="&trackingContentBlocked.block.label;"
|
||||
oncommand="document.getBindingParent(this).enableTrackingContentProtection();"/>
|
||||
</xul:menupopup>
|
||||
</xul:button>
|
||||
</xul:hbox>
|
||||
<xul:hbox anonid="trackingContentProtectionDisabled" hidden="true"
|
||||
class="popup-notification-footer" xbl:inherits="popupid">
|
||||
<xul:description class="popup-notification-item-message popup-notification-item-message-critical" xbl:inherits="popupid">
|
||||
&trackingContentBlocked.disabled.message;
|
||||
</xul:description>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<resources>
|
||||
<stylesheet src="chrome://global/skin/notification.css"/>
|
||||
</resources>
|
||||
<implementation>
|
||||
<field name="_brandShortName">
|
||||
document.getElementById("bundle_brand").getString("brandShortName")
|
||||
</field>
|
||||
<field name="_doorhangerTitle">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"badContentBlocked.title")
|
||||
</field>
|
||||
<field name="_mixedContent">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"mixedContent")
|
||||
</field>
|
||||
<field name="_mixedContentUnblock">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"mixedContentAction.unblock")
|
||||
</field>
|
||||
<field name="_mixedContentBlock">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"mixedContentAction.block");
|
||||
</field>
|
||||
<field name="_mixedContentProtectionDisabledWarning">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"mixedContentProtectionDisabled")
|
||||
</field>
|
||||
<field name="_mixedContentHelpLink">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"mixedContent.helplink")
|
||||
</field>
|
||||
<property name="isMixedContentBlocked" readonly="true">
|
||||
<getter><![CDATA[
|
||||
return this.notification.options.state &
|
||||
Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT;
|
||||
]]></getter>
|
||||
</property>
|
||||
<field name="_trackingContent">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"trackingContent")
|
||||
</field>
|
||||
<field name="_trackingContentUnblock">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"trackingContentAction.unblock")
|
||||
</field>
|
||||
<field name="_trackingContentBlock">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"trackingContentAction.block");
|
||||
</field>
|
||||
<field name="_trackingContentProtectionDisabledWarning">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"trackingContentProtectionDisabled")
|
||||
</field>
|
||||
<field name="_trackingContentHelpLink">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"trackingContent.helplink")
|
||||
</field>
|
||||
<property name="isTrackingContentBlocked" readonly="true">
|
||||
<getter><![CDATA[
|
||||
return this.notification.options.state &
|
||||
Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT;
|
||||
]]></getter>
|
||||
</property>
|
||||
<constructor><![CDATA[
|
||||
// default title
|
||||
_doorhangerTitle.value =
|
||||
gNavigatorBundle.getFormattedString(
|
||||
"badContentBlocked.notblocked.message", [this._brandShortName]);
|
||||
|
||||
if (this.notification.options.state &
|
||||
Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT) {
|
||||
_doorhangerTitle.value =
|
||||
gNavigatorBundle.getFormattedString(
|
||||
"badContentBlocked.blocked.message", [this._brandShortName]);
|
||||
_mixedContent.hidden = false;
|
||||
_mixedContentUnblock.hidden = false;
|
||||
_mixedContentHelpLink.href =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL")
|
||||
+ "mixed-content";
|
||||
}
|
||||
if (this.notification.options.state &
|
||||
Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT) {
|
||||
_mixedContent.hidden = false;
|
||||
_mixedContentBlock.hidden = false;
|
||||
_mixedContentProtectionDisabledWarning.hidden = false;
|
||||
_mixedContentHelpLink.href =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL")
|
||||
+ "mixed-content";
|
||||
}
|
||||
if (this.notification.options.state &
|
||||
Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) {
|
||||
_doorhangerTitle.value =
|
||||
gNavigatorBundle.getFormattedString(
|
||||
"badContentBlocked.blocked.message", [this._brandShortName]);
|
||||
_trackingContent.hidden = false
|
||||
_trackingContentUnblock.hidden = false;
|
||||
_trackingContentHelpLink.href =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL")
|
||||
+ "tracking-protection";
|
||||
}
|
||||
if (this.notification.options.state &
|
||||
Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT) {
|
||||
_trackingContent.hidden = false
|
||||
_trackingContentBlock.hidden = false;
|
||||
_trackingContentProtectionDisabledWarning.hidden = false;
|
||||
_trackingContentHelpLink.href =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL")
|
||||
+ "tracking-protection";
|
||||
}
|
||||
]]></constructor>
|
||||
<method name="disableMixedContentProtection">
|
||||
<body><![CDATA[
|
||||
// Use telemetry to measure how often unblocking happens
|
||||
const kMIXED_CONTENT_UNBLOCK_EVENT = 2;
|
||||
let histogram =
|
||||
Services.telemetry.getHistogramById(
|
||||
"MIXED_CONTENT_UNBLOCK_COUNTER");
|
||||
histogram.add(kMIXED_CONTENT_UNBLOCK_EVENT);
|
||||
// Reload the page with the content unblocked
|
||||
BrowserReloadWithFlags(
|
||||
nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="enableMixedContentProtection">
|
||||
<body><![CDATA[
|
||||
let docShell = gBrowser.webNavigation.QueryInterface(Ci.nsIDocShell);
|
||||
docShell.mixedContentChannel = null;
|
||||
BrowserReload();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="disableTrackingContentProtection">
|
||||
<body><![CDATA[
|
||||
// convert document URI into the format used by
|
||||
// nsChannelClassifier::ShouldEnableTrackingProtection
|
||||
// (any scheme turned into https is correct)
|
||||
let normalizedUrl = Services.io.newURI(
|
||||
"https://" + gBrowser.selectedBrowser.currentURI.hostPort,
|
||||
null, null);
|
||||
// Add the current host in the 'trackingprotection' consumer of
|
||||
// the permission manager using a normalized URI. This effectively
|
||||
// places this host on the tracking protection white list.
|
||||
Services.perms.add(normalizedUrl,
|
||||
"trackingprotection", Services.perms.ALLOW_ACTION);
|
||||
BrowserReload();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="enableTrackingContentProtection">
|
||||
<body><![CDATA[
|
||||
// Remove the current host from the 'trackingprotection' consumer
|
||||
// of the permission manager. This effectively removes this host
|
||||
// from the tracking protection white list (any list actually).
|
||||
Services.perms.remove(gBrowser.selectedBrowser.currentURI.host,
|
||||
"trackingprotection");
|
||||
BrowserReload();
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="click-to-play-plugins-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
|
||||
<content align="start" style="width: &pluginNotification.width;;">
|
||||
<xul:vbox flex="1" align="stretch" class="popup-notification-main-box"
|
||||
|
@ -12,9 +12,7 @@ SOURCES += [
|
||||
'nsModule.cpp',
|
||||
]
|
||||
|
||||
LIBRARY_NAME = 'browsercomps'
|
||||
|
||||
IS_COMPONENT = True
|
||||
XPCOMBinaryComponent('browsercomps')
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../about',
|
||||
@ -24,13 +22,6 @@ LOCAL_INCLUDES += [
|
||||
'../shell',
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'mozalloc',
|
||||
'nspr',
|
||||
'xpcomglue_s',
|
||||
'xul',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
OS_LIBS += [
|
||||
'ole32',
|
||||
|
@ -11,7 +11,7 @@ function test() {
|
||||
let cw = TabView.getContentWindow();
|
||||
whenAppTabIconAdded(cw.GroupItems.groupItems[0], function() {
|
||||
let body = cw.document.body;
|
||||
let [appTabIcon] = cw.iQ(".appTabTray .appTabIcon");
|
||||
let appTabIcon = cw.iQ(".appTabTray .appTabIcon")[0];
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(appTabIcon, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mousemove"}, cw);
|
||||
|
@ -12,8 +12,8 @@
|
||||
"filename": "gcc.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 166407,
|
||||
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
|
||||
"size": 166485,
|
||||
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
@ -12,8 +12,8 @@
|
||||
"filename": "gcc.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 166407,
|
||||
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
|
||||
"size": 166485,
|
||||
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
"filename": "clang.tar.bz2"
|
||||
},
|
||||
{
|
||||
"size": 166407,
|
||||
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
|
||||
"size": 166485,
|
||||
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
@ -12,8 +12,8 @@
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 166407,
|
||||
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
|
||||
"size": 166485,
|
||||
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2"
|
||||
}
|
||||
|
@ -98,7 +98,11 @@ let test = asyncTest(function*() {
|
||||
is (cmdSave.getAttribute("disabled"), "", "File menu item is enabled");
|
||||
is (cmdSaveas.getAttribute("disabled"), "", "File menu item is enabled");
|
||||
|
||||
is (cmdUndo.getAttribute("disabled"), "", "Edit menu item is enabled");
|
||||
// Use editor.canUndo() to see if this is failing - the menu disabled property
|
||||
// should be in sync with this because of isCommandEnabled in editor.js.
|
||||
info ('cmdUndo.getAttribute("disabled") is: "' + cmdUndo.getAttribute("disabled") + '"');
|
||||
ok (editor.editor.canUndo(), "Edit menu item is enabled");
|
||||
|
||||
is (cmdRedo.getAttribute("disabled"), "true", "Edit menu item is disabled");
|
||||
is (cmdCut.getAttribute("disabled"), "true", "Edit menu item is disabled");
|
||||
is (cmdCopy.getAttribute("disabled"), "true", "Edit menu item is disabled");
|
||||
|
@ -1291,10 +1291,7 @@ CssRuleView.prototype = {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
type: type,
|
||||
value: value
|
||||
};
|
||||
return {type, value};
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -31,8 +31,10 @@ const TOOLTIP_FONTFAMILY_TYPE = "font-family";
|
||||
|
||||
// Types of existing highlighters
|
||||
const HIGHLIGHTER_TRANSFORM_TYPE = "CssTransformHighlighter";
|
||||
const HIGHLIGHTER_SELECTOR_TYPE = "SelectorHighlighter";
|
||||
const HIGHLIGHTER_TYPES = [
|
||||
HIGHLIGHTER_TRANSFORM_TYPE
|
||||
HIGHLIGHTER_TRANSFORM_TYPE,
|
||||
HIGHLIGHTER_SELECTOR_TYPE
|
||||
];
|
||||
|
||||
// Types of nodes in the rule/computed-view
|
||||
@ -121,16 +123,26 @@ HighlightersOverlay.prototype = {
|
||||
}
|
||||
|
||||
// Choose the type of highlighter required for the hovered node
|
||||
let type;
|
||||
let type, options;
|
||||
if (this._isRuleViewTransform(nodeInfo) ||
|
||||
this._isComputedViewTransform(nodeInfo)) {
|
||||
type = HIGHLIGHTER_TRANSFORM_TYPE;
|
||||
} else if (nodeInfo.type === VIEW_NODE_SELECTOR_TYPE) {
|
||||
type = HIGHLIGHTER_SELECTOR_TYPE;
|
||||
options = {
|
||||
selector: nodeInfo.value,
|
||||
hideInfoBar: true,
|
||||
showOnly: "border",
|
||||
region: "border"
|
||||
};
|
||||
}
|
||||
|
||||
if (type) {
|
||||
this.highlighterShown = type;
|
||||
let node = this.view.inspector.selection.nodeFront;
|
||||
this._getHighlighter(type).then(highlighter => highlighter.show(node));
|
||||
this._getHighlighter(type).then(highlighter => {
|
||||
highlighter.show(node, options);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -96,6 +96,8 @@ skip-if = (os == "win" && debug) || e10s # bug 963492: win. bug 1040653: e10s.
|
||||
[browser_ruleview_refresh-on-attribute-change_02.js]
|
||||
[browser_ruleview_refresh-on-style-change.js]
|
||||
[browser_ruleview_select-and-copy-styles.js]
|
||||
[browser_ruleview_selector-highlighter_01.js]
|
||||
[browser_ruleview_selector-highlighter_02.js]
|
||||
[browser_ruleview_style-editor-link.js]
|
||||
skip-if = e10s # bug 1040670 Cannot open inline styles in viewSourceUtils
|
||||
[browser_ruleview_urls-clickable.js]
|
||||
|
@ -0,0 +1,44 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the selector highlighter is created when hovering over a selector
|
||||
// in the rule view
|
||||
|
||||
const PAGE_CONTENT = [
|
||||
'<style type="text/css">',
|
||||
' body, p, td {',
|
||||
' background: red;',
|
||||
' }',
|
||||
'</style>',
|
||||
'Test the selector highlighter'
|
||||
].join("\n");
|
||||
|
||||
let TYPE = "SelectorHighlighter";
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
yield addTab("data:text/html;charset=utf-8," + PAGE_CONTENT);
|
||||
|
||||
let {view: rView} = yield openRuleView();
|
||||
let hs = rView.highlighters;
|
||||
|
||||
ok(!hs.highlighters[TYPE], "No highlighter exists in the rule-view (1)");
|
||||
ok(!hs.promises[TYPE], "No highlighter is being created in the rule-view (1)");
|
||||
|
||||
info("Faking a mousemove NOT on a selector");
|
||||
let {valueSpan} = getRuleViewProperty(rView, "body, p, td", "background");
|
||||
hs._onMouseMove({target: valueSpan});
|
||||
ok(!hs.highlighters[TYPE], "No highlighter exists in the rule-view (2)");
|
||||
ok(!hs.promises[TYPE], "No highlighter is being created in the rule-view (2)");
|
||||
|
||||
info("Faking a mousemove on the body selector");
|
||||
let selectorContainer = getRuleViewSelector(rView, "body, p, td");
|
||||
// The highlighter appears for individual selectors only
|
||||
let bodySelector = selectorContainer.firstElementChild;
|
||||
hs._onMouseMove({target: bodySelector});
|
||||
ok(hs.promises[TYPE], "The highlighter is being initialized");
|
||||
let h = yield hs.promises[TYPE];
|
||||
is(h, hs.highlighters[TYPE], "The initialized highlighter is the right one");
|
||||
});
|
@ -0,0 +1,85 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the selector highlighter is shown when hovering over a selector
|
||||
// in the rule-view
|
||||
|
||||
// Note that in this test, we mock the highlighter front, merely testing the
|
||||
// behavior of the style-inspector UI for now
|
||||
|
||||
const PAGE_CONTENT = [
|
||||
'<style type="text/css">',
|
||||
' body {',
|
||||
' background: red;',
|
||||
' }',
|
||||
' p {',
|
||||
' color: white;',
|
||||
' }',
|
||||
'</style>',
|
||||
'<p>Testing the selector highlighter</p>'
|
||||
].join("\n");
|
||||
|
||||
const TYPE = "SelectorHighlighter";
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
yield addTab("data:text/html;charset=utf-8," + PAGE_CONTENT);
|
||||
|
||||
let {inspector, view: rView} = yield openRuleView();
|
||||
|
||||
// Mock the highlighter front to get the reference of the NodeFront
|
||||
let HighlighterFront = {
|
||||
isShown: false,
|
||||
nodeFront: null,
|
||||
options: null,
|
||||
show: function(nodeFront, options) {
|
||||
this.nodeFront = nodeFront;
|
||||
this.options = options;
|
||||
this.isShown = true;
|
||||
},
|
||||
hide: function() {
|
||||
this.nodeFront = null;
|
||||
this.options = null;
|
||||
this.isShown = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Inject the mock highlighter in the rule-view
|
||||
rView.highlighters.promises[TYPE] = {
|
||||
then: function(cb) {
|
||||
cb(HighlighterFront);
|
||||
}
|
||||
};
|
||||
|
||||
let selectorSpan = getRuleViewSelector(rView, "body").firstElementChild;
|
||||
|
||||
info("Checking that the HighlighterFront's show/hide methods are called");
|
||||
rView.highlighters._onMouseMove({target: selectorSpan});
|
||||
ok(HighlighterFront.isShown, "The highlighter is shown");
|
||||
rView.highlighters._onMouseLeave();
|
||||
ok(!HighlighterFront.isShown, "The highlighter is hidden");
|
||||
|
||||
info("Checking that the right NodeFront reference and options are passed");
|
||||
yield selectNode("p", inspector);
|
||||
let selectorSpan = getRuleViewSelector(rView, "p").firstElementChild;
|
||||
rView.highlighters._onMouseMove({target: selectorSpan});
|
||||
is(HighlighterFront.nodeFront.tagName, "P",
|
||||
"The right NodeFront is passed to the highlighter (1)");
|
||||
is(HighlighterFront.options.selector, "p",
|
||||
"The right selector option is passed to the highlighter (1)");
|
||||
|
||||
yield selectNode("body", inspector);
|
||||
let selectorSpan = getRuleViewSelector(rView, "body").firstElementChild;
|
||||
rView.highlighters._onMouseMove({target: selectorSpan});
|
||||
is(HighlighterFront.nodeFront.tagName, "BODY",
|
||||
"The right NodeFront is passed to the highlighter (2)");
|
||||
is(HighlighterFront.options.selector, "body",
|
||||
"The right selector option is passed to the highlighter (2)");
|
||||
|
||||
info("Checking that the highlighter gets hidden when hovering somewhere else");
|
||||
let {valueSpan} = getRuleViewProperty(rView, "body", "background");
|
||||
rView.highlighters._onMouseMove({target: valueSpan});
|
||||
ok(!HighlighterFront.isShown, "The highlighter is hidden");
|
||||
});
|
@ -641,6 +641,18 @@ function getRuleViewPropertyValue(view, selectorText, propertyName) {
|
||||
.valueSpan.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the selector DOM element corresponding to a given selector
|
||||
* in the rule-view
|
||||
* @param {CssRuleView} view The instance of the rule-view panel
|
||||
* @param {String} selectorText The selector in the rule-view to look for
|
||||
* @return {DOMNode} The selector DOM element
|
||||
*/
|
||||
function getRuleViewSelector(view, selectorText) {
|
||||
let rule = getRuleViewRule(view, selectorText);
|
||||
return rule.querySelector(".ruleview-selector, .ruleview-selector-matched");
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate a color change in a given color picker tooltip, and optionally wait
|
||||
* for a given element in the page to have its style changed as a result
|
||||
|
@ -56,10 +56,13 @@ function blockMixedContentTest1()
|
||||
|
||||
function mixedContentOverrideTest2(hud)
|
||||
{
|
||||
var notification = PopupNotifications.getNotification("mixed-content-blocked", browser);
|
||||
ok(notification, "Mixed Content Doorhanger didn't appear");
|
||||
var notification = PopupNotifications.getNotification("bad-content", browser);
|
||||
ok(notification, "Mixed Content Doorhanger did appear");
|
||||
notification.reshow();
|
||||
ok(PopupNotifications.panel.firstChild.isMixedContentBlocked, "OK: Mixed Content is being blocked");
|
||||
// Click on the doorhanger.
|
||||
notification.secondaryActions[0].callback();
|
||||
PopupNotifications.panel.firstChild.disableMixedContentProtection();
|
||||
notification.remove();
|
||||
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
|
@ -73,10 +73,10 @@ let inputTests = [
|
||||
// 7
|
||||
{
|
||||
input: "document.body.attributes",
|
||||
output: "MozNamedAttrMap [ ]",
|
||||
printOutput: "[object MozNamedAttrMap]",
|
||||
output: "NamedNodeMap [ ]",
|
||||
printOutput: "[object NamedNodeMap]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "MozNamedAttrMap[0]",
|
||||
variablesViewLabel: "NamedNodeMap[0]",
|
||||
},
|
||||
|
||||
// 8
|
||||
@ -137,11 +137,11 @@ let inputTests = [
|
||||
// 14
|
||||
{
|
||||
input: "document.body.attributes",
|
||||
output: 'MozNamedAttrMap [ class="test1 tezt2", id="foobarid", ' +
|
||||
output: 'NamedNodeMap [ class="test1 tezt2", id="foobarid", ' +
|
||||
'data-preview="zuzu"<a>foo" ]',
|
||||
printOutput: "[object MozNamedAttrMap]",
|
||||
printOutput: "[object NamedNodeMap]",
|
||||
inspectable: true,
|
||||
variablesViewLabel: "MozNamedAttrMap[3]",
|
||||
variablesViewLabel: "NamedNodeMap[3]",
|
||||
},
|
||||
|
||||
// 15
|
||||
|
@ -246,8 +246,11 @@ let UI = {
|
||||
this.unbusy();
|
||||
}, (e) => {
|
||||
this.cancelBusyTimeout();
|
||||
UI.reportError("error_operationFail", operationDescription);
|
||||
console.error(e);
|
||||
let operationCanceled = e && e.canceled;
|
||||
if (!operationCanceled) {
|
||||
UI.reportError("error_operationFail", operationDescription);
|
||||
console.error(e);
|
||||
}
|
||||
this.unbusy();
|
||||
});
|
||||
return promise;
|
||||
|
@ -337,7 +337,7 @@ exports.AppManager = AppManager = {
|
||||
try {
|
||||
this.selectedRuntime.connect(this.connection).then(
|
||||
() => {},
|
||||
() => {deferred.reject()});
|
||||
deferred.reject.bind(deferred));
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
deferred.reject();
|
||||
|
@ -126,11 +126,13 @@ let gRemoteRuntime = {
|
||||
return promise.reject();
|
||||
}
|
||||
let ret = {value: connection.host + ":" + connection.port};
|
||||
Services.prompt.prompt(win,
|
||||
Strings.GetStringFromName("remote_runtime_promptTitle"),
|
||||
Strings.GetStringFromName("remote_runtime_promptMessage"),
|
||||
ret, null, {});
|
||||
let title = Strings.GetStringFromName("remote_runtime_promptTitle");
|
||||
let message = Strings.GetStringFromName("remote_runtime_promptMessage");
|
||||
let ok = Services.prompt.prompt(win, title, message, ret, null, {});
|
||||
let [host,port] = ret.value.split(":");
|
||||
if (!ok) {
|
||||
return promise.reject({canceled: true});
|
||||
}
|
||||
if (!host || !port) {
|
||||
return promise.reject();
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user