Merge m-c to b2g-inbound. a=merge

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2014-08-25 13:07:41 -04:00
commit aa61f50d35
629 changed files with 11366 additions and 5512 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -24,7 +24,7 @@
if (navigator.platform.startsWith("Mac")) {
SimpleTest.expectAssertions(0, 1);
} else {
SimpleTest.expectAssertions(1);
SimpleTest.expectAssertions(0, 1);
}
function doTest()

View File

@ -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.

View File

@ -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);

View File

@ -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");

View File

@ -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 });
}

View File

@ -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"
}

View File

@ -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);
};

View File

@ -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) {

View File

@ -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) {

View File

@ -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,

View File

@ -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) {

View File

@ -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', {

View File

@ -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;

View File

@ -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'
};

View File

@ -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)));

View File

@ -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());

View File

@ -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;

View File

@ -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);
}
};

View File

@ -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;
}

View File

@ -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) => {

View File

@ -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:"

View File

@ -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,

View File

@ -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'

View File

@ -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()

View File

@ -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)

View File

@ -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));
}

View File

@ -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"
}

View File

@ -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));
}

View File

@ -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"
}

View File

@ -132,4 +132,7 @@ function closeConnection() {
return deferred.promise;
}
// bug 1042976 - temporary test disable
module.exports = {};
require('sdk/test/runner').runTestsFromModule(module);

View File

@ -127,4 +127,7 @@ function closeConnection() {
return deferred.promise;
}
// bug 1042976 - temporary test disable
module.exports = {};
require('sdk/test/runner').runTestsFromModule(module);

View File

@ -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) {

View File

@ -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);

View File

@ -0,0 +1 @@
module.exports = "assets!"

View File

@ -0,0 +1,6 @@
{
"name": "test-assets",
"version": "0.0.1",
"dependencies": {
}
}

View File

@ -0,0 +1,3 @@
body {
background-color: #ff0077;
}

View File

@ -4,6 +4,7 @@
"test-math": "*",
"test-custom-main": "*",
"test-custom-main-relative": "*",
"test-default-main": "*"
"test-default-main": "*",
"test-assets": "*"
}
}

View File

@ -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);

View File

@ -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`

View File

@ -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);

View File

@ -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,

View 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);

View File

@ -6,8 +6,8 @@
"filename": "setup.sh"
},
{
"size": 166407,
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
"size": 166485,
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -6,8 +6,8 @@
"filename": "setup.sh"
},
{
"size": 166407,
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
"size": 166485,
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -15,8 +15,8 @@
"filename": "clang.tar.bz2"
},
{
"size": 166407,
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
"size": 166485,
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -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">

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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");
}

View File

@ -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);
},
/**

View File

@ -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"/>

View File

@ -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() {

View 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]);
});
}
},
};

View File

@ -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;

View File

@ -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();

View File

@ -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">

View File

@ -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();
}
};

View File

@ -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);
},
/**

View File

@ -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>

View 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>

View File

@ -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]

View 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");
}

View File

@ -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() {

View File

@ -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();

View File

@ -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");

View File

@ -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() {

View File

@ -122,7 +122,7 @@ function closeStream(aAlreadyClosed) {
if (!aAlreadyClosed)
expectObserverCalled("recording-window-ended");
assertWebRTCIndicatorStatus(false);
assertWebRTCIndicatorStatus(null);
}
function loadPage(aUrl) {

View File

@ -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()

View File

@ -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();
});

View 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));
});

View 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>

View File

@ -0,0 +1,7 @@
<html>
<head>
</head>
<body>
<div id="mixedContentContainer">Mixed Content is here</div>
</body>
</html>

View File

@ -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");
}
}
}

View 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>

View File

@ -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]

View 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");
}

View File

@ -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());
}

View File

@ -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);
}

View File

@ -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"

View File

@ -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',

View File

@ -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);

View File

@ -12,8 +12,8 @@
"filename": "gcc.tar.xz"
},
{
"size": 166407,
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
"size": 166485,
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -12,8 +12,8 @@
"filename": "gcc.tar.xz"
},
{
"size": 166407,
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
"size": 166485,
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -15,8 +15,8 @@
"filename": "clang.tar.bz2"
},
{
"size": 166407,
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
"size": 166485,
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -12,8 +12,8 @@
"filename": "setup.sh"
},
{
"size": 166407,
"digest": "88fcc94f21818621e9e10107db913a3c787c6a68219c1e3e5fb26ebdf0864efdca4f05bd168d4851fee35c6b8d9ca4f9eb3ec229f565b7e6ce55ff6e7e899c24",
"size": 166485,
"digest": "ec5974b7e0a756ae3995f54ff92b3c17715857a8bf9407249e83372cd63d29fae086a324175e9b76cc883b29c3d8a474974fccc6d6e26f4dd5f3efa7fe9bf22a",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -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");

View File

@ -1291,10 +1291,7 @@ CssRuleView.prototype = {
return null;
}
return {
type: type,
value: value
};
return {type, value};
},
/**

View File

@ -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);
});
}
},

View File

@ -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]

View File

@ -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");
});

View File

@ -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");
});

View File

@ -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

View File

@ -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,

View File

@ -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&quot;&lt;a&gt;foo" ]',
printOutput: "[object MozNamedAttrMap]",
printOutput: "[object NamedNodeMap]",
inspectable: true,
variablesViewLabel: "MozNamedAttrMap[3]",
variablesViewLabel: "NamedNodeMap[3]",
},
// 15

View File

@ -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;

View File

@ -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();

View File

@ -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