mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-18 06:45:33 +00:00
Merge from mozilla-central.
This commit is contained in:
commit
a264d0ebc8
@ -1213,13 +1213,13 @@ HTMLTableAccessible::IsProbablyLayoutTable()
|
||||
// XXX currently, we just check the first cell -- do we really need to do more?
|
||||
nsCOMPtr<nsIDOMElement> cellElement;
|
||||
nsresult rv = GetCellAt(0, 0, *getter_AddRefs(cellElement));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
|
||||
NS_ENSURE_TRUE(cellContent, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(cellContent, false);
|
||||
nsIFrame *cellFrame = cellContent->GetPrimaryFrame();
|
||||
if (!cellFrame) {
|
||||
return NS_OK;
|
||||
RETURN_LAYOUT_ANSWER(false, "Could not get frame for cellContent");
|
||||
}
|
||||
nsMargin border;
|
||||
cellFrame->GetBorder(border);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
#virtual-cursor-box {
|
||||
#virtual-cursor-box {
|
||||
position: fixed;
|
||||
border: 1px solid orange;
|
||||
pointer-events: none;
|
||||
@ -11,7 +11,7 @@
|
||||
box-shadow: 1px 1px 1px #444;
|
||||
}
|
||||
|
||||
#virtual-cursor-inset {
|
||||
#virtual-cursor-inset {
|
||||
border-radius: 1px;
|
||||
box-shadow: inset 1px 1px 1px #444;
|
||||
display: block;
|
||||
@ -19,4 +19,12 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
#accessfu-glass {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
|
||||
Cu.import('resource://gre/modules/accessibility/Presenters.jsm');
|
||||
Cu.import('resource://gre/modules/accessibility/VirtualCursorController.jsm');
|
||||
Cu.import('resource://gre/modules/accessibility/TouchAdapter.jsm');
|
||||
|
||||
const ACCESSFU_DISABLE = 0;
|
||||
const ACCESSFU_ENABLE = 1;
|
||||
@ -44,8 +45,24 @@ var AccessFu = {
|
||||
this.prefsBranch.addObserver('activate', this, false);
|
||||
this.prefsBranch.addObserver('explorebytouch', this, false);
|
||||
|
||||
if (Utils.MozBuildApp == 'mobile/android')
|
||||
Services.obs.addObserver(this, 'Accessibility:Settings', false);
|
||||
this.touchAdapter = TouchAdapter;
|
||||
|
||||
switch(Utils.MozBuildApp) {
|
||||
case 'mobile/android':
|
||||
Services.obs.addObserver(this, 'Accessibility:Settings', false);
|
||||
this.touchAdapter = AndroidTouchAdapter;
|
||||
break;
|
||||
case 'b2g':
|
||||
aWindow.addEventListener(
|
||||
'ContentStart',
|
||||
(function(event) {
|
||||
let content = aWindow.shell.contentBrowser.contentWindow;
|
||||
content.addEventListener('mozContentEvent', this, false, true);
|
||||
}).bind(this), false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this._processPreferences();
|
||||
},
|
||||
@ -60,6 +77,13 @@ var AccessFu = {
|
||||
this._enabled = true;
|
||||
|
||||
Logger.info('enable');
|
||||
|
||||
// Add stylesheet
|
||||
let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
|
||||
this.stylesheet = this.chromeWin.document.createProcessingInstruction(
|
||||
'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
|
||||
this.chromeWin.document.insertBefore(this.stylesheet, this.chromeWin.document.firstChild);
|
||||
|
||||
this.addPresenter(new VisualPresenter());
|
||||
|
||||
// Implicitly add the Android presenter on Android.
|
||||
@ -88,6 +112,8 @@ var AccessFu = {
|
||||
|
||||
Logger.info('disable');
|
||||
|
||||
this.chromeWin.document.removeChild(this.stylesheet);
|
||||
|
||||
this.presenters.forEach(function(p) { p.detach(); });
|
||||
this.presenters = [];
|
||||
|
||||
@ -130,8 +156,10 @@ var AccessFu = {
|
||||
else
|
||||
this._disable();
|
||||
|
||||
VirtualCursorController.exploreByTouch = ebtPref == ACCESSFU_ENABLE;
|
||||
Logger.info('Explore by touch:', VirtualCursorController.exploreByTouch);
|
||||
if (ebtPref == ACCESSFU_ENABLE)
|
||||
this.touchAdapter.attach(this.chromeWin);
|
||||
else
|
||||
this.touchAdapter.detach(this.chromeWin);
|
||||
},
|
||||
|
||||
addPresenter: function addPresenter(presenter) {
|
||||
@ -192,6 +220,14 @@ var AccessFu = {
|
||||
this.presenters.forEach(function(p) { p.viewportChanged(); });
|
||||
break;
|
||||
}
|
||||
case 'mozContentEvent':
|
||||
{
|
||||
if (aEvent.detail.type == 'accessibility-screenreader') {
|
||||
let pref = aEvent.detail.enabled + 0;
|
||||
this._processPreferences(pref, pref);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -117,12 +117,6 @@ VisualPresenter.prototype = {
|
||||
attach: function VisualPresenter_attach(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
|
||||
// Add stylesheet
|
||||
let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
|
||||
this.stylesheet = aWindow.document.createProcessingInstruction(
|
||||
'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
|
||||
aWindow.document.insertBefore(this.stylesheet, aWindow.document.firstChild);
|
||||
|
||||
// Add highlight box
|
||||
this.highlightBox = this.chromeWin.document.
|
||||
createElementNS('http://www.w3.org/1999/xhtml', 'div');
|
||||
@ -138,7 +132,6 @@ VisualPresenter.prototype = {
|
||||
},
|
||||
|
||||
detach: function VisualPresenter_detach() {
|
||||
this.chromeWin.document.removeChild(this.stylesheet);
|
||||
this.highlightBox.parentNode.removeChild(this.highlightBox);
|
||||
this.highlightBox = this.stylesheet = null;
|
||||
},
|
||||
|
402
accessible/src/jsat/TouchAdapter.jsm
Normal file
402
accessible/src/jsat/TouchAdapter.jsm
Normal file
@ -0,0 +1,402 @@
|
||||
/* 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 Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
var EXPORTED_SYMBOLS = ['TouchAdapter', 'AndroidTouchAdapter'];
|
||||
|
||||
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
|
||||
|
||||
// We should not be emitting explore events more than 10 times a second.
|
||||
// It is granular enough to feel natural, and it does not hammer the CPU.
|
||||
const EXPLORE_THROTTLE = 100;
|
||||
|
||||
var TouchAdapter = {
|
||||
// minimal swipe distance in inches
|
||||
SWIPE_MIN_DISTANCE: 0.4,
|
||||
|
||||
// maximum duration of swipe
|
||||
SWIPE_MAX_DURATION: 400,
|
||||
|
||||
// how straight does a swipe need to be
|
||||
SWIPE_DIRECTNESS: 1.2,
|
||||
|
||||
// maximum consecutive
|
||||
MAX_CONSECUTIVE_GESTURE_DELAY: 400,
|
||||
|
||||
// delay before tap turns into dwell
|
||||
DWELL_THRESHOLD: 500,
|
||||
|
||||
// delay before distinct dwell events
|
||||
DWELL_REPEAT_DELAY: 300,
|
||||
|
||||
// maximum distance the mouse could move during a tap in inches
|
||||
TAP_MAX_RADIUS: 0.2,
|
||||
|
||||
attach: function TouchAdapter_attach(aWindow) {
|
||||
if (this.chromeWin)
|
||||
return;
|
||||
|
||||
Logger.info('TouchAdapter.attach');
|
||||
|
||||
this.chromeWin = aWindow;
|
||||
this._touchPoints = {};
|
||||
this._dwellTimeout = 0;
|
||||
this._prevGestures = {};
|
||||
this._lastExploreTime = 0;
|
||||
this._dpi = this.chromeWin.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindowUtils).displayDPI;
|
||||
|
||||
this.glass = this.chromeWin.document.
|
||||
createElementNS('http://www.w3.org/1999/xhtml', 'div');
|
||||
this.glass.id = 'accessfu-glass';
|
||||
this.chromeWin.document.documentElement.appendChild(this.glass);
|
||||
|
||||
this.glass.addEventListener('touchend', this, true, true);
|
||||
this.glass.addEventListener('touchmove', this, true, true);
|
||||
this.glass.addEventListener('touchstart', this, true, true);
|
||||
|
||||
if (Utils.OS != 'Android')
|
||||
Mouse2Touch.attach(aWindow);
|
||||
},
|
||||
|
||||
detach: function TouchAdapter_detach(aWindow) {
|
||||
if (!this.chromeWin)
|
||||
return;
|
||||
|
||||
Logger.info('TouchAdapter.detach');
|
||||
|
||||
this.glass.removeEventListener('touchend', this, true, true);
|
||||
this.glass.removeEventListener('touchmove', this, true, true);
|
||||
this.glass.removeEventListener('touchstart', this, true, true);
|
||||
this.glass.parentNode.removeChild(this.glass);
|
||||
|
||||
if (Utils.OS != 'Android')
|
||||
Mouse2Touch.detach(aWindow);
|
||||
|
||||
delete this.chromeWin;
|
||||
},
|
||||
|
||||
handleEvent: function TouchAdapter_handleEvent(aEvent) {
|
||||
let touches = aEvent.changedTouches;
|
||||
switch (aEvent.type) {
|
||||
case 'touchstart':
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
let touch = touches[i];
|
||||
let touchPoint = new TouchPoint(touch, aEvent.timeStamp, this._dpi);
|
||||
this._touchPoints[touch.identifier] = touchPoint;
|
||||
this._lastExploreTime = aEvent.timeStamp + this.SWIPE_MAX_DURATION;
|
||||
}
|
||||
this._dwellTimeout = this.chromeWin.setTimeout(
|
||||
(function () {
|
||||
this.compileAndEmit(aEvent.timeStamp + this.DWELL_THRESHOLD);
|
||||
}).bind(this), this.DWELL_THRESHOLD);
|
||||
break;
|
||||
case 'touchmove':
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
let touch = touches[i];
|
||||
let touchPoint = this._touchPoints[touch.identifier];
|
||||
touchPoint.update(touch, aEvent.timeStamp);
|
||||
}
|
||||
if (aEvent.timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
|
||||
this.compileAndEmit(aEvent.timeStamp);
|
||||
this._lastExploreTime = aEvent.timeStamp;
|
||||
}
|
||||
break;
|
||||
case 'touchend':
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
let touch = touches[i];
|
||||
let touchPoint = this._touchPoints[touch.identifier];
|
||||
touchPoint.update(touch, aEvent.timeStamp);
|
||||
touchPoint.finish();
|
||||
}
|
||||
this.compileAndEmit(aEvent.timeStamp);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
cleanupTouches: function cleanupTouches() {
|
||||
for (var identifier in this._touchPoints) {
|
||||
if (!this._touchPoints[identifier].done)
|
||||
continue;
|
||||
|
||||
delete this._touchPoints[identifier];
|
||||
}
|
||||
},
|
||||
|
||||
compile: function TouchAdapter_compile(aTime) {
|
||||
let multiDetails = {};
|
||||
|
||||
// Compound multiple simultaneous touch gestures.
|
||||
for (let identifier in this._touchPoints) {
|
||||
let touchPoint = this._touchPoints[identifier];
|
||||
let details = touchPoint.compile(aTime);
|
||||
|
||||
if (!details)
|
||||
continue;
|
||||
|
||||
details.touches = [identifier];
|
||||
|
||||
let otherTouches = multiDetails[details.type];
|
||||
if (otherTouches) {
|
||||
otherTouches.touches.push(identifier);
|
||||
otherTouches.startTime =
|
||||
Math.min(otherTouches.startTime, touchPoint.startTime);
|
||||
} else {
|
||||
details.startTime = touchPoint.startTime;
|
||||
details.endTime = aTime;
|
||||
multiDetails[details.type] = details;
|
||||
}
|
||||
}
|
||||
|
||||
// Compound multiple consecutive touch gestures.
|
||||
for each (let details in multiDetails) {
|
||||
let idhash = details.touches.slice().sort().toString();
|
||||
let prevGesture = this._prevGestures[idhash];
|
||||
|
||||
if (prevGesture) {
|
||||
// The time delta is calculated as the period between the end of the
|
||||
// last gesture and the start of this one.
|
||||
let timeDelta = details.startTime - prevGesture.endTime;
|
||||
if (timeDelta > this.MAX_CONSECUTIVE_GESTURE_DELAY) {
|
||||
delete this._prevGestures[idhash];
|
||||
} else {
|
||||
if (details.type == 'tap' && prevGesture.type == 'tap')
|
||||
details.type = 'doubletap';
|
||||
if (details.type == 'tap' && prevGesture.type == 'doubletap')
|
||||
details.type = 'tripletap';
|
||||
if (details.type == 'dwell' && prevGesture.type == 'tap')
|
||||
details.type = 'taphold';
|
||||
}
|
||||
}
|
||||
|
||||
this._prevGestures[idhash] = details;
|
||||
}
|
||||
|
||||
this.chromeWin.clearTimeout(this._dwellTimeout);
|
||||
this.cleanupTouches();
|
||||
|
||||
return multiDetails;
|
||||
},
|
||||
|
||||
emitGesture: function TouchAdapter_emitGesture(aDetails) {
|
||||
let evt = this.chromeWin.document.createEvent('CustomEvent');
|
||||
evt.initCustomEvent('mozAccessFuGesture', true, true, aDetails);
|
||||
this.chromeWin.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
compileAndEmit: function TouchAdapter_compileAndEmit(aTime) {
|
||||
for each (let details in this.compile(aTime)) {
|
||||
this.emitGesture(details);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/***
|
||||
* A TouchPoint represents a single touch from the moment of contact until it is
|
||||
* lifted from the surface. It is capable of compiling gestures from the scope
|
||||
* of one single touch.
|
||||
*/
|
||||
function TouchPoint(aTouch, aTime, aDPI) {
|
||||
this.startX = aTouch.screenX;
|
||||
this.startY = aTouch.screenY;
|
||||
this.startTime = aTime;
|
||||
this.distanceTraveled = 0;
|
||||
this.dpi = aDPI;
|
||||
this.done = false;
|
||||
}
|
||||
|
||||
TouchPoint.prototype = {
|
||||
update: function TouchPoint_update(aTouch, aTime) {
|
||||
let lastX = this.x;
|
||||
let lastY = this.y;
|
||||
this.x = aTouch.screenX;
|
||||
this.y = aTouch.screenY;
|
||||
this.time = aTime;
|
||||
|
||||
if (lastX != undefined && lastY != undefined)
|
||||
this.distanceTraveled += this.getDistanceToCoord(lastX, lastY);
|
||||
},
|
||||
|
||||
getDistanceToCoord: function TouchPoint_getDistanceToCoord(aX, aY) {
|
||||
return Math.sqrt(Math.pow(this.x - aX, 2) + Math.pow(this.y - aY, 2));
|
||||
},
|
||||
|
||||
finish: function TouchPoint_finish() {
|
||||
this.done = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Compile a gesture from an individual touch point. This is used by the
|
||||
* TouchAdapter to compound multiple single gestures in to higher level
|
||||
* gestures.
|
||||
*/
|
||||
compile: function TouchPoint_compile(aTime) {
|
||||
let directDistance = this.directDistanceTraveled;
|
||||
let duration = aTime - this.startTime;
|
||||
|
||||
// To be considered a tap/dwell...
|
||||
if ((this.distanceTraveled / this.dpi) < TouchAdapter.TAP_MAX_RADIUS) { // Didn't travel
|
||||
if (duration < TouchAdapter.DWELL_THRESHOLD) {
|
||||
// Mark it as done so we don't use this touch for another gesture.
|
||||
this.finish();
|
||||
return {type: 'tap', x: this.startX, y: this.startY};
|
||||
} else if (!this.done && duration == TouchAdapter.DWELL_THRESHOLD) {
|
||||
return {type: 'dwell', x: this.startX, y: this.startY};
|
||||
}
|
||||
}
|
||||
|
||||
// To be considered a swipe...
|
||||
if (duration <= TouchAdapter.SWIPE_MAX_DURATION && // Quick enough
|
||||
(directDistance / this.dpi) >= TouchAdapter.SWIPE_MIN_DISTANCE && // Traveled far
|
||||
(directDistance * 1.2) >= this.distanceTraveled) { // Direct enough
|
||||
|
||||
let swipeGesture = {x1: this.startX, y1: this.startY,
|
||||
x2: this.x, y2: this.y};
|
||||
let deltaX = this.x - this.startX;
|
||||
let deltaY = this.y - this.startY;
|
||||
|
||||
if (Math.abs(deltaX) > Math.abs(deltaY)) {
|
||||
// Horizontal swipe.
|
||||
if (deltaX > 0)
|
||||
swipeGesture.type = 'swiperight';
|
||||
else
|
||||
swipeGesture.type = 'swipeleft';
|
||||
} else if (Math.abs(deltaX) < Math.abs(deltaY)) {
|
||||
// Vertical swipe.
|
||||
if (deltaY > 0)
|
||||
swipeGesture.type = 'swipedown';
|
||||
else
|
||||
swipeGesture.type = 'swipeup';
|
||||
} else {
|
||||
// A perfect 45 degree swipe?? Not in our book.
|
||||
return null;
|
||||
}
|
||||
|
||||
this.finish();
|
||||
|
||||
return swipeGesture;
|
||||
}
|
||||
|
||||
// To be considered an explore...
|
||||
if (!this.done &&
|
||||
duration > TouchAdapter.SWIPE_MAX_DURATION &&
|
||||
(this.distanceTraveled / this.dpi) > TouchAdapter.TAP_MAX_RADIUS) {
|
||||
return {type: 'explore', x: this.x, y: this.y};
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
get directDistanceTraveled() {
|
||||
return this.getDistanceToCoord(this.startX, this.startY);
|
||||
}
|
||||
};
|
||||
|
||||
var Mouse2Touch = {
|
||||
_MouseToTouchMap: {
|
||||
mousedown: 'touchstart',
|
||||
mouseup: 'touchend',
|
||||
mousemove: 'touchmove'
|
||||
},
|
||||
|
||||
attach: function Mouse2Touch_attach(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
this.chromeWin.addEventListener('mousedown', this, true, true);
|
||||
this.chromeWin.addEventListener('mouseup', this, true, true);
|
||||
this.chromeWin.addEventListener('mousemove', this, true, true);
|
||||
},
|
||||
|
||||
detach: function Mouse2Touch_detach(aWindow) {
|
||||
this.chromeWin.removeEventListener('mousedown', this, true, true);
|
||||
this.chromeWin.removeEventListener('mouseup', this, true, true);
|
||||
this.chromeWin.removeEventListener('mousemove', this, true, true);
|
||||
},
|
||||
|
||||
handleEvent: function Mouse2Touch_handleEvent(aEvent) {
|
||||
if (aEvent.buttons == 0)
|
||||
return;
|
||||
|
||||
let name = this._MouseToTouchMap[aEvent.type];
|
||||
let evt = this.chromeWin.document.createEvent("touchevent");
|
||||
let points = [this.chromeWin.document.createTouch(
|
||||
this.chromeWin, aEvent.target, 0,
|
||||
aEvent.pageX, aEvent.pageY, aEvent.screenX, aEvent.screenY,
|
||||
aEvent.clientX, aEvent.clientY, 1, 1, 0, 0)];
|
||||
|
||||
// Simulate another touch point at a 5px offset when ctrl is pressed.
|
||||
if (aEvent.ctrlKey)
|
||||
points.push(this.chromeWin.document.createTouch(
|
||||
this.chromeWin, aEvent.target, 1,
|
||||
aEvent.pageX + 5, aEvent.pageY + 5,
|
||||
aEvent.screenX + 5, aEvent.screenY + 5,
|
||||
aEvent.clientX + 5, aEvent.clientY + 5,
|
||||
1, 1, 0, 0));
|
||||
|
||||
// Simulate another touch point at a -5px offset when alt is pressed.
|
||||
if (aEvent.altKey)
|
||||
points.push(this.chromeWin.document.createTouch(
|
||||
this.chromeWin, aEvent.target, 2,
|
||||
aEvent.pageX - 5, aEvent.pageY - 5,
|
||||
aEvent.screenX - 5, aEvent.screenY - 5,
|
||||
aEvent.clientX - 5, aEvent.clientY - 5,
|
||||
1, 1, 0, 0));
|
||||
|
||||
let touches = this.chromeWin.document.createTouchList(points);
|
||||
if (name == "touchend") {
|
||||
let empty = this.chromeWin.document.createTouchList();
|
||||
evt.initTouchEvent(name, true, true, this.chromeWin, 0,
|
||||
false, false, false, false, empty, empty, touches);
|
||||
} else {
|
||||
evt.initTouchEvent(name, true, true, this.chromeWin, 0,
|
||||
false, false, false, false, touches, touches, touches);
|
||||
}
|
||||
aEvent.target.dispatchEvent(evt);
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopImmediatePropagation();
|
||||
}
|
||||
};
|
||||
|
||||
var AndroidTouchAdapter = {
|
||||
attach: function AndroidTouchAdapter_attach(aWindow) {
|
||||
if (this.chromeWin)
|
||||
return;
|
||||
|
||||
Logger.info('AndroidTouchAdapter.attach');
|
||||
|
||||
this.chromeWin = aWindow;
|
||||
this.chromeWin.addEventListener('mousemove', this, true, true);
|
||||
this._lastExploreTime = 0;
|
||||
},
|
||||
|
||||
detach: function AndroidTouchAdapter_detach(aWindow) {
|
||||
if (!this.chromeWin)
|
||||
return;
|
||||
|
||||
Logger.info('AndroidTouchAdapter.detach');
|
||||
|
||||
this.chromeWin.removeEventListener('mousemove', this, true, true);
|
||||
delete this.chromeWin;
|
||||
},
|
||||
|
||||
handleEvent: function AndroidTouchAdapter_handleEvent(aEvent) {
|
||||
// On non-Android we use the shift key to simulate touch.
|
||||
if (Utils.MozBuildApp != 'mobile/android' && !aEvent.shiftKey)
|
||||
return;
|
||||
|
||||
if (aEvent.timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
|
||||
let evt = this.chromeWin.document.createEvent('CustomEvent');
|
||||
evt.initCustomEvent(
|
||||
'mozAccessFuGesture', true, true,
|
||||
{type: 'explore', x: aEvent.screenX, y: aEvent.screenY});
|
||||
this.chromeWin.dispatchEvent(evt);
|
||||
this._lastExploreTime = aEvent.timeStamp;
|
||||
}
|
||||
}
|
||||
};
|
@ -71,6 +71,20 @@ var Utils = {
|
||||
return this.getBrowserApp(aWindow).selectedBrowser.contentDocument;
|
||||
},
|
||||
|
||||
getAllDocuments: function getAllDocuments(aWindow) {
|
||||
let doc = gAccRetrieval.
|
||||
getAccessibleFor(this.getCurrentContentDoc(aWindow)).
|
||||
QueryInterface(Ci.nsIAccessibleDocument);
|
||||
let docs = [];
|
||||
function getAllDocuments(aDocument) {
|
||||
docs.push(aDocument.DOMDocument);
|
||||
for (let i = 0; i < aDocument.childDocumentCount; i++)
|
||||
getAllDocuments(aDocument.getChildDocumentAt(i));
|
||||
}
|
||||
getAllDocuments(doc);
|
||||
return docs;
|
||||
},
|
||||
|
||||
getViewport: function getViewport(aWindow) {
|
||||
switch (this.MozBuildApp) {
|
||||
case 'mobile/android':
|
||||
@ -103,6 +117,83 @@ var Utils = {
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
scroll: function scroll(aWindow, aPage, aHorizontal) {
|
||||
for each (let doc in this.getAllDocuments(aWindow)) {
|
||||
// First see if we could scroll a window.
|
||||
let win = doc.defaultView;
|
||||
if (!aHorizontal && win.scrollMaxY &&
|
||||
((aPage > 0 && win.scrollY < win.scrollMaxY) ||
|
||||
(aPage < 0 && win.scrollY > 0))) {
|
||||
win.scroll(0, win.innerHeight);
|
||||
return true;
|
||||
} else if (aHorizontal && win.scrollMaxX &&
|
||||
((aPage > 0 && win.scrollX < win.scrollMaxX) ||
|
||||
(aPage < 0 && win.scrollX > 0))) {
|
||||
win.scroll(win.innerWidth, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Second, try to scroll main section or current target if there is no
|
||||
// main section.
|
||||
let main = doc.querySelector('[role=main]') ||
|
||||
doc.querySelector(':target');
|
||||
|
||||
if (main) {
|
||||
if ((!aHorizontal && main.clientHeight < main.scrollHeight) ||
|
||||
(aHorizontal && main.clientWidth < main.scrollWidth)) {
|
||||
let s = win.getComputedStyle(main);
|
||||
if (!aHorizontal) {
|
||||
if (s.overflowY == 'scroll' || s.overflowY == 'auto') {
|
||||
main.scrollTop += aPage * main.clientHeight;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (s.overflowX == 'scroll' || s.overflowX == 'auto') {
|
||||
main.scrollLeft += aPage * main.clientWidth;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
changePage: function changePage(aWindow, aPage) {
|
||||
for each (let doc in this.getAllDocuments(aWindow)) {
|
||||
// Get current main section or active target.
|
||||
let main = doc.querySelector('[role=main]') ||
|
||||
doc.querySelector(':target');
|
||||
if (!main)
|
||||
continue;
|
||||
|
||||
let mainAcc = gAccRetrieval.getAccessibleFor(main);
|
||||
if (!mainAcc)
|
||||
continue;
|
||||
|
||||
let controllers = mainAcc.
|
||||
getRelationByType(Ci.nsIAccessibleRelation.RELATION_CONTROLLED_BY);
|
||||
|
||||
for (var i=0; controllers.targetsCount > i; i++) {
|
||||
let controller = controllers.getTarget(i);
|
||||
// If the section has a controlling slider, it should be considered
|
||||
// the page-turner.
|
||||
if (controller.role == Ci.nsIAccessibleRole.ROLE_SLIDER) {
|
||||
// Sliders are controlled with ctrl+right/left. I just decided :)
|
||||
let evt = doc.createEvent("KeyboardEvent");
|
||||
evt.initKeyEvent('keypress', true, true, null,
|
||||
true, false, false, false,
|
||||
(aPage > 0) ? evt.DOM_VK_RIGHT : evt.DOM_VK_LEFT, 0);
|
||||
controller.DOMNode.dispatchEvent(evt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -197,12 +197,12 @@ var VirtualCursorController = {
|
||||
attach: function attach(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
this.chromeWin.document.addEventListener('keypress', this, true);
|
||||
this.chromeWin.document.addEventListener('mousemove', this, true);
|
||||
this.chromeWin.addEventListener('mozAccessFuGesture', this, true);
|
||||
},
|
||||
|
||||
detach: function detach() {
|
||||
this.chromeWin.document.removeEventListener('keypress', this, true);
|
||||
this.chromeWin.document.removeEventListener('mousemove', this, true);
|
||||
this.chromeWin.removeEventListener('mozAccessFuGesture', this, true);
|
||||
},
|
||||
|
||||
handleEvent: function VirtualCursorController_handleEvent(aEvent) {
|
||||
@ -210,45 +210,68 @@ var VirtualCursorController = {
|
||||
case 'keypress':
|
||||
this._handleKeypress(aEvent);
|
||||
break;
|
||||
case 'mousemove':
|
||||
this._handleMousemove(aEvent);
|
||||
case 'mozAccessFuGesture':
|
||||
this._handleGesture(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_handleMousemove: function _handleMousemove(aEvent) {
|
||||
// Explore by touch is disabled.
|
||||
if (!this.exploreByTouch)
|
||||
return;
|
||||
_handleGesture: function _handleGesture(aEvent) {
|
||||
let document = Utils.getCurrentContentDoc(this.chromeWin);
|
||||
let detail = aEvent.detail;
|
||||
Logger.info('Gesture', detail.type,
|
||||
'(fingers: ' + detail.touches.length + ')');
|
||||
|
||||
// On non-Android we use the shift key to simulate touch.
|
||||
if (Utils.OS != 'Android' && !aEvent.shiftKey)
|
||||
return;
|
||||
|
||||
// We should not be calling moveToPoint more than 10 times a second.
|
||||
// It is granular enough to feel natural, and it does not hammer the CPU.
|
||||
if (!this._handleMousemove._lastEventTime ||
|
||||
aEvent.timeStamp - this._handleMousemove._lastEventTime >= 100) {
|
||||
this.moveToPoint(Utils.getCurrentContentDoc(this.chromeWin),
|
||||
aEvent.screenX, aEvent.screenY);
|
||||
this._handleMousemove._lastEventTime = aEvent.timeStamp;
|
||||
if (detail.touches.length == 1) {
|
||||
switch (detail.type) {
|
||||
case 'swiperight':
|
||||
this.moveForward(document, aEvent.shiftKey);
|
||||
break;
|
||||
case 'swipeleft':
|
||||
this.moveBackward(document, aEvent.shiftKey);
|
||||
break;
|
||||
case 'doubletap':
|
||||
this.activateCurrent(document);
|
||||
break;
|
||||
case 'explore':
|
||||
this.moveToPoint(document, detail.x, detail.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopImmediatePropagation();
|
||||
if (detail.touches.length == 3) {
|
||||
switch (detail.type) {
|
||||
case 'swiperight':
|
||||
if (!Utils.scroll(this.chromeWin, -1, true))
|
||||
Utils.changePage(this.chromeWin, -1);
|
||||
break;
|
||||
case 'swipedown':
|
||||
Utils.scroll(this.chromeWin, -1);
|
||||
break;
|
||||
case 'swipeleft':
|
||||
if (!Utils.scroll(this.chromeWin, 1, true))
|
||||
Utils.changePage(this.chromeWin, 1);
|
||||
case 'swipeup':
|
||||
Utils.scroll(this.chromeWin, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_handleKeypress: function _handleKeypress(aEvent) {
|
||||
let document = Utils.getCurrentContentDoc(this.chromeWin);
|
||||
let target = aEvent.target;
|
||||
|
||||
// Ignore keys with modifiers so the content could take advantage of them.
|
||||
if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
|
||||
return;
|
||||
|
||||
switch (aEvent.keyCode) {
|
||||
case 0:
|
||||
// an alphanumeric key was pressed, handle it separately.
|
||||
// If it was pressed with either alt or ctrl, just pass through.
|
||||
// If it was pressed with meta, pass the key on without the meta.
|
||||
if (this.editableState ||
|
||||
aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
|
||||
if (this.editableState)
|
||||
return;
|
||||
|
||||
let key = String.fromCharCode(aEvent.charCode);
|
||||
|
@ -488,6 +488,13 @@ pref("javascript.options.mem.log", true);
|
||||
// Increase mark slice time from 10ms to 30ms
|
||||
pref("javascript.options.mem.gc_incremental_slice_ms", 30);
|
||||
|
||||
pref("javascript.options.mem.gc_high_frequency_heap_growth_max", 120);
|
||||
pref("javascript.options.mem.gc_high_frequency_heap_growth_min", 101);
|
||||
pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 40);
|
||||
pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 10);
|
||||
pref("javascript.options.mem.gc_low_frequency_heap_growth", 105);
|
||||
pref("javascript.options.mem.high_water_mark", 16);
|
||||
|
||||
// Show/Hide scrollbars when active/inactive
|
||||
pref("ui.showHideScrollbars", 1);
|
||||
|
||||
@ -508,3 +515,6 @@ pref("hal.processPriorityManager.gonk.backgroundNice", 10);
|
||||
pref("dom.ipc.processPrelauch.enabled", true);
|
||||
// Wait this long before pre-launching a new subprocess.
|
||||
pref("dom.ipc.processPrelauch.delayMs", 1000);
|
||||
|
||||
// Ignore the "dialog=1" feature in window.open.
|
||||
pref("dom.disable_window_open_dialog_feature", true);
|
||||
|
93
b2g/chrome/content/runapp.js
Normal file
93
b2g/chrome/content/runapp.js
Normal file
@ -0,0 +1,93 @@
|
||||
// runapp.js:
|
||||
// Provide a --runapp APPNAME command-line option.
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
// Get the command line arguments that were passed to the b2g client
|
||||
let args = window.arguments[0].QueryInterface(Ci.nsICommandLine);
|
||||
let appname;
|
||||
|
||||
// - Check if the argument is present before doing any work.
|
||||
try {
|
||||
// Returns null if the argument was not specified. Throws
|
||||
// NS_ERROR_INVALID_ARG if there is no parameter specified (because
|
||||
// it was the last argument or the next argument starts with '-').
|
||||
// However, someone could still explicitly pass an empty argument!
|
||||
appname = args.handleFlagWithParam('runapp', false);
|
||||
}
|
||||
catch(e) {
|
||||
// treat a missing parameter like an empty parameter (=> show usage)
|
||||
appname = '';
|
||||
}
|
||||
|
||||
// not specified, bail.
|
||||
if (appname === null)
|
||||
return;
|
||||
|
||||
// - Get the list of apps since the parameter was specified
|
||||
let appsReq = navigator.mozApps.mgmt.getAll();
|
||||
appsReq.onsuccess = function() {
|
||||
let apps = appsReq.result;
|
||||
function findAppWithName(name) {
|
||||
let normalizedSearchName = name.replace(/[- ]+/g, '').toLowerCase();
|
||||
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let app = apps[i];
|
||||
let normalizedAppName =
|
||||
app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
|
||||
if (normalizedSearchName === normalizedAppName) {
|
||||
return app;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function usageAndDie(justApps) {
|
||||
if (!justApps)
|
||||
dump(
|
||||
'The --runapp argument specifies an app to automatically run at\n'+
|
||||
'startup. We match against app names per their manifest and \n' +
|
||||
'ignoring capitalization, dashes, and whitespace.\n' +
|
||||
'\nThe system will load as usual except the lock screen will be ' +
|
||||
'automatically be disabled.\n\n' +
|
||||
'Known apps:\n');
|
||||
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
dump(' ' + apps[i].manifest.name + '\n');
|
||||
}
|
||||
|
||||
// Exit the b2g client
|
||||
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
|
||||
}
|
||||
|
||||
if (appname === '') {
|
||||
usageAndDie();
|
||||
return;
|
||||
}
|
||||
|
||||
let app = findAppWithName(appname);
|
||||
if (!app) {
|
||||
dump('Could not find app: "' + appname + '". Maybe you meant one of:\n');
|
||||
usageAndDie(true);
|
||||
return;
|
||||
}
|
||||
|
||||
let setReq =
|
||||
navigator.mozSettings.getLock().set({'lockscreen.enabled': false});
|
||||
setReq.onsuccess = function() {
|
||||
// give the event loop another turn to disable the lock screen
|
||||
window.setTimeout(function() {
|
||||
dump('--runapp launching app: ' + app.manifest.name + '\n');
|
||||
app.launch();
|
||||
}, 0);
|
||||
};
|
||||
setReq.onerror = function() {
|
||||
dump('--runapp failed to disable lock-screen. Giving up.\n');
|
||||
};
|
||||
|
||||
dump('--runapp found app: ' + app.manifest.name +
|
||||
', disabling lock screen...\n');
|
||||
};
|
||||
appsReq.onerror = function() {
|
||||
dump('Problem getting the list of all apps!');
|
||||
};
|
||||
});
|
@ -16,6 +16,8 @@ Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
|
||||
Cu.import('resource://gre/modules/Webapps.jsm');
|
||||
Cu.import('resource://gre/modules/AlarmService.jsm');
|
||||
Cu.import('resource://gre/modules/ActivitiesService.jsm');
|
||||
Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
|
||||
Cu.import('resource://gre/modules/ObjectWrapper.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'env',
|
||||
'@mozilla.org/process/environment;1',
|
||||
@ -314,7 +316,8 @@ var shell = {
|
||||
},
|
||||
|
||||
sendChromeEvent: function shell_sendChromeEvent(details) {
|
||||
this.sendEvent(getContentWindow(), "mozChromeEvent", details);
|
||||
this.sendEvent(getContentWindow(), "mozChromeEvent",
|
||||
ObjectWrapper.wrap(details, getContentWindow()));
|
||||
},
|
||||
|
||||
receiveMessage: function shell_receiveMessage(message) {
|
||||
@ -372,14 +375,14 @@ Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
|
||||
url: msg.uri,
|
||||
origin: origin,
|
||||
manifest: msg.manifest,
|
||||
isActivity: (msg.type == 'activity'),
|
||||
target: msg.target
|
||||
});
|
||||
}, 'system-messages-open-app', false);
|
||||
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
shell.sendEvent(shell.contentBrowser.contentWindow,
|
||||
"mozChromeEvent", { type: "fullscreenoriginchange",
|
||||
fullscreenorigin: aData } );
|
||||
shell.sendChromeEvent({ type: "fullscreenoriginchange",
|
||||
fullscreenorigin: aData });
|
||||
}, "fullscreen-origin-change", false);
|
||||
|
||||
(function Repl() {
|
||||
@ -646,3 +649,24 @@ window.addEventListener('ContentStart', function ss_onContentStart() {
|
||||
}
|
||||
}, "geolocation-device-events", false);
|
||||
})();
|
||||
|
||||
(function recordingStatusTracker() {
|
||||
let gRecordingActiveCount = 0;
|
||||
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
let oldCount = gRecordingActiveCount;
|
||||
if (aData == "starting") {
|
||||
gRecordingActiveCount += 1;
|
||||
} else if (aData == "shutdown") {
|
||||
gRecordingActiveCount -= 1;
|
||||
}
|
||||
|
||||
// We need to track changes from 1 <-> 0
|
||||
if (gRecordingActiveCount + oldCount == 1) {
|
||||
shell.sendChromeEvent({
|
||||
type: 'recording-status',
|
||||
active: (gRecordingActiveCount == 1)
|
||||
});
|
||||
}
|
||||
}, "recording-device-events", false);
|
||||
})();
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef ANDROID
|
||||
<!-- this script handles the screen argument for desktop builds -->
|
||||
<script type="application/javascript" src="chrome://browser/content/screen.js"/>
|
||||
<!-- this script handles the "runapp" argument for desktop builds -->
|
||||
<script type="application/javascript" src="chrome://browser/content/runapp.js"/>
|
||||
#endif
|
||||
<!-- The html:iframe containing the UI is created here. -->
|
||||
</window>
|
||||
|
@ -16,6 +16,7 @@ chrome.jar:
|
||||
* content/shell.js (content/shell.js)
|
||||
#ifndef ANDROID
|
||||
content/screen.js (content/screen.js)
|
||||
content/runapp.js (content/runapp.js)
|
||||
#endif
|
||||
content/content.css (content/content.css)
|
||||
content/touchcontrols.css (content/touchcontrols.css)
|
||||
|
@ -33,13 +33,12 @@ ActivitiesDialog.prototype = {
|
||||
// activity. The front-end should display a UI to pick one.
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let content = browser.getContentWindow();
|
||||
let event = content.document.createEvent("CustomEvent");
|
||||
event.initCustomEvent("mozChromeEvent", true, true, {
|
||||
let detail = {
|
||||
type: "activity-choice",
|
||||
id: id,
|
||||
name: activity.name,
|
||||
choices: choices
|
||||
});
|
||||
};
|
||||
|
||||
// Listen the resulting choice from the front-end. If there is no choice,
|
||||
// let's return -1, which means the user has cancelled the dialog.
|
||||
@ -51,7 +50,7 @@ ActivitiesDialog.prototype = {
|
||||
activity.callback.handleEvent(evt.detail.value ? evt.detail.value : -1);
|
||||
});
|
||||
|
||||
content.dispatchEvent(event);
|
||||
browser.shell.sendChromeEvent(detail);
|
||||
},
|
||||
|
||||
chooseActivity: function ap_chooseActivity(aName, aActivities, aCallback) {
|
||||
|
@ -58,9 +58,7 @@ ContentPermissionPrompt.prototype = {
|
||||
"id": requestId,
|
||||
"url": request.principal.URI.spec
|
||||
};
|
||||
let event = content.document.createEvent("CustomEvent");
|
||||
event.initCustomEvent("mozChromeEvent", true, true, details);
|
||||
content.dispatchEvent(event);
|
||||
browser.shell.sendChromeEvent(details);
|
||||
},
|
||||
|
||||
classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"),
|
||||
|
@ -11,6 +11,7 @@ const kFormsFrameScript = "chrome://browser/content/forms.js";
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ObjectWrapper.jsm");
|
||||
|
||||
const messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
|
||||
.getService(Ci.nsIChromeFrameMessageManager);
|
||||
@ -103,7 +104,8 @@ MozKeyboard.prototype = {
|
||||
"detail": msg.json
|
||||
};
|
||||
|
||||
let evt = new this._window.CustomEvent("focuschanged", detail);
|
||||
let evt = new this._window.CustomEvent("focuschanged",
|
||||
ObjectWrapper.wrap(detail, this._window));
|
||||
handler.handleEvent(evt);
|
||||
},
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
. $topsrcdir/build/macosx/common
|
||||
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
ac_add_options --enable-codesighs
|
||||
@ -16,7 +18,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j12"
|
||||
|
||||
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
|
||||
ac_add_options --enable-warnings-as-errors
|
||||
ac_add_options --with-ccache
|
||||
|
||||
# B2G Stuff
|
||||
ac_add_options --enable-application=b2g
|
||||
|
17
b2g/config/tooltool-manifests/macosx64/releng.manifest
Normal file
17
b2g/config/tooltool-manifests/macosx64/releng.manifest
Normal file
@ -0,0 +1,17 @@
|
||||
[
|
||||
{
|
||||
"clang_version": "r161022"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 54405078,
|
||||
"digest": "940f02ee8e4a760f52d6fe9cd1dc8dec01abc61b8086d46b4aa7d7292cf7c353a2cec1c9687491ade756ba2654b9e93986123155cb931bd18431fbbfdef671a9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
]
|
@ -1,14 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1344613852000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1345147390000">
|
||||
<emItems>
|
||||
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
|
||||
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
|
||||
</versionRange>
|
||||
@ -21,12 +17,6 @@
|
||||
<versionRange minVersion=" " severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i43" id="supportaccessplugin@gmail.com">
|
||||
</emItem>
|
||||
<emItem blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i107" os="WINNT" id="{ABDE892B-13A8-4d1b-88E6-365A6E755758}">
|
||||
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
|
||||
</versionRange>
|
||||
@ -35,21 +25,6 @@
|
||||
<versionRange minVersion="2.4.6.4" maxVersion="2.4.6.4" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
|
||||
<versionRange minVersion="2.2" maxVersion="2.2">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i98" id="youtubeeing@youtuberie.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
|
||||
<versionRange minVersion="0.1" maxVersion="*">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="9.0a1" maxVersion="9.0" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i65" id="activity@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
@ -58,77 +33,16 @@
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i54" id="applebeegifts@mozilla.doslash.org">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}">
|
||||
<versionRange minVersion="1.0" maxVersion="1.0">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}">
|
||||
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i92" id="play5@vide04flash.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i108" id="{28bfb930-7620-11e1-b0c4-0800200c9a66}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i105" id="{95ff02bc-ffc6-45f0-a5c8-619b8226a9de}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i61" id="youtube@youtube3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
|
||||
</emItem>
|
||||
<emItem blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
|
||||
<versionRange minVersion="2.1" maxVersion="3.3">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
<versionRange minVersion=" " maxVersion="6.9.8">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.7a1pre" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i63" id="youtube@youtuber.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i101" id="{3a12052a-66ef-49db-8c39-e5b0bd5c83fa}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i18" id="msntoolbar@msn.com">
|
||||
<versionRange minVersion=" " maxVersion="6.*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
|
||||
</emItem>
|
||||
<emItem blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}">
|
||||
<versionRange minVersion="0" maxVersion="1.0.8" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
|
||||
<versionRange minVersion="0.1" maxVersion="1.3.328.4" severity="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.7a1pre" maxVersion="*" />
|
||||
</targetApplication>
|
||||
<emItem blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
|
||||
<versionRange minVersion="2.5.0" maxVersion="2.5.0" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i64" id="royal@facebook.com">
|
||||
@ -139,84 +53,43 @@
|
||||
<versionRange minVersion="3.4.1" maxVersion="3.4.1.194" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i97" id="support3_en@adobe122.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
|
||||
<versionRange minVersion="1.2" maxVersion="1.2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com">
|
||||
<versionRange minVersion="1.9.0" maxVersion="1.9.0" severity="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="9.0a1" maxVersion="9.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
|
||||
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
|
||||
<versionRange minVersion="2.5.0" maxVersion="2.5.0" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i83" id="flash@adobee.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i59" id="ghostviewer@youtube2.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i78" id="socialnetworktools@mozilla.doslash.org">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
|
||||
<versionRange minVersion="2.0.3" maxVersion="2.0.3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i51" id="admin@youtubeplayer.com">
|
||||
<emItem blockID="i101" id="{3a12052a-66ef-49db-8c39-e5b0bd5c83fa}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i68" id="flashupdate@adobe.com">
|
||||
<emItem blockID="i5" id="support@daemon-tools.cc">
|
||||
<versionRange minVersion=" " maxVersion="1.0.0.5">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i97" id="support3_en@adobe122.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
|
||||
</emItem>
|
||||
<emItem blockID="i90" id="videoplugin@player.com">
|
||||
<emItem blockID="i11" id="yslow@yahoo-inc.com">
|
||||
<versionRange minVersion="2.0.5" maxVersion="2.0.5">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.5.7" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i91" id="crossriderapp4926@crossrider.com">
|
||||
<versionRange minVersion="0" maxVersion="0.81.43" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i84" id="pink@rosaplugin.info">
|
||||
<emItem blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}">
|
||||
<versionRange minVersion="0.1" maxVersion="14.4.0" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i67" id="youtube2@youtube2.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i60" id="youtb3@youtb3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
<emItem blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
|
||||
<versionRange minVersion="1.1b1" maxVersion="1.1b1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i111" os="WINNT" id="{C3949AC2-4B17-43ee-B4F1-D26B9D42404D}">
|
||||
@ -235,6 +108,225 @@
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i98" id="youtubeeing@youtuberie.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}">
|
||||
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}">
|
||||
<versionRange minVersion="0.1" maxVersion="14.4.0" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
|
||||
<versionRange minVersion="2.0.3" maxVersion="2.0.3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i63" id="youtube@youtuber.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i18" id="msntoolbar@msn.com">
|
||||
<versionRange minVersion=" " maxVersion="6.*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
|
||||
<versionRange minVersion="1.2" maxVersion="1.2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com">
|
||||
<versionRange minVersion="1.9.0" maxVersion="1.9.0" severity="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="9.0a1" maxVersion="9.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i127" id="plugin@youtubeplayer.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i59" id="ghostviewer@youtube2.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i51" id="admin@youtubeplayer.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
|
||||
<versionRange minVersion="0.1" maxVersion="*">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="9.0a1" maxVersion="9.0" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i22" id="ShopperReports@ShopperReports.com">
|
||||
<versionRange minVersion="3.1.22.0" maxVersion="3.1.22.0">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i44" id="sigma@labs.mozilla">
|
||||
</emItem>
|
||||
<emItem blockID="i48" id="admin@youtubespeedup.com">
|
||||
</emItem>
|
||||
<emItem blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i79" id="GifBlock@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
|
||||
<versionRange minVersion="2.2" maxVersion="2.2">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i115" id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
|
||||
</emItem>
|
||||
<emItem blockID="i52" id="ff-ext@youtube">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i43" id="supportaccessplugin@gmail.com">
|
||||
</emItem>
|
||||
<emItem blockID="i54" id="applebeegifts@mozilla.doslash.org">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}">
|
||||
<versionRange minVersion="1.0" maxVersion="1.0">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i92" id="play5@vide04flash.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
|
||||
</emItem>
|
||||
<emItem blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
|
||||
<versionRange minVersion="2.1" maxVersion="3.3">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
<versionRange minVersion=" " maxVersion="6.9.8">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.7a1pre" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
|
||||
</emItem>
|
||||
<emItem blockID="i83" id="flash@adobee.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i104" id="yasd@youasdr3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i76" id="crossriderapp3924@crossrider.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i91" id="crossriderapp4926@crossrider.com">
|
||||
<versionRange minVersion="0" maxVersion="0.81.43" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i67" id="youtube2@youtube2.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i56" id="flash@adobe.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i2" id="fdm_ffext@freedownloadmanager.org">
|
||||
<versionRange minVersion="1.0" maxVersion="1.3.1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
|
||||
<versionRange minVersion=" " maxVersion="8.5">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i12" id="masterfiler@gmail.com">
|
||||
<versionRange severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
|
||||
<versionRange minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i47" id="youtube@youtube2.com">
|
||||
</emItem>
|
||||
<emItem blockID="i103" id="kdrgun@gmail.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i3" id="langpack-vi-VN@firefox.mozilla.org">
|
||||
<versionRange minVersion="2.0" maxVersion="2.0">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
|
||||
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i15" id="personas@christopher.beard">
|
||||
<versionRange minVersion="1.6" maxVersion="1.6">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.6" maxVersion="3.6.*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i108" id="{28bfb930-7620-11e1-b0c4-0800200c9a66}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i61" id="youtube@youtube3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i84" id="pink@rosaplugin.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i60" id="youtb3@youtb3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i23" id="firefox@bandoo.com">
|
||||
<versionRange minVersion="5.0" maxVersion="5.0" severity="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
@ -246,111 +338,11 @@
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i47" id="youtube@youtube2.com">
|
||||
</emItem>
|
||||
<emItem blockID="i22" id="ShopperReports@ShopperReports.com">
|
||||
<versionRange minVersion="3.1.22.0" maxVersion="3.1.22.0">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i2" id="fdm_ffext@freedownloadmanager.org">
|
||||
<versionRange minVersion="1.0" maxVersion="1.3.1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0a1" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i44" id="sigma@labs.mozilla">
|
||||
</emItem>
|
||||
<emItem blockID="i5" id="support@daemon-tools.cc">
|
||||
<versionRange minVersion=" " maxVersion="1.0.0.5">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
|
||||
<versionRange minVersion=" " maxVersion="8.5">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i12" id="masterfiler@gmail.com">
|
||||
<versionRange severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i48" id="admin@youtubespeedup.com">
|
||||
</emItem>
|
||||
<emItem blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
|
||||
<versionRange minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i104" id="yasd@youasdr3.com">
|
||||
<emItem blockID="i90" id="videoplugin@player.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i76" id="crossriderapp3924@crossrider.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i79" id="GifBlock@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i115" id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i56" id="flash@adobe.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i103" id="kdrgun@gmail.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
|
||||
<versionRange minVersion="1.1b1" maxVersion="1.1b1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i3" id="langpack-vi-VN@firefox.mozilla.org">
|
||||
<versionRange minVersion="2.0" maxVersion="2.0">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i73" id="a1g0a9g219d@a1.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i96" id="youtubeee@youtuber3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
|
||||
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i11" id="yslow@yahoo-inc.com">
|
||||
<versionRange minVersion="2.0.5" maxVersion="2.0.5">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.5.7" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i52" id="ff-ext@youtube">
|
||||
<emItem blockID="i68" id="flashupdate@adobe.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
@ -361,10 +353,22 @@
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i15" id="personas@christopher.beard">
|
||||
<versionRange minVersion="1.6" maxVersion="1.6">
|
||||
<emItem blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i73" id="a1g0a9g219d@a1.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i96" id="youtubeee@youtuber3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
|
||||
<versionRange minVersion="0.1" maxVersion="1.3.328.4" severity="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.6" maxVersion="3.6.*" />
|
||||
<versionRange minVersion="3.7a1pre" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
@ -373,6 +377,13 @@
|
||||
</emItems>
|
||||
|
||||
<pluginItems>
|
||||
<pluginItem blockID="p32">
|
||||
<match name="filename" exp="npViewpoint.dll" /> <versionRange >
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p26">
|
||||
<match name="name" exp="^Yahoo Application State Plugin$" /> <match name="description" exp="^Yahoo Application State Plugin$" /> <match name="filename" exp="npYState.dll" /> <versionRange >
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
@ -387,20 +398,6 @@
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p28">
|
||||
<match name="filename" exp="NPFFAddOn.dll" /> </pluginItem>
|
||||
<pluginItem blockID="p31">
|
||||
<match name="filename" exp="NPMySrch.dll" /> </pluginItem>
|
||||
<pluginItem blockID="p32">
|
||||
<match name="filename" exp="npViewpoint.dll" /> <versionRange >
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="3.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p33">
|
||||
<match name="name" exp="[0-6]\.0\.[01]\d{2}\.\d+" /> <match name="filename" exp="npdeploytk.dll" /> <versionRange severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p34">
|
||||
<match name="filename" exp="[Nn][Pp][Jj][Pp][Ii]1[56]0_[0-9]+\.[Dd][Ll][Ll]" /> <versionRange >
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
@ -408,9 +405,22 @@
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p28">
|
||||
<match name="filename" exp="NPFFAddOn.dll" /> </pluginItem>
|
||||
<pluginItem blockID="p31">
|
||||
<match name="filename" exp="NPMySrch.dll" /> </pluginItem>
|
||||
<pluginItem blockID="p33">
|
||||
<match name="name" exp="[0-6]\.0\.[01]\d{2}\.\d+" /> <match name="filename" exp="npdeploytk.dll" /> <versionRange severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p80">
|
||||
<match name="name" exp="\(TM\)" /> <match name="description" exp="[^\d\._]((0(\.\d+(\.\d+([_\.]\d+)?)?)?)|(1\.(([0-5](\.\d+([_\.]\d+)?)?)|(6(\.0([_\.](0?\d|1\d|2\d|30))?)?)|(7(\.0([_\.][0-2])?)?))))([^\d\._]|$)" /> <match name="filename" exp="(npjp2\.dll)|(libnpjp2\.so)" /> <versionRange severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p119">
|
||||
<match name="name" exp="Java\(TM\) Plug-in 1\.(6\.0_(\d|[0-2]\d?|3[0-2])|7\.0(_0?([1-4]))?)([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p125">
|
||||
<match name="name" exp="Java\(TM\) Platform SE ((6( U(\d|([0-2]\d)|3[0-2]))?)|(7(\sU[0-4])?))(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p85">
|
||||
<match name="filename" exp="JavaPlugin2_NPAPI\.plugin" /> <versionRange minVersion="0" maxVersion="13.6.0" severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
@ -426,6 +436,9 @@
|
||||
<pluginItem blockID="p113">
|
||||
<match name="filename" exp="npuplaypc\.dll" /> <versionRange minVersion="0" maxVersion="1.0.0.0" severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p123">
|
||||
<match name="filename" exp="JavaPlugin2_NPAPI\.plugin" /> <versionRange minVersion="0" maxVersion="14.2.0" severity="1"></versionRange>
|
||||
</pluginItem>
|
||||
</pluginItems>
|
||||
|
||||
<gfxItems>
|
||||
|
@ -1128,6 +1128,12 @@ pref("browser.newtab.preload", false);
|
||||
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
|
||||
pref("browser.newtabpage.enabled", true);
|
||||
|
||||
// number of rows of newtab grid
|
||||
pref("browser.newtabpage.rows", 3);
|
||||
|
||||
// number of columns of newtab grid
|
||||
pref("browser.newtabpage.columns", 3);
|
||||
|
||||
// Enable the DOM fullscreen API.
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
||||
|
@ -42,6 +42,10 @@
|
||||
]]></script>
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
#errorPageContainer {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
#errorPageContainer:before {
|
||||
content: url('chrome://browser/content/aboutRobots-icon.png');
|
||||
position: absolute;
|
||||
|
@ -33,10 +33,18 @@ let SocialUI = {
|
||||
observe: function SocialUI_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "social:pref-changed":
|
||||
this.updateToggleCommand();
|
||||
SocialShareButton.updateButtonHiddenState();
|
||||
SocialToolbar.updateButtonHiddenState();
|
||||
SocialSidebar.updateSidebar();
|
||||
// Exceptions here sometimes don't get reported properly, report them
|
||||
// manually :(
|
||||
try {
|
||||
this.updateToggleCommand();
|
||||
SocialShareButton.updateButtonHiddenState();
|
||||
SocialToolbar.updateButtonHiddenState();
|
||||
SocialSidebar.updateSidebar();
|
||||
SocialChatBar.update();
|
||||
} catch (e) {
|
||||
Components.utils.reportError(e);
|
||||
throw e;
|
||||
}
|
||||
break;
|
||||
case "social:ambient-notification-changed":
|
||||
SocialToolbar.updateButton();
|
||||
@ -150,6 +158,27 @@ let SocialUI = {
|
||||
}
|
||||
}
|
||||
|
||||
let SocialChatBar = {
|
||||
get chatbar() {
|
||||
return document.getElementById("pinnedchats");
|
||||
},
|
||||
// Whether the chats can be shown for this window.
|
||||
get canShow() {
|
||||
let docElem = document.documentElement;
|
||||
let chromeless = docElem.getAttribute("disablechrome") ||
|
||||
docElem.getAttribute("chromehidden").indexOf("extrachrome") >= 0;
|
||||
return Social.uiVisible && !chromeless;
|
||||
},
|
||||
newChat: function(aProvider, aURL, aCallback) {
|
||||
if (this.canShow)
|
||||
this.chatbar.newChat(aProvider, aURL, aCallback);
|
||||
},
|
||||
update: function() {
|
||||
if (!this.canShow)
|
||||
this.chatbar.removeAll();
|
||||
}
|
||||
}
|
||||
|
||||
let SocialShareButton = {
|
||||
// Called once, after window load, when the Social.provider object is initialized
|
||||
init: function SSB_init() {
|
||||
@ -253,9 +282,6 @@ var SocialToolbar = {
|
||||
init: function SocialToolbar_init() {
|
||||
document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
|
||||
|
||||
let notifBrowser = document.getElementById("social-notification-browser");
|
||||
notifBrowser.docShell.isAppTab = true;
|
||||
|
||||
let removeItem = document.getElementById("social-remove-menuitem");
|
||||
let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
|
||||
let label = gNavigatorBundle.getFormattedString("social.remove.label",
|
||||
@ -265,7 +291,7 @@ var SocialToolbar = {
|
||||
removeItem.setAttribute("accesskey", accesskey);
|
||||
|
||||
let statusAreaPopup = document.getElementById("social-statusarea-popup");
|
||||
statusAreaPopup.addEventListener("popupshowing", function(e) {
|
||||
statusAreaPopup.addEventListener("popupshown", function(e) {
|
||||
this.button.setAttribute("open", "true");
|
||||
}.bind(this));
|
||||
statusAreaPopup.addEventListener("popuphidden", function(e) {
|
||||
@ -282,6 +308,14 @@ var SocialToolbar = {
|
||||
|
||||
updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
|
||||
this.button.hidden = !Social.uiVisible;
|
||||
if (!Social.provider || !Social.provider.profile || !Social.provider.profile.userName) {
|
||||
["social-notification-box",
|
||||
"social-status-iconbox"].forEach(function removeChildren(parentId) {
|
||||
let parent = document.getElementById(parentId);
|
||||
while(parent.hasChildNodes())
|
||||
parent.removeChild(parent.firstChild);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
updateProfile: function SocialToolbar_updateProfile() {
|
||||
@ -306,42 +340,73 @@ var SocialToolbar = {
|
||||
|
||||
updateButton: function SocialToolbar_updateButton() {
|
||||
this.updateButtonHiddenState();
|
||||
|
||||
let provider = Social.provider;
|
||||
// if there are no ambient icons, we collapse them in the following loop
|
||||
let iconNames = Object.keys(provider.ambientNotificationIcons);
|
||||
let iconBox = document.getElementById("social-status-iconbox");
|
||||
for (var i = 0; i < iconBox.childNodes.length; i++) {
|
||||
let iconContainer = iconBox.childNodes[i];
|
||||
if (i > iconNames.length - 1) {
|
||||
iconContainer.collapsed = true;
|
||||
continue;
|
||||
let notifBox = document.getElementById("social-notification-box");
|
||||
let notifBrowsers = document.createDocumentFragment();
|
||||
let iconContainers = document.createDocumentFragment();
|
||||
|
||||
for each(let name in iconNames) {
|
||||
let icon = provider.ambientNotificationIcons[name];
|
||||
|
||||
let notifBrowserId = "social-status-" + icon.name;
|
||||
let notifBrowser = document.getElementById(notifBrowserId);
|
||||
if (!notifBrowser) {
|
||||
notifBrowser = document.createElement("iframe");
|
||||
notifBrowser.setAttribute("type", "content");
|
||||
notifBrowser.setAttribute("id", notifBrowserId);
|
||||
notifBrowsers.appendChild(notifBrowser);
|
||||
}
|
||||
notifBrowser.setAttribute("origin", provider.origin);
|
||||
if (notifBrowser.getAttribute("src") != icon.contentPanel)
|
||||
notifBrowser.setAttribute("src", icon.contentPanel);
|
||||
|
||||
iconContainer.collapsed = false;
|
||||
let icon = provider.ambientNotificationIcons[iconNames[i]];
|
||||
let iconImage = iconContainer.firstChild;
|
||||
let iconCounter = iconImage.nextSibling;
|
||||
|
||||
iconImage.setAttribute("contentPanel", icon.contentPanel);
|
||||
iconImage.setAttribute("src", icon.iconURL);
|
||||
|
||||
if (iconCounter.firstChild)
|
||||
iconCounter.removeChild(iconCounter.firstChild);
|
||||
|
||||
if (icon.counter) {
|
||||
iconCounter.appendChild(document.createTextNode(icon.counter));
|
||||
iconCounter.collapsed = false;
|
||||
let iconId = "social-notification-icon-" + icon.name;
|
||||
let iconContainer = document.getElementById(iconId);
|
||||
let iconImage, iconCounter;
|
||||
if (iconContainer) {
|
||||
iconImage = iconContainer.getElementsByClassName("social-notification-icon-image")[0];
|
||||
iconCounter = iconContainer.getElementsByClassName("social-notification-icon-counter")[0];
|
||||
} else {
|
||||
iconCounter.collapsed = true;
|
||||
iconContainer = document.createElement("box");
|
||||
iconContainer.setAttribute("id", iconId);
|
||||
iconContainer.classList.add("social-notification-icon-container");
|
||||
iconContainer.addEventListener("click", function (e) { SocialToolbar.showAmbientPopup(iconContainer); }, false);
|
||||
|
||||
iconImage = document.createElement("image");
|
||||
iconImage.classList.add("social-notification-icon-image");
|
||||
iconImage = iconContainer.appendChild(iconImage);
|
||||
|
||||
iconCounter = document.createElement("box");
|
||||
iconCounter.classList.add("social-notification-icon-counter");
|
||||
iconCounter.appendChild(document.createTextNode(""));
|
||||
iconCounter = iconContainer.appendChild(iconCounter);
|
||||
|
||||
iconContainers.appendChild(iconContainer);
|
||||
}
|
||||
if (iconImage.getAttribute("src") != icon.iconURL)
|
||||
iconImage.setAttribute("src", icon.iconURL);
|
||||
iconImage.setAttribute("notifBrowserId", notifBrowserId);
|
||||
|
||||
iconCounter.collapsed = !icon.counter;
|
||||
iconCounter.firstChild.textContent = icon.counter || "";
|
||||
}
|
||||
notifBox.appendChild(notifBrowsers);
|
||||
iconBox.appendChild(iconContainers);
|
||||
|
||||
let browserIter = notifBox.firstElementChild;
|
||||
while (browserIter) {
|
||||
browserIter.docShell.isAppTab = true;
|
||||
browserIter = browserIter.nextElementSibling;
|
||||
}
|
||||
},
|
||||
|
||||
showAmbientPopup: function SocialToolbar_showAmbientPopup(iconContainer) {
|
||||
let iconImage = iconContainer.firstChild;
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
let notifBrowser = document.getElementById("social-notification-browser");
|
||||
let notifBox = document.getElementById("social-notification-box");
|
||||
let notifBrowser = document.getElementById(iconImage.getAttribute("notifBrowserId"));
|
||||
|
||||
panel.hidden = false;
|
||||
|
||||
@ -349,31 +414,59 @@ var SocialToolbar = {
|
||||
// FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
|
||||
// Need to handle dynamic sizing
|
||||
let doc = notifBrowser.contentDocument;
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
// "notif" is an implementation detail that we should get rid of
|
||||
// eventually
|
||||
let body = doc.getElementById("notif") || (doc.body && doc.body.firstChild);
|
||||
if (!body)
|
||||
let body = doc.getElementById("notif") || doc.body;
|
||||
if (!body || !body.firstChild) {
|
||||
return;
|
||||
let h = body.scrollHeight > 0 ? body.scrollHeight : 300;
|
||||
notifBrowser.style.width = body.scrollWidth + "px";
|
||||
notifBrowser.style.height = h + "px";
|
||||
}
|
||||
|
||||
// Clear dimensions on all browsers so the panel size will
|
||||
// only use the selected browser.
|
||||
let browserIter = notifBox.firstElementChild;
|
||||
while (browserIter) {
|
||||
browserIter.hidden = (browserIter != notifBrowser);
|
||||
browserIter = browserIter.nextElementSibling;
|
||||
}
|
||||
|
||||
let [height, width] = [body.firstChild.offsetHeight || 300, 330];
|
||||
notifBrowser.style.width = width + "px";
|
||||
notifBrowser.style.height = height + "px";
|
||||
}
|
||||
|
||||
notifBrowser.addEventListener("DOMContentLoaded", function onload() {
|
||||
notifBrowser.removeEventListener("DOMContentLoaded", onload);
|
||||
sizePanelToContent();
|
||||
});
|
||||
sizePanelToContent();
|
||||
|
||||
function dispatchPanelEvent(name) {
|
||||
let evt = notifBrowser.contentDocument.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(name, true, true, {});
|
||||
notifBrowser.contentDocument.documentElement.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
panel.addEventListener("popuphiding", function onpopuphiding() {
|
||||
panel.removeEventListener("popuphiding", onpopuphiding);
|
||||
// unload the panel
|
||||
SocialToolbar.button.removeAttribute("open");
|
||||
notifBrowser.setAttribute("src", "about:blank");
|
||||
dispatchPanelEvent("socialFrameHide");
|
||||
});
|
||||
|
||||
panel.addEventListener("popupshown", function onpopupshown() {
|
||||
panel.removeEventListener("popupshown", onpopupshown);
|
||||
SocialToolbar.button.setAttribute("open", "true");
|
||||
if (notifBrowser.contentDocument.readyState == "complete") {
|
||||
dispatchPanelEvent("socialFrameShow");
|
||||
} else {
|
||||
// first time load, wait for load and dispatch after load
|
||||
notifBrowser.addEventListener("load", function panelBrowserOnload(e) {
|
||||
notifBrowser.removeEventListener("load", panelBrowserOnload, true);
|
||||
setTimeout(function() {
|
||||
dispatchPanelEvent("socialFrameShow");
|
||||
}, 0);
|
||||
}, true);
|
||||
}
|
||||
});
|
||||
|
||||
notifBrowser.setAttribute("origin", Social.provider.origin);
|
||||
notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
|
||||
this.button.setAttribute("open", "true");
|
||||
panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
|
||||
}
|
||||
}
|
||||
@ -426,8 +519,9 @@ var SocialSidebar = {
|
||||
command.setAttribute("checked", !hideSidebar);
|
||||
|
||||
let sbrowser = document.getElementById("social-sidebar-browser");
|
||||
sbrowser.docShell.isActive = !hideSidebar;
|
||||
if (hideSidebar) {
|
||||
this.dispatchEvent("sidebarhide");
|
||||
this.dispatchEvent("socialFrameHide");
|
||||
// If we're disabled, unload the sidebar content
|
||||
if (!this.canShow) {
|
||||
sbrowser.removeAttribute("origin");
|
||||
@ -442,11 +536,11 @@ var SocialSidebar = {
|
||||
sbrowser.removeEventListener("load", sidebarOnShow);
|
||||
// let load finish, then fire our event
|
||||
setTimeout(function () {
|
||||
SocialSidebar.dispatchEvent("sidebarshow");
|
||||
SocialSidebar.dispatchEvent("socialFrameShow");
|
||||
}, 0);
|
||||
});
|
||||
} else {
|
||||
this.dispatchEvent("sidebarshow");
|
||||
this.dispatchEvent("socialFrameShow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -615,3 +615,12 @@ stack[anonid=browserStack][responsivemode] {
|
||||
stack[anonid=browserStack][responsivemode][notransition] {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
chatbox {
|
||||
-moz-binding: url("chrome://browser/content/socialchat.xml#chatbox");
|
||||
}
|
||||
|
||||
chatbar {
|
||||
-moz-binding: url("chrome://browser/content/socialchat.xml#chatbar");
|
||||
height: 0;
|
||||
}
|
||||
|
@ -3161,6 +3161,52 @@ const DOMLinkHandler = {
|
||||
break;
|
||||
}
|
||||
},
|
||||
getLinkIconURI: function(aLink) {
|
||||
let targetDoc = aLink.ownerDocument;
|
||||
var uri = makeURI(aLink.href, targetDoc.characterSet);
|
||||
|
||||
// Verify that the load of this icon is legal.
|
||||
// Some error or special pages can load their favicon.
|
||||
// To be on the safe side, only allow chrome:// favicons.
|
||||
var isAllowedPage = [
|
||||
/^about:neterror\?/,
|
||||
/^about:blocked\?/,
|
||||
/^about:certerror\?/,
|
||||
/^about:home$/,
|
||||
].some(function (re) re.test(targetDoc.documentURI));
|
||||
|
||||
if (!isAllowedPage || !uri.schemeIs("chrome")) {
|
||||
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Ci.nsIScriptSecurityManager);
|
||||
try {
|
||||
ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri,
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
|
||||
} catch(e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var contentPolicy = Cc["@mozilla.org/layout/content-policy;1"].
|
||||
getService(Ci.nsIContentPolicy);
|
||||
} catch(e) {
|
||||
return null; // Refuse to load if we can't do a security check.
|
||||
}
|
||||
|
||||
// Security says okay, now ask content policy
|
||||
if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
|
||||
uri, targetDoc.documentURIObject,
|
||||
aLink, aLink.type, null)
|
||||
!= Ci.nsIContentPolicy.ACCEPT)
|
||||
return null;
|
||||
|
||||
try {
|
||||
uri.userPass = "";
|
||||
} catch(e) {
|
||||
// some URIs are immutable
|
||||
}
|
||||
return uri;
|
||||
},
|
||||
onLinkAdded: function (event) {
|
||||
var link = event.originalTarget;
|
||||
var rel = link.rel && link.rel.toLowerCase();
|
||||
@ -3194,54 +3240,20 @@ const DOMLinkHandler = {
|
||||
if (!gPrefService.getBoolPref("browser.chrome.site_icons"))
|
||||
break;
|
||||
|
||||
var targetDoc = link.ownerDocument;
|
||||
var uri = makeURI(link.href, targetDoc.characterSet);
|
||||
var uri = this.getLinkIconURI(link);
|
||||
if (!uri)
|
||||
break;
|
||||
|
||||
if (gBrowser.isFailedIcon(uri))
|
||||
break;
|
||||
|
||||
// Verify that the load of this icon is legal.
|
||||
// Some error or special pages can load their favicon.
|
||||
// To be on the safe side, only allow chrome:// favicons.
|
||||
var isAllowedPage = [
|
||||
/^about:neterror\?/,
|
||||
/^about:blocked\?/,
|
||||
/^about:certerror\?/,
|
||||
/^about:home$/,
|
||||
].some(function (re) re.test(targetDoc.documentURI));
|
||||
|
||||
if (!isAllowedPage || !uri.schemeIs("chrome")) {
|
||||
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Ci.nsIScriptSecurityManager);
|
||||
try {
|
||||
ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri,
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
|
||||
} catch(e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var contentPolicy = Cc["@mozilla.org/layout/content-policy;1"].
|
||||
getService(Ci.nsIContentPolicy);
|
||||
} catch(e) {
|
||||
break; // Refuse to load if we can't do a security check.
|
||||
}
|
||||
|
||||
// Security says okay, now ask content policy
|
||||
if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
|
||||
uri, targetDoc.documentURIObject,
|
||||
link, link.type, null)
|
||||
!= Ci.nsIContentPolicy.ACCEPT)
|
||||
break;
|
||||
|
||||
var browserIndex = gBrowser.getBrowserIndexForDocument(targetDoc);
|
||||
var browserIndex = gBrowser.getBrowserIndexForDocument(link.ownerDocument);
|
||||
// no browser? no favicon.
|
||||
if (browserIndex == -1)
|
||||
break;
|
||||
|
||||
let tab = gBrowser.tabs[browserIndex];
|
||||
gBrowser.setIcon(tab, link.href);
|
||||
gBrowser.setIcon(tab, uri.spec);
|
||||
iconAdded = true;
|
||||
}
|
||||
break;
|
||||
|
@ -269,7 +269,7 @@
|
||||
</panel>
|
||||
|
||||
<panel id="social-notification-panel" type="arrow" hidden="true" noautofocus="true">
|
||||
<browser id="social-notification-browser" type="content" flex="1"/>
|
||||
<box id="social-notification-box" flex="1"></box>
|
||||
</panel>
|
||||
|
||||
<menupopup id="inspector-node-popup">
|
||||
@ -685,21 +685,6 @@
|
||||
</menupopup>
|
||||
</button>
|
||||
<hbox id="social-status-iconbox" flex="1">
|
||||
<box class="social-notification-icon-container" collapsed="true"
|
||||
onclick="SocialToolbar.showAmbientPopup(this);">
|
||||
<image class="social-notification-icon-image"/>
|
||||
<box class="social-notification-icon-counter" collapsed="true"/>
|
||||
</box>
|
||||
<box class="social-notification-icon-container" collapsed="true"
|
||||
onclick="SocialToolbar.showAmbientPopup(this);">
|
||||
<image class="social-notification-icon-image"/>
|
||||
<box class="social-notification-icon-counter" collapsed="true"/>
|
||||
</box>
|
||||
<box class="social-notification-icon-container" collapsed="true"
|
||||
onclick="SocialToolbar.showAmbientPopup(this);">
|
||||
<image class="social-notification-icon-image"/>
|
||||
<box class="social-notification-icon-counter" collapsed="true"/>
|
||||
</box>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</toolbaritem>
|
||||
@ -1066,6 +1051,7 @@
|
||||
contentcontextmenu="contentAreaContextMenu"
|
||||
autocompletepopup="PopupAutoComplete"
|
||||
onclick="contentAreaClick(event, false);"/>
|
||||
<chatbar id="pinnedchats" layer="true" mousethrough="always"/>
|
||||
<statuspanel id="statusbar-display" inactive="true"/>
|
||||
</vbox>
|
||||
<splitter id="devtools-side-splitter" hidden="true"/>
|
||||
|
@ -22,17 +22,8 @@ let gGrid = {
|
||||
/**
|
||||
* All cells contained in the grid.
|
||||
*/
|
||||
get cells() {
|
||||
let cells = [];
|
||||
let children = this.node.querySelectorAll(".newtab-cell");
|
||||
for (let i = 0; i < children.length; i++)
|
||||
cells.push(new Cell(this, children[i]));
|
||||
|
||||
// Replace the getter with our cached value.
|
||||
Object.defineProperty(this, "cells", {value: cells, enumerable: true});
|
||||
|
||||
return cells;
|
||||
},
|
||||
_cells: null,
|
||||
get cells() this._cells,
|
||||
|
||||
/**
|
||||
* All sites contained in the grid's cells. Sites may be empty.
|
||||
@ -46,7 +37,7 @@ let gGrid = {
|
||||
init: function Grid_init() {
|
||||
this._node = document.getElementById("newtab-grid");
|
||||
this._createSiteFragment();
|
||||
this._draw();
|
||||
this._render();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -74,8 +65,8 @@ let gGrid = {
|
||||
node.removeChild(child);
|
||||
}, this);
|
||||
|
||||
// Draw the grid again.
|
||||
this._draw();
|
||||
// Render the grid again.
|
||||
this._render();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -92,6 +83,32 @@ let gGrid = {
|
||||
this.node.removeAttribute("locked");
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the newtab grid.
|
||||
*/
|
||||
_renderGrid: function Grid_renderGrid() {
|
||||
let row = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
let cell = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
row.classList.add("newtab-row");
|
||||
cell.classList.add("newtab-cell");
|
||||
|
||||
// Clear the grid
|
||||
this._node.innerHTML = "";
|
||||
|
||||
// Creates the structure of one row
|
||||
for (let i = 0; i < gGridPrefs.gridColumns; i++) {
|
||||
row.appendChild(cell.cloneNode(true));
|
||||
}
|
||||
// Creates the grid
|
||||
for (let j = 0; j < gGridPrefs.gridRows; j++) {
|
||||
this._node.appendChild(row.cloneNode(true));
|
||||
}
|
||||
|
||||
// (Re-)initialize all cells.
|
||||
let cellElements = this.node.querySelectorAll(".newtab-cell");
|
||||
this._cells = [new Cell(this, cell) for (cell of cellElements)];
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the DOM fragment that is re-used when creating sites.
|
||||
*/
|
||||
@ -116,11 +133,10 @@ let gGrid = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Draws the grid, creates all sites and puts them into their cells.
|
||||
* Renders the sites, creates all sites and puts them into their cells.
|
||||
*/
|
||||
_draw: function Grid_draw() {
|
||||
_renderSites: function Grid_renderSites() {
|
||||
let cells = this.cells;
|
||||
|
||||
// Put sites into the cells.
|
||||
let links = gLinks.getLinks();
|
||||
let length = Math.min(links.length, cells.length);
|
||||
@ -129,5 +145,24 @@ let gGrid = {
|
||||
if (links[i])
|
||||
this.createSite(links[i], cells[i]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the grid.
|
||||
*/
|
||||
_render: function Grid_render() {
|
||||
if (this._shouldRenderGrid()) {
|
||||
this._renderGrid();
|
||||
}
|
||||
|
||||
this._renderSites();
|
||||
},
|
||||
|
||||
_shouldRenderGrid : function Grid_shouldRenderGrid() {
|
||||
let rowsLength = this._node.querySelectorAll(".newtab-row").length;
|
||||
let cellsLength = this._node.querySelectorAll(".newtab-cell").length;
|
||||
|
||||
return (rowsLength != gGridPrefs.gridRows ||
|
||||
cellsLength != (gGridPrefs.gridRows * gGridPrefs.gridColumns));
|
||||
}
|
||||
};
|
||||
|
@ -20,7 +20,8 @@ let {
|
||||
allPages: gAllPages,
|
||||
linkChecker: gLinkChecker,
|
||||
pinnedLinks: gPinnedLinks,
|
||||
blockedLinks: gBlockedLinks
|
||||
blockedLinks: gBlockedLinks,
|
||||
gridPrefs: gGridPrefs
|
||||
} = NewTabUtils;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
|
||||
|
@ -26,21 +26,6 @@
|
||||
<div class="newtab-side-margin"/>
|
||||
|
||||
<div id="newtab-grid">
|
||||
<div class="newtab-row">
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
</div>
|
||||
<div class="newtab-row">
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
</div>
|
||||
<div class="newtab-row">
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="newtab-side-margin"/>
|
||||
|
263
browser/base/content/socialchat.xml
Normal file
263
browser/base/content/socialchat.xml
Normal file
@ -0,0 +1,263 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<bindings id="socialChatBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="chatbox">
|
||||
<content orient="vertical" mousethrough="never">
|
||||
<xul:hbox class="chat-titlebar" xbl:inherits="minimized">
|
||||
<xul:image class="chat-status-icon" xbl:inherits="src=image"/>
|
||||
<xul:label class="chat-title" flex="1" xbl:inherits="value=label,crop"/>
|
||||
<xul:toolbarbutton class="chat-toggle-button chat-toolbarbutton"
|
||||
xbl:inherits="minimized"
|
||||
oncommand="document.getBindingParent(this).toggle();"/>
|
||||
<xul:toolbarbutton class="chat-close-button chat-toolbarbutton"
|
||||
oncommand="document.getBindingParent(this).close();"/>
|
||||
</xul:hbox>
|
||||
<xul:iframe anonid="iframe" class="chat-frame" flex="1"
|
||||
xbl:inherits="src,origin,collapsed=minimized" type="content"/>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
<field name="iframe" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "iframe");
|
||||
</field>
|
||||
|
||||
<method name="init">
|
||||
<parameter name="aProvider"/>
|
||||
<parameter name="aURL"/>
|
||||
<parameter name="aCallback"/>
|
||||
<body><![CDATA[
|
||||
this._callback = aCallback;
|
||||
this.setAttribute("origin", aProvider.origin);
|
||||
this.setAttribute("src", aURL);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="close">
|
||||
<body><![CDATA[
|
||||
this.parentNode.remove(this);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="toggle">
|
||||
<body><![CDATA[
|
||||
let type;
|
||||
if (this.getAttribute("minimized") == "true") {
|
||||
this.removeAttribute("minimized");
|
||||
type = "socialFrameShow";
|
||||
} else {
|
||||
this.setAttribute("minimized", "true");
|
||||
type = "socialFrameHide";
|
||||
}
|
||||
// let the chat frame know if it is being shown or hidden
|
||||
let evt = this.iframe.contentDocument.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(type, true, true, {});
|
||||
this.iframe.contentDocument.documentElement.dispatchEvent(evt);
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="focus" phase="capturing">
|
||||
this.parentNode.selectedChat = this;
|
||||
</handler>
|
||||
<handler event="DOMContentLoaded" action="if (this._callback) this._callback(this.iframe.contentWindow);"/>
|
||||
<handler event="DOMTitleChanged" action="this.setAttribute('label', this.iframe.contentDocument.title);"/>
|
||||
<handler event="DOMLinkAdded"><![CDATA[
|
||||
// much of this logic is from DOMLinkHandler in browser.js
|
||||
// this sets the presence icon for a chat user, we simply use favicon style updating
|
||||
let link = event.originalTarget;
|
||||
let rel = link.rel && link.rel.toLowerCase();
|
||||
if (!link || !link.ownerDocument || !rel || !link.href)
|
||||
return;
|
||||
if (link.rel.indexOf("icon") < 0)
|
||||
return;
|
||||
|
||||
let uri = DOMLinkHandler.getLinkIconURI(link);
|
||||
if (!uri)
|
||||
return;
|
||||
|
||||
// we made it this far, use it
|
||||
this.setAttribute('image', uri.spec);
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="chatbar">
|
||||
<content>
|
||||
<xul:hbox align="end" pack="end" anonid="innerbox" class="chatbar-innerbox" mousethrough="always" flex="1">
|
||||
<xul:toolbarbutton anonid="nub" class="chatbar-button" type="menu" collapsed="true" mousethrough="never">
|
||||
<xul:menupopup anonid="nubMenu" oncommand="document.getBindingParent(this).swapChat(event)"/>
|
||||
</xul:toolbarbutton>
|
||||
<xul:spacer flex="1" anonid="spacer" class="chatbar-overflow-spacer"/>
|
||||
<children/>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
|
||||
<field name="innerbox" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "innerbox");
|
||||
</field>
|
||||
|
||||
<field name="menupopup" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "nubMenu");
|
||||
</field>
|
||||
|
||||
<property name="emptyWidth">
|
||||
<getter>
|
||||
return document.getAnonymousElementByAttribute(this, "anonid", "spacer").boxObject.width;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<field name="selectedChat"/>
|
||||
|
||||
<field name="menuitemMap">new WeakMap()</field>
|
||||
|
||||
<property name="firstCollapsedChild">
|
||||
<getter><![CDATA[
|
||||
let child = this.lastChild;
|
||||
while (child && !child.collapsed) {
|
||||
child = child.previousSibling;
|
||||
}
|
||||
return child;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="firstVisibleChild">
|
||||
<getter><![CDATA[
|
||||
let child = this.firstChild;
|
||||
while (child && child.collapsed) {
|
||||
child = child.nextSibling;
|
||||
}
|
||||
return child;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="firstRemovableChild">
|
||||
<getter><![CDATA[
|
||||
let child = this.firstChild;
|
||||
// find the first visible non-focused chatbox, always keep one visible if we
|
||||
// have enough width to do so.
|
||||
while (child &&
|
||||
(child.collapsed || child == this.selectedChat)) {
|
||||
child = child.nextSibling;
|
||||
}
|
||||
if (!child && this.selectedChat) {
|
||||
child = this.selectedChat;
|
||||
}
|
||||
return child;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<method name="resize">
|
||||
<body><![CDATA[
|
||||
let child = this.firstCollapsedChild;
|
||||
if (child && this.emptyWidth > 200) {
|
||||
this.showChat(child);
|
||||
}
|
||||
if (!this.firstCollapsedChild) {
|
||||
window.removeEventListener("resize", this);
|
||||
this.menupopup.parentNode.collapsed = true;
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="handleEvent">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
if (aEvent.type == "resize") {
|
||||
this.resize();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="swapChat">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
let menuitem = aEvent.target;
|
||||
let newChat = menuitem.chat;
|
||||
let oldChat = this.firstVisibleChild;
|
||||
if (oldChat)
|
||||
this.collapseChat(oldChat);
|
||||
if (newChat)
|
||||
this.showChat(newChat);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="collapseChat">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
aChatbox.collapsed = true;
|
||||
let menu = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
|
||||
menu.setAttribute("label", aChatbox.iframe.contentDocument.title);
|
||||
menu.chat = aChatbox;
|
||||
this.menuitemMap.set(aChatbox, menu);
|
||||
this.menupopup.appendChild(menu);
|
||||
this.menupopup.parentNode.collapsed = false;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="showChat">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
let menuitem = this.menuitemMap.get(aChatbox);
|
||||
this.menuitemMap.delete(aChatbox);
|
||||
this.menupopup.removeChild(menuitem);
|
||||
aChatbox.collapsed = false;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="remove">
|
||||
<parameter name="aChatbox"/>
|
||||
<body><![CDATA[
|
||||
if (this.selectedChat == aChatbox) {
|
||||
this.selectedChat = aChatbox.previousSibling ? aChatbox.previousSibling : aChatbox.nextSibling
|
||||
}
|
||||
this.removeChild(aChatbox);
|
||||
this.resize();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="removeAll">
|
||||
<body><![CDATA[
|
||||
while (this.firstChild) {
|
||||
this.removeChild(this.firstChild);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="newChat">
|
||||
<parameter name="aProvider"/>
|
||||
<parameter name="aURL"/>
|
||||
<parameter name="aCallback"/>
|
||||
<body><![CDATA[
|
||||
let cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
|
||||
this.selectedChat = cb;
|
||||
this.appendChild(cb);
|
||||
cb.init(aProvider, aURL, aCallback);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
<handlers>
|
||||
<handler event="overflow"><![CDATA[
|
||||
// make sure we're not getting an overflow from content
|
||||
if (event.originalTarget != this.innerbox)
|
||||
return;
|
||||
|
||||
let hasHidden = this.firstCollapsedChild;
|
||||
let child = this.firstRemovableChild;
|
||||
if (child)
|
||||
this.collapseChat(child);
|
||||
if (!hasHidden) {
|
||||
window.addEventListener("resize", this);
|
||||
}
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
@ -64,6 +64,9 @@ endif
|
||||
|
||||
# browser_pageInfo.js + feed_tab.html is disabled for leaking (bug 767896)
|
||||
|
||||
# browser_social_shareButton.js is disabled for not properly
|
||||
# tearing down the social providers (bug 780010).
|
||||
|
||||
_BROWSER_FILES = \
|
||||
head.js \
|
||||
browser_typeAheadFind.js \
|
||||
@ -89,6 +92,7 @@ _BROWSER_FILES = \
|
||||
browser_bug427559.js \
|
||||
browser_bug432599.js \
|
||||
browser_bug435035.js \
|
||||
browser_bug435325.js \
|
||||
browser_bug441778.js \
|
||||
browser_popupNotification.js \
|
||||
browser_bug455852.js \
|
||||
@ -156,7 +160,6 @@ _BROWSER_FILES = \
|
||||
browser_bug749738.js \
|
||||
browser_bug763468.js \
|
||||
browser_bug767836.js \
|
||||
browser_social_shareButton.js \
|
||||
browser_canonizeURL.js \
|
||||
browser_customize.js \
|
||||
browser_findbarClose.js \
|
||||
@ -261,8 +264,11 @@ _BROWSER_FILES = \
|
||||
browser_social_toolbar.js \
|
||||
browser_social_sidebar.js \
|
||||
browser_social_mozSocial_API.js \
|
||||
browser_social_isVisible.js \
|
||||
browser_social_chatwindow.js \
|
||||
social_panel.html \
|
||||
social_sidebar.html \
|
||||
social_chat.html \
|
||||
social_window.html \
|
||||
social_worker.js \
|
||||
$(NULL)
|
||||
|
@ -2,7 +2,6 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Ensure that clicking the button in the Offline mode neterror page makes the browser go online. See bug 435325. */
|
||||
/* TEST_PATH=docshell/test/browser/browser_bug435325.js make -C $(OBJDIR) mochitest-browser-chrome */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
@ -34,9 +33,8 @@ function checkPage() {
|
||||
"The error page has got a #errorTryAgain element");
|
||||
gBrowser.contentDocument.getElementById("errorTryAgain").click();
|
||||
|
||||
ok(!Services.io.offline, "After clicking the Try Again button, we're back "
|
||||
+" online. This depends on Components.interfaces.nsIDOMWindowUtils being "
|
||||
+"available from untrusted content (bug 435325).");
|
||||
ok(!Services.io.offline, "After clicking the Try Again button, we're back " +
|
||||
"online.");
|
||||
|
||||
finish();
|
||||
}
|
94
browser/base/content/test/browser_social_chatwindow.js
Normal file
94
browser/base/content/test/browser_social_chatwindow.js
Normal file
@ -0,0 +1,94 @@
|
||||
/* 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/. */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
ok(chats.children.length == 0, "no chatty children left behind");
|
||||
finishcb();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testOpenCloseChat: function(next) {
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-sidebar-message":
|
||||
port.postMessage({topic: "test-chatbox-open"});
|
||||
break;
|
||||
case "got-chatbox-visibility":
|
||||
if (e.data.result == "hidden") {
|
||||
ok(true, "chatbox got minimized");
|
||||
chats.selectedChat.toggle();
|
||||
} else if (e.data.result == "shown") {
|
||||
ok(true, "chatbox got shown");
|
||||
// close it now
|
||||
let iframe = chats.selectedChat.iframe;
|
||||
iframe.addEventListener("unload", function chatUnload() {
|
||||
iframe.removeEventListener("unload", chatUnload, true);
|
||||
ok(true, "got chatbox unload on close");
|
||||
next();
|
||||
}, true);
|
||||
chats.selectedChat.close();
|
||||
}
|
||||
break;
|
||||
case "got-chatbox-message":
|
||||
ok(true, "got chatbox message");
|
||||
ok(e.data.result == "ok", "got chatbox windowRef result: "+e.data.result);
|
||||
chats.selectedChat.toggle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
},
|
||||
testManyChats: function(next) {
|
||||
// open enough chats to overflow the window, then check
|
||||
// if the menupopup is visible
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
let width = document.documentElement.boxObject.width;
|
||||
let numToOpen = (width / 200) + 1;
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-chatbox-message":
|
||||
numToOpen--;
|
||||
if (numToOpen >= 0) {
|
||||
// we're waiting for all to open
|
||||
ok(true, "got a chat window opened");
|
||||
break;
|
||||
}
|
||||
// close our chats now
|
||||
let chats = document.getElementById("pinnedchats");
|
||||
ok(!chats.menupopup.parentNode.collapsed, "menu selection is visible");
|
||||
while (chats.selectedChat) {
|
||||
chats.selectedChat.close();
|
||||
}
|
||||
ok(!chats.selectedChat, "chats are all closed");
|
||||
next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
let num = numToOpen;
|
||||
while (num-- > 0) {
|
||||
port.postMessage({topic: "test-chatbox-open"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
62
browser/base/content/test/browser_social_isVisible.js
Normal file
62
browser/base/content/test/browser_social_isVisible.js
Normal file
@ -0,0 +1,62 @@
|
||||
/* 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/. */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
runSocialTests(tests, undefined, undefined, finishcb);
|
||||
});
|
||||
}
|
||||
|
||||
var tests = {
|
||||
testSidebarMessage: function(next) {
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-init"});
|
||||
Social.provider.port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-sidebar-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got sidebar message");
|
||||
next();
|
||||
break;
|
||||
}
|
||||
};
|
||||
},
|
||||
testIsVisible: function(next) {
|
||||
let port = Social.provider.port;
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-isVisible-response":
|
||||
is(e.data.result, true, "Sidebar should be visible by default");
|
||||
Social.toggleSidebar();
|
||||
next();
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-isVisible"});
|
||||
},
|
||||
testIsNotVisible: function(next) {
|
||||
let port = Social.provider.port;
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-isVisible-response":
|
||||
is(e.data.result, false, "Sidebar should be hidden");
|
||||
Services.prefs.clearUserPref("social.sidebar.open");
|
||||
next();
|
||||
}
|
||||
};
|
||||
port.postMessage({topic: "test-isVisible"});
|
||||
}
|
||||
}
|
@ -7,9 +7,9 @@ function test() {
|
||||
|
||||
let manifest = { // normal provider
|
||||
name: "provider 1",
|
||||
origin: "http://example.com",
|
||||
sidebarURL: "http://example.com/browser/browser/base/content/test/social_sidebar.html",
|
||||
workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function (finishcb) {
|
||||
@ -29,7 +29,7 @@ var tests = {
|
||||
|
||||
function triggerIconPanel() {
|
||||
let statusIcons = document.getElementById("social-status-iconbox");
|
||||
ok(!statusIcons.firstChild.collapsed, "status icon is visible");
|
||||
ok(!statusIcons.firstChild.hidden, "status icon is visible");
|
||||
// Click the button to trigger its contentPanel
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
|
||||
@ -37,20 +37,21 @@ var tests = {
|
||||
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-init"});
|
||||
Social.provider.port.onmessage = function (e) {
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-panel-message":
|
||||
ok(true, "got panel message");
|
||||
// Wait for the panel to close before ending the test
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.addEventListener("popuphidden", function hiddenListener() {
|
||||
panel.removeEventListener("popuphidden", hiddenListener);
|
||||
next();
|
||||
});
|
||||
panel.hidePopup();
|
||||
break;
|
||||
case "got-social-panel-visibility":
|
||||
if (e.data.result == "shown") {
|
||||
ok(true, "panel shown");
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.hidePopup();
|
||||
} else if (e.data.result == "hidden") {
|
||||
ok(true, "panel hidden");
|
||||
next();
|
||||
}
|
||||
case "got-sidebar-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got sidebar message");
|
||||
@ -59,6 +60,7 @@ var tests = {
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "test-init"});
|
||||
|
||||
// Our worker sets up ambient notification at the same time as it responds to
|
||||
// the workerAPI initialization. If it's already initialized, we can
|
||||
|
@ -38,13 +38,13 @@ function doTest(finishcb) {
|
||||
ok(!command.hidden, "toggle command should be visible");
|
||||
checkShown(true);
|
||||
|
||||
browser.addEventListener("sidebarhide", function sidebarhide() {
|
||||
browser.removeEventListener("sidebarhide", sidebarhide);
|
||||
browser.addEventListener("socialFrameHide", function sidebarhide() {
|
||||
browser.removeEventListener("socialFrameHide", sidebarhide);
|
||||
|
||||
checkShown(false);
|
||||
|
||||
browser.addEventListener("sidebarshow", function sidebarshow() {
|
||||
browser.removeEventListener("sidebarshow", sidebarshow);
|
||||
browser.addEventListener("socialFrameShow", function sidebarshow() {
|
||||
browser.removeEventListener("socialFrameShow", sidebarshow);
|
||||
|
||||
checkShown(true);
|
||||
|
||||
|
@ -62,7 +62,7 @@ var tests = {
|
||||
ok(userButton.hidden, "username is not visible");
|
||||
let ambience = document.getElementById("social-status-iconbox").firstChild;
|
||||
while (ambience) {
|
||||
ok(ambience.collapsed, "ambient icon is collapsed");
|
||||
ok(ambience.collapsed, "ambient icon (" + ambience.id + ") is collapsed");
|
||||
ambience = ambience.nextSibling;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ _BROWSER_FILES = \
|
||||
browser_newtab_bug725996.js \
|
||||
browser_newtab_bug734043.js \
|
||||
browser_newtab_bug735987.js \
|
||||
browser_newtab_bug752841.js \
|
||||
browser_newtab_bug765628.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
53
browser/base/content/test/newtab/browser_newtab_bug752841.js
Normal file
53
browser/base/content/test/newtab/browser_newtab_bug752841.js
Normal file
@ -0,0 +1,53 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
|
||||
const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
|
||||
|
||||
function runTests() {
|
||||
let testValues = [
|
||||
{row: 0, column: 0},
|
||||
{row: -1, column: -1},
|
||||
{row: -1, column: 0},
|
||||
{row: 0, column: -1},
|
||||
{row: 2, column: 4},
|
||||
{row: 2, column: 5},
|
||||
];
|
||||
|
||||
// Expected length of grid
|
||||
let expectedValues = [1, 1, 1, 1, 8, 10];
|
||||
|
||||
// Values before setting new pref values (9 is the default value -> 3 x 3)
|
||||
let previousValues = [9, 1, 1, 1, 1, 8];
|
||||
|
||||
let existingTab, existingTabGridLength, newTab, newTabGridLength;
|
||||
yield addNewTabPageTab();
|
||||
existingTab = gBrowser.selectedTab;
|
||||
|
||||
for (let i = 0; i < expectedValues.length; i++) {
|
||||
gBrowser.selectedTab = existingTab;
|
||||
existingTabGridLength = getGrid().cells.length;
|
||||
is(existingTabGridLength, previousValues[i],
|
||||
"Grid length of existing page before update is correctly.");
|
||||
|
||||
Services.prefs.setIntPref(PREF_NEWTAB_ROWS, testValues[i].row);
|
||||
Services.prefs.setIntPref(PREF_NEWTAB_COLUMNS, testValues[i].column);
|
||||
|
||||
existingTabGridLength = getGrid().cells.length;
|
||||
is(existingTabGridLength, expectedValues[i],
|
||||
"Existing page grid is updated correctly.");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
newTab = gBrowser.selectedTab;
|
||||
newTabGridLength = getGrid().cells.length;
|
||||
is(newTabGridLength, expectedValues[i],
|
||||
"New page grid is updated correctly.");
|
||||
|
||||
gBrowser.removeTab(newTab);
|
||||
}
|
||||
|
||||
gBrowser.removeTab(existingTab);
|
||||
|
||||
Services.prefs.clearUserPref(PREF_NEWTAB_ROWS);
|
||||
Services.prefs.clearUserPref(PREF_NEWTAB_COLUMNS);
|
||||
}
|
22
browser/base/content/test/social_chat.html
Normal file
22
browser/base/content/test/social_chat.html
Normal file
@ -0,0 +1,22 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "chatbox-message", result: "ok"});
|
||||
}
|
||||
window.addEventListener("socialFrameShow", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "chatbox-visibility", result: "shown"});
|
||||
}, false);
|
||||
window.addEventListener("socialFrameHide", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "chatbox-visibility", result: "hidden"});
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<p>This is a test social chat window.</p>
|
||||
</body>
|
||||
</html>
|
@ -6,6 +6,14 @@
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "panel-message", result: "ok"});
|
||||
}
|
||||
window.addEventListener("socialFrameShow", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "status-panel-visibility", result: "shown"});
|
||||
}, false);
|
||||
window.addEventListener("socialFrameHide", function(e) {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "status-panel-visibility", result: "hidden"});
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
|
@ -8,6 +8,11 @@
|
||||
port.onmessage = function(e) {
|
||||
var topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-chatbox-open":
|
||||
navigator.mozSocial.openChatWindow("social_chat.html", function(chatwin) {
|
||||
port.postMessage({topic: "chatbox-opened", result: chatwin ? "ok" : "failed"});
|
||||
});
|
||||
break;
|
||||
case "test-service-window":
|
||||
win = navigator.mozSocial.openServiceWindow("social_window.html", "test-service-window", "width=300,height=300");
|
||||
break;
|
||||
@ -28,6 +33,9 @@
|
||||
}, false)
|
||||
win.close();
|
||||
break;
|
||||
case "test-isVisible":
|
||||
port.postMessage({topic: "test-isVisible-response", result: navigator.mozSocial.isVisible});
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "sidebar-message", result: "ok"});
|
||||
|
@ -39,6 +39,18 @@ onconnect = function(e) {
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-panel-message"});
|
||||
break;
|
||||
case "status-panel-visibility":
|
||||
testPort.postMessage({topic:"got-social-panel-visibility", result: event.data.result });
|
||||
break;
|
||||
case "test-chatbox-open":
|
||||
sidebarPort.postMessage({topic:"test-chatbox-open"});
|
||||
break;
|
||||
case "chatbox-message":
|
||||
testPort.postMessage({topic:"got-chatbox-message", result: event.data.result});
|
||||
break;
|
||||
case "chatbox-visibility":
|
||||
testPort.postMessage({topic:"got-chatbox-visibility", result: event.data.result});
|
||||
break;
|
||||
case "social.initialize":
|
||||
// This is the workerAPI port, respond and set up a notification icon.
|
||||
port.postMessage({topic: "social.initialize-response"});
|
||||
@ -49,11 +61,17 @@ onconnect = function(e) {
|
||||
let icon = {
|
||||
name: "testIcon",
|
||||
iconURL: "chrome://branding/content/icon48.png",
|
||||
contentPanel: "http://example.com/browser/browser/base/content/test/social_panel.html",
|
||||
contentPanel: "https://example.com/browser/browser/base/content/test/social_panel.html",
|
||||
counter: 1
|
||||
};
|
||||
port.postMessage({topic: "social.ambient-notification", data: icon});
|
||||
break;
|
||||
case "test-isVisible":
|
||||
sidebarPort.postMessage({topic: "test-isVisible"});
|
||||
break;
|
||||
case "test-isVisible-response":
|
||||
testPort.postMessage({topic: "got-isVisible-response", result: event.data.result});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +102,7 @@ browser.jar:
|
||||
content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul)
|
||||
#endif
|
||||
content/browser/social-icon.png (content/social-icon.png)
|
||||
content/browser/socialchat.xml (content/socialchat.xml)
|
||||
# the following files are browser-specific overrides
|
||||
* content/browser/license.html (/toolkit/content/license.html)
|
||||
% override chrome://global/content/license.html chrome://browser/content/license.html
|
||||
|
@ -285,7 +285,7 @@ FeedConverter.prototype = {
|
||||
// getResponseHeader.
|
||||
if (!httpChannel.requestSucceeded) {
|
||||
// Just give up, but don't forget to cancel the channel first!
|
||||
request.cancel(0x804b0002); // NS_BINDING_ABORTED
|
||||
request.cancel(Cr.NS_BINDING_ABORTED);
|
||||
return;
|
||||
}
|
||||
var noSniff = httpChannel.getResponseHeader("X-Moz-Is-Feed");
|
||||
|
@ -60,11 +60,6 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_463206.js \
|
||||
browser_463206_sample.html \
|
||||
browser_464199.js \
|
||||
browser_464620_a.js \
|
||||
browser_464620_a.html \
|
||||
browser_464620_b.js \
|
||||
browser_464620_b.html \
|
||||
browser_464620_xd.html \
|
||||
browser_465215.js \
|
||||
browser_465223.js \
|
||||
browser_466937.js \
|
||||
@ -136,6 +131,20 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_739805.js \
|
||||
$(NULL)
|
||||
|
||||
# Disabled on Windows for frequent intermittent failures
|
||||
ifneq ($(OS_ARCH), WINNT)
|
||||
MOCHITEST_FILES += \
|
||||
browser_464620_a.js \
|
||||
browser_464620_a.html \
|
||||
browser_464620_b.js \
|
||||
browser_464620_b.html \
|
||||
browser_464620_xd.html \
|
||||
$(NULL)
|
||||
else
|
||||
$(warning browser_464620_a.js is disabled on Windows for intermittent failures. Bug 552424)
|
||||
$(warning browser_464620_b.js is disabled on Windows for intermittent failures. Bug 552424)
|
||||
endif
|
||||
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_597071.js \
|
||||
|
@ -3,7 +3,6 @@
|
||||
- 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/. -->
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/orion.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/debugger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/debugger.css" type="text/css"?>
|
||||
|
@ -909,48 +909,63 @@ function JSPropertyProvider(aScope, aInputValue)
|
||||
return null;
|
||||
}
|
||||
|
||||
let properties = completionPart.split(".");
|
||||
let matchProp;
|
||||
if (properties.length > 1) {
|
||||
matchProp = properties.pop().trimLeft();
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
let prop = properties[i].trim();
|
||||
if (!prop) {
|
||||
return null;
|
||||
}
|
||||
let matches = null;
|
||||
let matchProp = "";
|
||||
|
||||
// If obj is undefined or null (which is what "== null" does),
|
||||
// then there is no chance to run completion on it. Exit here.
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
let lastDot = completionPart.lastIndexOf(".");
|
||||
if (lastDot > 0 &&
|
||||
(completionPart[0] == "'" || completionPart[0] == '"') &&
|
||||
completionPart[lastDot - 1] == completionPart[0]) {
|
||||
// We are completing a string literal.
|
||||
obj = obj.String.prototype;
|
||||
matchProp = completionPart.slice(lastDot + 1);
|
||||
|
||||
// Check if prop is a getter function on obj. Functions can change other
|
||||
// stuff so we can't execute them to get the next object. Stop here.
|
||||
if (WCU.isNonNativeGetter(obj, prop)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
obj = obj[prop];
|
||||
}
|
||||
catch (ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
matchProp = properties[0].trimLeft();
|
||||
}
|
||||
// We are completing a variable / a property lookup.
|
||||
|
||||
// If obj is undefined or null (which is what "== null" does),
|
||||
// then there is no chance to run completion on it. Exit here.
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
let properties = completionPart.split(".");
|
||||
if (properties.length > 1) {
|
||||
matchProp = properties.pop().trimLeft();
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
let prop = properties[i].trim();
|
||||
if (!prop) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip Iterators and Generators.
|
||||
if (WCU.isIteratorOrGenerator(obj)) {
|
||||
return null;
|
||||
// If obj is undefined or null (which is what "== null" does),
|
||||
// then there is no chance to run completion on it. Exit here.
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if prop is a getter function on obj. Functions can change other
|
||||
// stuff so we can't execute them to get the next object. Stop here.
|
||||
if (WCU.isNonNativeGetter(obj, prop)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
obj = obj[prop];
|
||||
}
|
||||
catch (ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
matchProp = properties[0].trimLeft();
|
||||
}
|
||||
|
||||
// If obj is undefined or null (which is what "== null" does),
|
||||
// then there is no chance to run completion on it. Exit here.
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip Iterators and Generators.
|
||||
if (WCU.isIteratorOrGenerator(obj)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
let matches = Object.keys(getMatchedProps(obj, {matchProp:matchProp}));
|
||||
|
@ -105,6 +105,13 @@ function testCompletion(hud) {
|
||||
|
||||
is(jsterm.completeNode.value, " ice", "non-object completion");
|
||||
|
||||
// Test string literal autocompletion.
|
||||
input.value = "'Asimov'.sl";
|
||||
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
|
||||
yield;
|
||||
|
||||
is(jsterm.completeNode.value, " ice", "string literal completion");
|
||||
|
||||
testDriver = jsterm = input = null;
|
||||
executeSoon(finishTest);
|
||||
yield;
|
||||
|
@ -706,6 +706,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
||||
@BINPATH@/webapprt/components/DirectoryProvider.js
|
||||
@BINPATH@/webapprt/components/components.manifest
|
||||
@BINPATH@/webapprt/defaults/preferences/prefs.js
|
||||
@BINPATH@/webapprt/modules/Startup.jsm
|
||||
@BINPATH@/webapprt/modules/WebappRT.jsm
|
||||
@BINPATH@/webapprt/modules/WebappsHandler.jsm
|
||||
#endif
|
||||
|
@ -358,6 +358,9 @@ webapps.install.accesskey = I
|
||||
#LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
|
||||
webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
|
||||
webapps.install.success = Application Installed
|
||||
# LOCALIZATION NOTE (webapps.uninstall.notification): %S will be replaced with the name of the uninstalled web app
|
||||
webapps.uninstall.notification = %S has been uninstalled from your computer.
|
||||
webapps.uninstall.label = Uninstall App
|
||||
|
||||
# Telemetry opt-out prompt for Aurora and Nightly
|
||||
# LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
|
||||
|
@ -24,6 +24,12 @@ XPCOMUtils.defineLazyGetter(this, "gPrincipal", function () {
|
||||
// The preference that tells whether this feature is enabled.
|
||||
const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
|
||||
|
||||
// The preference that tells the number of rows of the newtab grid.
|
||||
const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
|
||||
|
||||
// The preference that tells the number of columns of the newtab grid.
|
||||
const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
|
||||
|
||||
// The maximum number of results we want to retrieve from history.
|
||||
const HISTORY_RESULTS_LIMIT = 100;
|
||||
|
||||
@ -183,6 +189,60 @@ let AllPages = {
|
||||
Ci.nsISupportsWeakReference])
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton that keeps Grid preferences
|
||||
*/
|
||||
let GridPrefs = {
|
||||
/**
|
||||
* Cached value that tells the number of rows of newtab grid.
|
||||
*/
|
||||
_gridRows: null,
|
||||
get gridRows() {
|
||||
if (!this._gridRows) {
|
||||
this._gridRows = Math.max(1, Services.prefs.getIntPref(PREF_NEWTAB_ROWS));
|
||||
}
|
||||
|
||||
return this._gridRows;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cached value that tells the number of columns of newtab grid.
|
||||
*/
|
||||
_gridColumns: null,
|
||||
get gridColumns() {
|
||||
if (!this._gridColumns) {
|
||||
this._gridColumns = Math.max(1, Services.prefs.getIntPref(PREF_NEWTAB_COLUMNS));
|
||||
}
|
||||
|
||||
return this._gridColumns;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Initializes object. Adds a preference observer
|
||||
*/
|
||||
init: function GridPrefs_init() {
|
||||
Services.prefs.addObserver(PREF_NEWTAB_ROWS, this, false);
|
||||
Services.prefs.addObserver(PREF_NEWTAB_COLUMNS, this, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements the nsIObserver interface to get notified when the preference
|
||||
* value changes.
|
||||
*/
|
||||
observe: function GridPrefs_observe(aSubject, aTopic, aData) {
|
||||
if (aData == PREF_NEWTAB_ROWS) {
|
||||
this._gridRows = null;
|
||||
} else {
|
||||
this._gridColumns = null;
|
||||
}
|
||||
|
||||
AllPages.update();
|
||||
}
|
||||
};
|
||||
|
||||
GridPrefs.init();
|
||||
|
||||
/**
|
||||
* Singleton that keeps track of all pinned links and their positions in the
|
||||
* grid.
|
||||
@ -606,5 +666,6 @@ let NewTabUtils = {
|
||||
allPages: AllPages,
|
||||
linkChecker: LinkChecker,
|
||||
pinnedLinks: PinnedLinks,
|
||||
blockedLinks: BlockedLinks
|
||||
blockedLinks: BlockedLinks,
|
||||
gridPrefs: GridPrefs
|
||||
};
|
||||
|
@ -2748,3 +2748,126 @@ stack[anonid=browserStack][responsivemode] {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
|
||||
.chat-status-icon {
|
||||
max-height: 16px;
|
||||
max-width: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.chat-toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.chat-toolbarbutton > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chat-close-button {
|
||||
list-style-image: url("chrome://global/skin/icons/close.png");
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
.chat-close-button:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.chat-close-button:hover:active {
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
|
||||
.chat-toggle-button {
|
||||
/* XXX get a real image for this */
|
||||
list-style-image: url("chrome://global/skin/icons/checkbox.png");
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.chat-toggle-button:hover {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
.chat-toggle-button[minimized="true"] {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
.chat-toggle-button[minimized="true"]:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.chat-title {
|
||||
font-weight: bold;
|
||||
color: -moz-dialogtext;
|
||||
}
|
||||
|
||||
.chat-titlebar {
|
||||
background-image: linear-gradient(white, #ddd);
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
border: none;
|
||||
border-bottom: 1px solid gray;
|
||||
}
|
||||
|
||||
.chat-titlebar[minimized="true"] {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.chat-frame {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chatbar-button {
|
||||
/* XXX get a real image for this */
|
||||
list-style-image: url("chrome://browser/skin/social/social.png");
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
height: 21px;
|
||||
width: 21px;
|
||||
border-top: 1px solid gray;
|
||||
-moz-border-end: 1px solid gray;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"],
|
||||
.chatbar-button:active:hover {
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
/* toolbarbutton-icon */
|
||||
.chatbar-button > .toolbarbutton-text,
|
||||
.chatbar-button > .toolbarbutton-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chatbar-innerbox {
|
||||
background: transparent;
|
||||
margin: -200px -1px 0 -1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
chatbar > chatbox {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
background-color: white;
|
||||
border: 1px solid gray;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
chatbar > chatbox[minimized="true"] {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
chatbar > chatbox + chatbox {
|
||||
-moz-margin-start: -1px;
|
||||
}
|
||||
|
@ -3519,3 +3519,129 @@ stack[anonid=browserStack][responsivemode] {
|
||||
}
|
||||
|
||||
/* === end of social toolbar panels === */
|
||||
|
||||
|
||||
.chat-status-icon {
|
||||
max-height: 16px;
|
||||
max-width: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.chat-toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.chat-toolbarbutton > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chat-close-button {
|
||||
list-style-image: url("chrome://global/skin/icons/close.png");
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
.chat-close-button:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.chat-close-button:hover:active {
|
||||
-moz-image-region: rect(0, 48px, 16px, 32px);
|
||||
}
|
||||
|
||||
|
||||
.chat-toggle-button {
|
||||
/* XXX get a real image for this */
|
||||
list-style-image: url("chrome://global/skin/icons/checkbox.png");
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.chat-toggle-button:hover {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
.chat-toggle-button[minimized="true"] {
|
||||
-moz-image-region: rect(0, 16px, 16px, 0);
|
||||
}
|
||||
|
||||
.chat-toggle-button[minimized="true"]:hover {
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
.chat-title {
|
||||
font-weight: bold;
|
||||
color: -moz-dialogtext;
|
||||
}
|
||||
|
||||
.chat-titlebar {
|
||||
background-image: linear-gradient(white, #ddd);
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
border: none;
|
||||
border-bottom: 1px solid #404040;
|
||||
}
|
||||
|
||||
.chat-titlebar[minimized="true"] {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.chat-frame {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chatbar-button {
|
||||
/* XXX get a real image for this */
|
||||
background-image: linear-gradient(white, #ddd);
|
||||
list-style-image: url("chrome://browser/skin/social/social.png");
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
height: 21px;
|
||||
width: 21px;
|
||||
border-top: 1px solid #404040;
|
||||
-moz-border-end: 1px solid #404040;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"],
|
||||
.chatbar-button:active:hover {
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
/* toolbarbutton-icon */
|
||||
.chatbar-button > .toolbarbutton-text,
|
||||
.chatbar-button > .toolbarbutton-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chatbar-innerbox {
|
||||
background: transparent;
|
||||
margin: -200px -1px 0 -1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
chatbar > chatbox {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
background-color: white;
|
||||
border: 1px solid #404040;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
chatbar > chatbox[minimized="true"] {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
chatbar > chatbox + chatbox {
|
||||
-moz-margin-start: -1px;
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,12 @@
|
||||
.menu-iconic-accel {
|
||||
color: graytext;
|
||||
}
|
||||
|
||||
.chatbar-button,
|
||||
chatbar > chatbox {
|
||||
border-color: #A9B7C9;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (-moz-windows-compositor) {
|
||||
|
@ -3450,3 +3450,136 @@ stack[anonid=browserStack][responsivemode] {
|
||||
max-height: 600px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
|
||||
.chat-status-icon {
|
||||
max-height: 16px;
|
||||
max-width: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.chat-toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.chat-toolbarbutton > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chat-close-button {
|
||||
list-style-image: url("chrome://global/skin/icons/Close.gif");
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.chat-close-button:hover {
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.chat-close-button:hover:active {
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
|
||||
.chat-toggle-button {
|
||||
/* XXX get a real image for this */
|
||||
list-style-image: url("chrome://global/skin/icons/expand.png");
|
||||
}
|
||||
|
||||
.chat-toggle-button:hover {
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.chat-toggle-button[minimized="true"] {
|
||||
list-style-image: url("chrome://global/skin/icons/collapse.png");
|
||||
}
|
||||
|
||||
.chat-toggle-button[minimized="true"]:hover {
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.chat-title {
|
||||
font-weight: bold;
|
||||
color: -moz-dialogtext;
|
||||
}
|
||||
|
||||
.chat-titlebar {
|
||||
background-image: linear-gradient(white, #ddd);
|
||||
height: 20px;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
border: none;
|
||||
border-bottom: 1px solid gray;
|
||||
}
|
||||
|
||||
.chat-titlebar[minimized="true"] {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.chat-frame {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chatbar-button {
|
||||
/* XXX get a real image for this */
|
||||
-moz-appearance: none;
|
||||
list-style-image: url("chrome://browser/skin/social/social.png");
|
||||
background-image: linear-gradient(white, #ddd);
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
height: 21px;
|
||||
width: 21px;
|
||||
border-top: 1px solid gray;
|
||||
-moz-border-end: 1px solid gray;
|
||||
}
|
||||
|
||||
.chatbar-button > .button-box > .box-inherit > .button-icon {
|
||||
max-height: 16px;
|
||||
max-width: 16px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.chatbar-button[open="true"],
|
||||
.chatbar-button:hover,
|
||||
.chatbar-button:active:hover {
|
||||
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
/* toolbarbutton-icon */
|
||||
.chatbar-button > .toolbarbutton-text,
|
||||
.chatbar-button > .toolbarbutton-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chatbar-innerbox {
|
||||
background: transparent;
|
||||
margin: -200px -1px 0 -1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
chatbar > chatbox {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
background-color: white;
|
||||
border: 1px solid gray;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
chatbar > chatbox[minimized="true"] {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
chatbar > chatbox + chatbox {
|
||||
-moz-margin-start: -1px;
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,11 @@ if test "$CLANG_CXX"; then
|
||||
## returned by C functions. This is possible because we use knowledge about the ABI
|
||||
## to typedef it to a C type with the same layout when the headers are included
|
||||
## from C.
|
||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
|
||||
##
|
||||
## mismatched-tags is disabled (bug 780474) mostly because it's useless.
|
||||
## Worse, it's not supported by gcc, so it will cause tryserver bustage
|
||||
## without any easy way for non-Clang users to check for it.
|
||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-mismatched-tags"
|
||||
fi
|
||||
|
||||
if test "$GNU_CC"; then
|
||||
|
@ -74,6 +74,8 @@ dnl We're going to need [ ] for python syntax.
|
||||
changequote(<<<, >>>)dnl
|
||||
echo creating $CONFIG_STATUS
|
||||
|
||||
extra_python_path=${COMM_BUILD:+"'mozilla', "}
|
||||
|
||||
cat > $CONFIG_STATUS <<EOF
|
||||
#!${PYTHON}
|
||||
# coding=$encoding
|
||||
@ -85,7 +87,7 @@ topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
|
||||
if not os.path.isabs(topsrcdir):
|
||||
topsrcdir = os.path.normpath(os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir))
|
||||
dnl Don't rely on virtualenv here. Standalone js doesn't use it.
|
||||
sys.path.append(os.path.join(topsrcdir, ${COMM_BUILD:+'mozilla',} 'build'))
|
||||
sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
|
||||
from ConfigStatus import config_status
|
||||
|
||||
args = {
|
||||
|
@ -98,7 +98,7 @@ public class CmdWorkerThread extends Thread
|
||||
String inputLine, outputLine;
|
||||
DoCommand dc = new DoCommand(theParent.svc);
|
||||
|
||||
SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "CmdWorkerThread starts: "+getId());
|
||||
SUTAgentAndroid.logToFile(dc, "CmdWorkerThread starts: "+getId());
|
||||
|
||||
int nAvail = cmdIn.available();
|
||||
cmdIn.skip(nAvail);
|
||||
@ -136,7 +136,7 @@ public class CmdWorkerThread extends Thread
|
||||
{
|
||||
String message = String.format("%s : %s",
|
||||
socket.getInetAddress().getHostAddress(), inputLine);
|
||||
SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), message);
|
||||
SUTAgentAndroid.logToFile(dc, message);
|
||||
|
||||
outputLine = dc.processCommand(inputLine, out, in, cmdOut);
|
||||
if (outputLine.length() > 0)
|
||||
@ -166,7 +166,7 @@ public class CmdWorkerThread extends Thread
|
||||
in.close();
|
||||
in = null;
|
||||
socket.close();
|
||||
SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "CmdWorkerThread ends: "+getId());
|
||||
SUTAgentAndroid.logToFile(dc, "CmdWorkerThread ends: "+getId());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -75,6 +75,7 @@ public class SUTAgentAndroid extends Activity
|
||||
private static String HardwareID = "";
|
||||
private static String Pool = "";
|
||||
private static String sRegString = "";
|
||||
private static boolean LogCommands = false;
|
||||
|
||||
private WifiLock wl = null;
|
||||
|
||||
@ -152,17 +153,20 @@ public class SUTAgentAndroid extends Activity
|
||||
|
||||
DoCommand dc = new DoCommand(getApplication());
|
||||
|
||||
logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onCreate");
|
||||
|
||||
// Get configuration settings from "ini" file
|
||||
File dir = getFilesDir();
|
||||
File iniFile = new File(dir, "SUTAgent.ini");
|
||||
String sIniFile = iniFile.getAbsolutePath();
|
||||
|
||||
String lc = dc.GetIniData("General", "LogCommands", sIniFile);
|
||||
if (lc != "" && Integer.parseInt(lc) == 1) {
|
||||
SUTAgentAndroid.LogCommands = true;
|
||||
}
|
||||
SUTAgentAndroid.RegSvrIPAddr = dc.GetIniData("Registration Server", "IPAddr", sIniFile);
|
||||
SUTAgentAndroid.RegSvrIPPort = dc.GetIniData("Registration Server", "PORT", sIniFile);
|
||||
SUTAgentAndroid.HardwareID = dc.GetIniData("Registration Server", "HARDWARE", sIniFile);
|
||||
SUTAgentAndroid.Pool = dc.GetIniData("Registration Server", "POOL", sIniFile);
|
||||
logToFile(dc, "onCreate");
|
||||
|
||||
tv = (TextView) this.findViewById(R.id.Textview01);
|
||||
|
||||
@ -354,11 +358,11 @@ public class SUTAgentAndroid extends Activity
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
DoCommand dc = new DoCommand(getApplication());
|
||||
super.onDestroy();
|
||||
if (isFinishing())
|
||||
{
|
||||
logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onDestroy - finishing");
|
||||
logToFile(dc, "onDestroy - finishing");
|
||||
Intent listenerSvc = new Intent(this, ASMozStub.class);
|
||||
listenerSvc.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
|
||||
stopService(listenerSvc);
|
||||
@ -373,7 +377,7 @@ public class SUTAgentAndroid extends Activity
|
||||
}
|
||||
else
|
||||
{
|
||||
logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onDestroy - not finishing");
|
||||
logToFile(dc, "onDestroy - not finishing");
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,8 +388,8 @@ public class SUTAgentAndroid extends Activity
|
||||
DoCommand dc = new DoCommand(getApplication());
|
||||
if (dc != null)
|
||||
{
|
||||
logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onLowMemory");
|
||||
logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.GetMemoryInfo());
|
||||
logToFile(dc, "onLowMemory");
|
||||
logToFile(dc, dc.GetMemoryInfo());
|
||||
String procInfo = dc.GetProcessInfo();
|
||||
if (procInfo != null)
|
||||
{
|
||||
@ -394,11 +398,11 @@ public class SUTAgentAndroid extends Activity
|
||||
{
|
||||
if (line.contains("mozilla"))
|
||||
{
|
||||
logToFile(dc.GetTestRoot(), dc.GetSystemTime(), line);
|
||||
logToFile(dc, line);
|
||||
String words[] = line.split("\t");
|
||||
if ((words != null) && (words.length > 1))
|
||||
{
|
||||
logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.StatProcess(words[1]));
|
||||
logToFile(dc, dc.StatProcess(words[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -758,17 +762,29 @@ public class SUTAgentAndroid extends Activity
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void logToFile(String testRoot, String datestamp, String message)
|
||||
public static void logToFile(DoCommand dc, String message)
|
||||
{
|
||||
if (testRoot == null ||
|
||||
datestamp == null ||
|
||||
message == null)
|
||||
if (SUTAgentAndroid.LogCommands == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (message == null)
|
||||
{
|
||||
Log.e("SUTAgentAndroid", "bad arguments in logToFile()!");
|
||||
return;
|
||||
}
|
||||
Log.i("SUTAgentAndroid", message);
|
||||
String fileDateStr = "00";
|
||||
String testRoot = dc.GetTestRoot();
|
||||
String datestamp = dc.GetSystemTime();
|
||||
if (testRoot == null || datestamp == null)
|
||||
{
|
||||
Log.e("SUTAgentAndroid", "Unable to get testRoot or datestamp in logToFile!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
|
||||
|
@ -21,7 +21,7 @@ interface nsIContentSecurityPolicy;
|
||||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
||||
|
||||
[scriptable, uuid(6df7d16d-5b26-42a1-b1f7-069d46c37aa8)]
|
||||
[scriptable, uuid(825ffce8-962d-11e1-aef3-8f2b6188709b)]
|
||||
interface nsIPrincipal : nsISerializable
|
||||
{
|
||||
/**
|
||||
@ -173,7 +173,13 @@ interface nsIPrincipal : nsISerializable
|
||||
* located at the given URI under the same-origin policy. This means that
|
||||
* codebase principals are only allowed to load resources from the same
|
||||
* domain, the system principal is allowed to load anything, and null
|
||||
* principals are not allowed to load anything.
|
||||
* principals are not allowed to load anything. This is changed slightly
|
||||
* by the optional flag allowIfInheritsPrincipal (which defaults to false)
|
||||
* which allows the load of a data: URI (which inherits the principal of
|
||||
* its loader) or a URI with the same principal as its loader (eg. a
|
||||
* Blob URI).
|
||||
* In these cases, with allowIfInheritsPrincipal set to true, the URI can
|
||||
* be loaded by a null principal.
|
||||
*
|
||||
* If the load is allowed this function does nothing. If the load is not
|
||||
* allowed the function throws NS_ERROR_DOM_BAD_URI.
|
||||
@ -187,9 +193,13 @@ interface nsIPrincipal : nsISerializable
|
||||
* @param uri The URI about to be loaded.
|
||||
* @param report If true, will report a warning to the console service
|
||||
* if the load is not allowed.
|
||||
* @param allowIfInheritsPrincipal If true, the load is allowed if the
|
||||
* loadee inherits the principal of the
|
||||
* loader.
|
||||
* @throws NS_ERROR_DOM_BAD_URI if the load is not allowed.
|
||||
*/
|
||||
void checkMayLoad(in nsIURI uri, in boolean report);
|
||||
void checkMayLoad(in nsIURI uri, in boolean report,
|
||||
in boolean allowIfInheritsPrincipal);
|
||||
|
||||
/**
|
||||
* The subject name for the certificate. This actually identifies the
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPrincipal.h"
|
||||
|
||||
class nsIURI;
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
|
||||
class nsIObjectInputStream;
|
||||
class nsIObjectOutputStream;
|
||||
@ -123,7 +126,7 @@ public:
|
||||
NS_IMETHOD GetOrigin(char** aOrigin);
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||
NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
|
||||
NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
|
||||
NS_IMETHOD GetAppId(PRUint32* aAppStatus);
|
||||
@ -158,6 +161,23 @@ public:
|
||||
virtual void GetScriptLocation(nsACString& aStr) MOZ_OVERRIDE;
|
||||
void SetURI(nsIURI* aURI);
|
||||
|
||||
static bool IsPrincipalInherited(nsIURI* aURI) {
|
||||
// return true if the loadee URI has
|
||||
// the URI_INHERITS_SECURITY_CONTEXT flag set.
|
||||
bool doesInheritSecurityContext;
|
||||
nsresult rv =
|
||||
NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&doesInheritSecurityContext);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the puny-encoded origin of aURI.
|
||||
*/
|
||||
@ -202,7 +222,7 @@ public:
|
||||
NS_IMETHOD GetOrigin(char** aOrigin);
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||
NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
|
||||
NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
|
||||
NS_IMETHOD GetAppId(PRUint32* aAppStatus);
|
||||
|
@ -292,8 +292,26 @@ nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
|
||||
{
|
||||
nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
if (aAllowIfInheritsPrincipal) {
|
||||
if (nsPrincipal::IsPrincipalInherited(aURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Also allow the load if the principal of the URI being checked is exactly
|
||||
// us ie this.
|
||||
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
|
||||
if (uriPrinc) {
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
uriPrinc->GetPrincipal(getter_AddRefs(principal));
|
||||
|
||||
if (principal && principal == this) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mURI, aURI);
|
||||
|
@ -846,8 +846,16 @@ URIIsLocalFile(nsIURI *aURI)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
|
||||
nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
if (aAllowIfInheritsPrincipal) {
|
||||
// If the caller specified to allow loads of URIs that inherit
|
||||
// our principal, allow the load if this URI inherits its principal
|
||||
if (nsPrincipal::IsPrincipalInherited(aURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
||||
if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
|
||||
URIIsLocalFile(aURI)) {
|
||||
@ -1432,11 +1440,11 @@ nsExpandedPrincipal::SubsumesIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
|
||||
nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
nsresult rv;
|
||||
for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
|
||||
rv = mPrincipals[i]->CheckMayLoad(uri, aReport);
|
||||
rv = mPrincipals[i]->CheckMayLoad(uri, aReport, aAllowIfInheritsPrincipal);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
@ -846,10 +846,9 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
|
||||
if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin) {
|
||||
nsCOMPtr<nsIURI> uri, domain;
|
||||
subjectPrincipal->GetURI(getter_AddRefs(uri));
|
||||
// Subject can't be system if we failed the security
|
||||
// check, so |uri| is non-null.
|
||||
NS_ASSERTION(uri, "How did that happen?");
|
||||
GetOriginFromURI(uri, subjectOrigin);
|
||||
if (uri) { // Object principal might be expanded
|
||||
GetOriginFromURI(uri, subjectOrigin);
|
||||
}
|
||||
subjectPrincipal->GetDomain(getter_AddRefs(domain));
|
||||
if (domain) {
|
||||
GetOriginFromURI(domain, subjectDomain);
|
||||
@ -1069,55 +1068,63 @@ nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
|
||||
#ifdef DEBUG_CAPS_LookupPolicy
|
||||
printf("DomainLookup ");
|
||||
#endif
|
||||
|
||||
nsCAutoString origin;
|
||||
rv = GetPrincipalDomainOrigin(aPrincipal, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char *start = origin.BeginWriting();
|
||||
const char *nextToLastDot = nullptr;
|
||||
const char *lastDot = nullptr;
|
||||
const char *colon = nullptr;
|
||||
char *p = start;
|
||||
|
||||
//-- search domain (stop at the end of the string or at the 3rd slash)
|
||||
for (PRUint32 slashes=0; *p; p++)
|
||||
if (nsCOMPtr<nsIExpandedPrincipal> exp = do_QueryInterface(aPrincipal))
|
||||
{
|
||||
if (*p == '/' && ++slashes == 3)
|
||||
{
|
||||
*p = '\0'; // truncate at 3rd slash
|
||||
break;
|
||||
}
|
||||
if (*p == '.')
|
||||
{
|
||||
nextToLastDot = lastDot;
|
||||
lastDot = p;
|
||||
}
|
||||
else if (!colon && *p == ':')
|
||||
colon = p;
|
||||
}
|
||||
|
||||
nsCStringKey key(nextToLastDot ? nextToLastDot+1 : start);
|
||||
DomainEntry *de = (DomainEntry*) mOriginToPolicyMap->Get(&key);
|
||||
if (!de)
|
||||
{
|
||||
nsCAutoString scheme(start, colon-start+1);
|
||||
nsCStringKey schemeKey(scheme);
|
||||
de = (DomainEntry*) mOriginToPolicyMap->Get(&schemeKey);
|
||||
}
|
||||
|
||||
while (de)
|
||||
{
|
||||
if (de->Matches(start))
|
||||
{
|
||||
dpolicy = de->mDomainPolicy;
|
||||
break;
|
||||
}
|
||||
de = de->mNext;
|
||||
}
|
||||
|
||||
if (!dpolicy)
|
||||
// For expanded principals domain origin is not defined so let's just
|
||||
// use the default policy
|
||||
dpolicy = mDefaultPolicy;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCAutoString origin;
|
||||
rv = GetPrincipalDomainOrigin(aPrincipal, origin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char *start = origin.BeginWriting();
|
||||
const char *nextToLastDot = nullptr;
|
||||
const char *lastDot = nullptr;
|
||||
const char *colon = nullptr;
|
||||
char *p = start;
|
||||
|
||||
//-- search domain (stop at the end of the string or at the 3rd slash)
|
||||
for (PRUint32 slashes=0; *p; p++)
|
||||
{
|
||||
if (*p == '/' && ++slashes == 3)
|
||||
{
|
||||
*p = '\0'; // truncate at 3rd slash
|
||||
break;
|
||||
}
|
||||
if (*p == '.')
|
||||
{
|
||||
nextToLastDot = lastDot;
|
||||
lastDot = p;
|
||||
}
|
||||
else if (!colon && *p == ':')
|
||||
colon = p;
|
||||
}
|
||||
|
||||
nsCStringKey key(nextToLastDot ? nextToLastDot+1 : start);
|
||||
DomainEntry *de = (DomainEntry*) mOriginToPolicyMap->Get(&key);
|
||||
if (!de)
|
||||
{
|
||||
nsCAutoString scheme(start, colon-start+1);
|
||||
nsCStringKey schemeKey(scheme);
|
||||
de = (DomainEntry*) mOriginToPolicyMap->Get(&schemeKey);
|
||||
}
|
||||
|
||||
while (de)
|
||||
{
|
||||
if (de->Matches(start))
|
||||
{
|
||||
dpolicy = de->mDomainPolicy;
|
||||
break;
|
||||
}
|
||||
de = de->mNext;
|
||||
}
|
||||
|
||||
if (!dpolicy)
|
||||
dpolicy = mDefaultPolicy;
|
||||
}
|
||||
|
||||
aPrincipal->SetSecurityPolicy((void*)dpolicy);
|
||||
}
|
||||
@ -1387,7 +1394,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (hasFlags) {
|
||||
return aPrincipal->CheckMayLoad(targetBaseURI, true);
|
||||
return aPrincipal->CheckMayLoad(targetBaseURI, true, false);
|
||||
}
|
||||
|
||||
//-- get the source scheme
|
||||
|
@ -115,7 +115,7 @@ nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
|
||||
nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -13,7 +13,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=292789
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<script src="chrome://global/content/strres.js"></script>
|
||||
<script src="chrome://mozapps/content/xpinstall/xpinstallConfirm.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="chrome://mozapps/content/xpinstall/xpinstallConfirm.js"></script>
|
||||
<script id="resjs" type="application/javascript;version=1.8"></script>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
@ -36,13 +37,13 @@ function testScriptSrc(aCallback) {
|
||||
/** make sure the last one didn't pass because someone
|
||||
** moved the resource
|
||||
**/
|
||||
var resjs = document.createElement("script");
|
||||
var resjs = document.getElementById("resjs");
|
||||
resjs.onload = scriptOnload;
|
||||
#ifdef MOZ_CHROME_FILE_FORMAT_JAR
|
||||
resjs.src = "jar:resource://gre/chrome/toolkit.jar!/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#else
|
||||
resjs.src = "resource://gre/chrome/toolkit/content/mozapps/xpinstall/xpinstallConfirm.js";
|
||||
#endif
|
||||
resjs.onload = scriptOnload;
|
||||
document.getElementById("content").appendChild(resjs);
|
||||
|
||||
function scriptOnload() {
|
||||
|
@ -1,3 +1,4 @@
|
||||
locale testmatchos en-US jar:en-US.jar!/locale/en-US/global/
|
||||
locale testmatchos fr-FR jar:en-US.jar!/locale/en-US/global/
|
||||
locale testmatchos de-DE jar:en-US.jar!/locale/en-US/global/
|
||||
locale testmatchos xx-AA jar:en-US.jar!/locale/en-US/global/
|
||||
|
@ -7,6 +7,45 @@ var MANIFESTS = [
|
||||
do_get_file("data/test_bug519468.manifest")
|
||||
];
|
||||
|
||||
// Stub in the locale service so we can control what gets returned as the OS locale setting
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let stubOSLocale = null;
|
||||
|
||||
stubID = Components.ID("9d09d686-d913-414c-a1e6-4be8652d7d93");
|
||||
localeContractID = "@mozilla.org/intl/nslocaleservice;1";
|
||||
|
||||
StubLocaleService = {
|
||||
classDescription: "Stub version of Locale service for testing",
|
||||
classID: stubID,
|
||||
contractID: localeContractID,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsILocaleService, Ci.nsISupports, Ci.nsIFactory]),
|
||||
|
||||
createInstance: function (outer, iid) {
|
||||
if (outer)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
lockFactory: function (lock) {
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
getLocaleComponentForUserAgent: function SLS_getLocaleComponentForUserAgent()
|
||||
{
|
||||
return stubOSLocale;
|
||||
}
|
||||
}
|
||||
|
||||
let registrar = Components.manager.nsIComponentRegistrar;
|
||||
// Save original factory.
|
||||
let localeCID = registrar.contractIDToCID(localeContractID)
|
||||
let originalFactory =
|
||||
Components.manager.getClassObject(Components.classes[localeContractID],
|
||||
Components.interfaces.nsIFactory);
|
||||
|
||||
registrar.registerFactory(stubID, "Unit test Locale Service", localeContractID, StubLocaleService);
|
||||
|
||||
// Now fire up the test
|
||||
do_test_pending()
|
||||
registerManifests(MANIFESTS);
|
||||
|
||||
@ -15,48 +54,62 @@ var chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.QueryInterface(Ci.nsIToolkitChromeRegistry);
|
||||
chromeReg.checkForNewChrome();
|
||||
|
||||
var localeService = Cc["@mozilla.org/intl/nslocaleservice;1"]
|
||||
.getService(Ci.nsILocaleService);
|
||||
|
||||
var prefService = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService)
|
||||
.QueryInterface(Ci.nsIPrefBranch);
|
||||
var os = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService);
|
||||
|
||||
var systemLocale = localeService.getLocaleComponentForUserAgent();
|
||||
var count = 0;
|
||||
var testsLocale = [
|
||||
{matchOS: false, selected: null, locale: "en-US"},
|
||||
{matchOS: true, selected: null, locale: systemLocale},
|
||||
{matchOS: true, selected: "fr-FR", locale: systemLocale},
|
||||
{matchOS: false, selected: "fr-FR", locale: "fr-FR"},
|
||||
{matchOS: false, selected: "de-DE", locale: "de-DE"},
|
||||
{matchOS: true, selected: null, locale: systemLocale}
|
||||
// These tests cover when the OS local is included in our manifest
|
||||
{matchOS: false, selected: "en-US", osLocale: "xx-AA", locale: "en-US"},
|
||||
{matchOS: true, selected: "en-US", osLocale: "xx-AA", locale: "xx-AA"},
|
||||
{matchOS: false, selected: "fr-FR", osLocale: "xx-AA", locale: "fr-FR"},
|
||||
{matchOS: true, selected: "fr-FR", osLocale: "xx-AA", locale: "xx-AA"},
|
||||
{matchOS: false, selected: "de-DE", osLocale: "xx-AA", locale: "de-DE"},
|
||||
{matchOS: true, selected: "de-DE", osLocale: "xx-AA", locale: "xx-AA"},
|
||||
// these tests cover the case where the OS locale is not available in our manifest, but the
|
||||
// base language is (ie, substitute xx-AA which we have for xx-BB which we don't)
|
||||
{matchOS: false, selected: "en-US", osLocale: "xx-BB", locale: "en-US"},
|
||||
{matchOS: true, selected: "en-US", osLocale: "xx-BB", locale: "xx-AA"},
|
||||
{matchOS: false, selected: "fr-FR", osLocale: "xx-BB", locale: "fr-FR"},
|
||||
{matchOS: true, selected: "fr-FR", osLocale: "xx-BB", locale: "xx-AA"},
|
||||
// These tests cover where the language is not available
|
||||
{matchOS: false, selected: "en-US", osLocale: "xy-BB", locale: "en-US"},
|
||||
{matchOS: true, selected: "en-US", osLocale: "xy-BB", locale: "en-US"},
|
||||
{matchOS: false, selected: "fr-FR", osLocale: "xy-BB", locale: "fr-FR"},
|
||||
{matchOS: true, selected: "fr-FR", osLocale: "xy-BB", locale: "en-US"},
|
||||
];
|
||||
|
||||
var observedLocale = null;
|
||||
|
||||
function test_locale(aTest) {
|
||||
observedLocale = null;
|
||||
|
||||
stubOSLocale = aTest.osLocale;
|
||||
prefService.setBoolPref("intl.locale.matchOS", aTest.matchOS);
|
||||
prefService.setCharPref("general.useragent.locale", aTest.selected || "en-US");
|
||||
prefService.setCharPref("general.useragent.locale", aTest.selected);
|
||||
|
||||
chromeReg.reloadChrome();
|
||||
|
||||
do_check_eq(observedLocale, aTest.locale);
|
||||
}
|
||||
|
||||
// Callback function for observing locale change. May be called more than once
|
||||
// per test iteration.
|
||||
function checkValidity() {
|
||||
var selectedLocale = chromeReg.getSelectedLocale("testmatchos");
|
||||
do_check_eq(selectedLocale, testsLocale[count].locale);
|
||||
|
||||
count++;
|
||||
if (count >= testsLocale.length) {
|
||||
os.removeObserver(checkValidity, "selected-locale-has-changed");
|
||||
do_test_finished();
|
||||
}
|
||||
else {
|
||||
test_locale(testsLocale[count]);
|
||||
}
|
||||
observedLocale = chromeReg.getSelectedLocale("testmatchos");
|
||||
dump("checkValidity called back with locale = " + observedLocale + "\n");
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
os.addObserver(checkValidity, "selected-locale-has-changed", false);
|
||||
test_locale(testsLocale[count]);
|
||||
|
||||
for (let count = 0 ; count < testsLocale.length ; count++) {
|
||||
dump("count = " + count + " " + testsLocale[count].toSource() + "\n");
|
||||
test_locale(testsLocale[count]);
|
||||
}
|
||||
|
||||
os.removeObserver(checkValidity, "selected-locale-has-changed");
|
||||
do_test_finished();
|
||||
}
|
||||
|
20
configure.in
20
configure.in
@ -4335,7 +4335,7 @@ if test -z "$gonkdir" ; then
|
||||
android_min_api_level=13
|
||||
;;
|
||||
mobile/android)
|
||||
android_min_api_level=14
|
||||
android_min_api_level=16
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -5273,8 +5273,13 @@ if test -n "$MOZ_WEBM"; then
|
||||
fi;
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable media plugin support
|
||||
dnl = Enable media plugin support
|
||||
dnl ========================================================
|
||||
if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
|
||||
dnl Enable support on android by default
|
||||
MOZ_MEDIA_PLUGINS=1
|
||||
fi
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(media-plugins,
|
||||
[ --enable-media-plugins Enable support for media plugins],
|
||||
MOZ_MEDIA_PLUGINS=1,
|
||||
@ -5299,6 +5304,11 @@ fi
|
||||
dnl ========================================================
|
||||
dnl = Enable building OMX media plugin (B2G or Android)
|
||||
dnl ========================================================
|
||||
if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
|
||||
dnl Enable support on android by default
|
||||
MOZ_OMX_PLUGIN=1
|
||||
fi
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(omx-plugin,
|
||||
[ --enable-omx-plugin Enable building OMX plugin (B2G)],
|
||||
MOZ_OMX_PLUGIN=1,
|
||||
@ -5796,7 +5806,7 @@ MOZ_ARG_DISABLE_BOOL(crashreporter,
|
||||
if test -n "$MOZ_CRASHREPORTER"; then
|
||||
AC_DEFINE(MOZ_CRASHREPORTER)
|
||||
|
||||
if (test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS") && \
|
||||
if test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS" && \
|
||||
test -z "$SKIP_LIBRARY_CHECKS"; then
|
||||
PKG_CHECK_MODULES(MOZ_GTHREAD, gthread-2.0)
|
||||
AC_SUBST(MOZ_GTHREAD_CFLAGS)
|
||||
@ -5805,7 +5815,7 @@ if test -n "$MOZ_CRASHREPORTER"; then
|
||||
MOZ_CHECK_HEADERS([curl/curl.h], [], [AC_MSG_ERROR([Couldn't find curl/curl.h which is required for the crash reporter. Use --disable-crashreporter to disable the crash reporter.])])
|
||||
fi
|
||||
|
||||
if (test "$OS_ARCH" != "$HOST_OS_ARCH"); then
|
||||
if test "$OS_ARCH" != "$HOST_OS_ARCH"; then
|
||||
AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH. Use --disable-crashreporter.])
|
||||
fi
|
||||
|
||||
@ -7681,7 +7691,7 @@ MOZ_ARG_DISABLE_BOOL(md,
|
||||
fi])
|
||||
if test "$_cpp_md_flag"; then
|
||||
COMPILER_DEPEND=1
|
||||
_DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(@F).pp)'
|
||||
_DEPEND_CFLAGS='$(filter-out %/.pp,-MMD -MF $(MDDEPDIR)/$(@F).pp)'
|
||||
dnl Sun Studio on Solaris use -xM instead of -MD, see config/rules.mk
|
||||
if test "$SOLARIS_SUNPRO_CC"; then
|
||||
_DEPEND_CFLAGS=
|
||||
|
@ -816,6 +816,16 @@ public:
|
||||
const char* aKey,
|
||||
nsXPIDLString& aResult);
|
||||
|
||||
/**
|
||||
* A helper function that parses a sandbox attribute (of an <iframe> or
|
||||
* a CSP directive) and converts it to the set of flags used internally.
|
||||
*
|
||||
* @param aAttribute the value of the sandbox attribute
|
||||
* @return the set of flags
|
||||
*/
|
||||
static PRUint32 ParseSandboxAttributeToFlags(const nsAString& aSandboxAttr);
|
||||
|
||||
|
||||
/**
|
||||
* Fill (with the parameters given) the localized string named |aKey| in
|
||||
* properties file |aFile|.
|
||||
@ -1694,7 +1704,7 @@ public:
|
||||
static already_AddRefed<nsIDocument>
|
||||
GetDocumentFromScriptContext(nsIScriptContext *aScriptContext);
|
||||
|
||||
static bool CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel);
|
||||
static bool CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal);
|
||||
|
||||
/**
|
||||
* The method checks whether the caller can access native anonymous content.
|
||||
@ -1950,15 +1960,17 @@ public:
|
||||
* Set the given principal as the owner of the given channel, if
|
||||
* needed. aURI must be the URI of aChannel. aPrincipal may be
|
||||
* null. If aSetUpForAboutBlank is true, then about:blank will get
|
||||
* the principal set up on it.
|
||||
*
|
||||
* the principal set up on it. If aForceOwner is true, the owner
|
||||
* will be set on the channel, even if the principal can be determined
|
||||
* from the channel.
|
||||
* The return value is whether the principal was set up as the owner
|
||||
* of the channel.
|
||||
*/
|
||||
static bool SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
bool aSetUpForAboutBlank);
|
||||
bool aSetUpForAboutBlank,
|
||||
bool aForceOwner = false);
|
||||
|
||||
static nsresult Btoa(const nsAString& aBinaryData,
|
||||
nsAString& aAsciiBase64String);
|
||||
@ -1975,7 +1987,7 @@ public:
|
||||
|
||||
/**
|
||||
* Returns whether the input element passed in parameter has the autocomplete
|
||||
* functionnality enabled. It is taking into account the form owner.
|
||||
* functionality enabled. It is taking into account the form owner.
|
||||
* NOTE: the caller has to make sure autocomplete makes sense for the
|
||||
* element's type.
|
||||
*
|
||||
|
@ -45,6 +45,5 @@ DEPRECATED_OPERATION(InputEncoding)
|
||||
DEPRECATED_OPERATION(MozBeforePaint)
|
||||
DEPRECATED_OPERATION(MozBlobBuilder)
|
||||
DEPRECATED_OPERATION(DOMExceptionCode)
|
||||
DEPRECATED_OPERATION(NoExposedProps)
|
||||
DEPRECATED_OPERATION(MutationEvent)
|
||||
DEPRECATED_OPERATION(MozSlice)
|
||||
|
@ -79,8 +79,8 @@ class Element;
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xdb888523, 0x541f, 0x49e3, \
|
||||
{ 0xa9, 0x71, 0xb5, 0xea, 0xd1, 0xf0, 0xc3, 0xcf } }
|
||||
{ 0x57fe44ae, 0x6656, 0x44b8, \
|
||||
{ 0x8d, 0xc0, 0xfc, 0xa7, 0x43, 0x28, 0xbe, 0x86 } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
@ -400,6 +400,25 @@ public:
|
||||
mBidiOptions = aBidiOptions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the sandbox flags for this document.
|
||||
* @see nsSandboxFlags.h for the possible flags
|
||||
*/
|
||||
PRUint32 GetSandboxFlags() const
|
||||
{
|
||||
return mSandboxFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sandbox flags for this document.
|
||||
* @see nsSandboxFlags.h for the possible flags
|
||||
*/
|
||||
void SetSandboxFlags(PRUint32 sandboxFlags)
|
||||
{
|
||||
mSandboxFlags = sandboxFlags;
|
||||
}
|
||||
|
||||
inline mozilla::directionality::Directionality GetDocumentDirectionality() {
|
||||
return mDirectionality;
|
||||
}
|
||||
@ -456,6 +475,11 @@ public:
|
||||
{
|
||||
mParentDocument = aParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are plugins allowed in this document ?
|
||||
*/
|
||||
virtual nsresult GetAllowPlugins (bool* aAllowPlugins) = 0;
|
||||
|
||||
/**
|
||||
* Set the sub document for aContent to aSubDoc.
|
||||
@ -1867,6 +1891,11 @@ protected:
|
||||
// defined in nsBidiUtils.h
|
||||
PRUint32 mBidiOptions;
|
||||
|
||||
// The sandbox flags on the document. These reflect the value of the sandbox attribute of the
|
||||
// associated IFRAME or CSP-protectable content, if existent. These are set at load time and
|
||||
// are immutable - see nsSandboxFlags.h for the possible flags.
|
||||
PRUint32 mSandboxFlags;
|
||||
|
||||
// The root directionality of this document.
|
||||
mozilla::directionality::Directionality mDirectionality;
|
||||
|
||||
|
@ -147,14 +147,14 @@ public:
|
||||
* @param aSink can be null if the breaks are not actually needed (we may
|
||||
* still be setting up state for later breaks)
|
||||
*/
|
||||
nsresult AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32 aLength,
|
||||
nsresult AppendText(nsIAtom* aHyphenationLanguage, const PRUnichar* aText, PRUint32 aLength,
|
||||
PRUint32 aFlags, nsILineBreakSink* aSink);
|
||||
/**
|
||||
* Feed 8-bit text into the linebreaker for analysis. aLength must be nonzero.
|
||||
* @param aSink can be null if the breaks are not actually needed (we may
|
||||
* still be setting up state for later breaks)
|
||||
*/
|
||||
nsresult AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aLength,
|
||||
nsresult AppendText(nsIAtom* aHyphenationLanguage, const PRUint8* aText, PRUint32 aLength,
|
||||
PRUint32 aFlags, nsILineBreakSink* aSink);
|
||||
/**
|
||||
* Reset all state. This means the current run has ended; any outstanding
|
||||
@ -198,7 +198,7 @@ private:
|
||||
// appropriate sink(s). Then we clear the current word state.
|
||||
nsresult FlushCurrentWord();
|
||||
|
||||
void UpdateCurrentWordLangGroup(nsIAtom *aLangGroup);
|
||||
void UpdateCurrentWordLanguage(nsIAtom *aHyphenationLanguage);
|
||||
|
||||
void FindHyphenationPoints(nsHyphenator *aHyphenator,
|
||||
const PRUnichar *aTextStart,
|
||||
@ -208,7 +208,7 @@ private:
|
||||
nsAutoTArray<PRUnichar,100> mCurrentWord;
|
||||
// All the items that contribute to mCurrentWord
|
||||
nsAutoTArray<TextItem,2> mTextItems;
|
||||
nsIAtom* mCurrentWordLangGroup;
|
||||
nsIAtom* mCurrentWordLanguage;
|
||||
bool mCurrentWordContainsMixedLang;
|
||||
bool mCurrentWordContainsComplexChar;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
@ -31,6 +32,41 @@ var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
var gETLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
|
||||
.getService(Components.interfaces.nsIEffectiveTLDService);
|
||||
|
||||
// These regexps represent the concrete syntax on the w3 spec as of 7-5-2012
|
||||
// scheme = <scheme production from RFC 3986>
|
||||
const R_SCHEME = new RegExp ("([a-zA-Z0-9\\-]+)", 'i');
|
||||
const R_GETSCHEME = new RegExp ("^" + R_SCHEME.source + "(?=\\:)", 'i');
|
||||
|
||||
// scheme-source = scheme ":"
|
||||
const R_SCHEMESRC = new RegExp ("^" + R_SCHEME.source + "\\:$", 'i');
|
||||
|
||||
// host-char = ALPHA / DIGIT / "-"
|
||||
const R_HOSTCHAR = new RegExp ("[a-zA-Z0-9\\-]", 'i');
|
||||
|
||||
// host = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
|
||||
const R_HOST = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
|
||||
"+)(\\." + R_HOSTCHAR.source +"+)+)",'i');
|
||||
// port = ":" ( 1*DIGIT / "*" )
|
||||
const R_PORT = new RegExp ("(\\:([0-9]+|\\*))", 'i');
|
||||
|
||||
// host-source = [ scheme "://" ] host [ port ]
|
||||
const R_HOSTSRC = new RegExp ("^((" + R_SCHEME.source + "\\:\\/\\/)?("
|
||||
+ R_HOST.source + ")"
|
||||
+ R_PORT.source + "?)$", 'i');
|
||||
|
||||
// ext-host-source = host-source "/" *( <VCHAR except ";" and ","> )
|
||||
// ; ext-host-source is reserved for future use.
|
||||
const R_EXTHOSTSRC = new RegExp ("^" + R_HOSTSRC.source + "\\/[:print:]+$", 'i');
|
||||
|
||||
// keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
|
||||
const R_KEYWORDSRC = new RegExp ("^('self'|'unsafe-inline'|'unsafe-eval')$", 'i');
|
||||
|
||||
// source-exp = scheme-source / host-source / keyword-source
|
||||
const R_SOURCEEXP = new RegExp (R_SCHEMESRC.source + "|" +
|
||||
R_HOSTSRC.source + "|" +
|
||||
R_KEYWORDSRC.source, 'i');
|
||||
|
||||
|
||||
var gPrefObserver = {
|
||||
get debugEnabled () {
|
||||
if (!this._branch)
|
||||
@ -479,8 +515,10 @@ CSPRep.prototype = {
|
||||
|
||||
for (var dir in CSPRep.SRC_DIRECTIVES) {
|
||||
var dirv = CSPRep.SRC_DIRECTIVES[dir];
|
||||
newRep._directives[dirv] = this._directives[dirv]
|
||||
.intersectWith(aCSPRep._directives[dirv]);
|
||||
if (this._directives.hasOwnProperty(dirv))
|
||||
newRep._directives[dirv] = this._directives[dirv].intersectWith(aCSPRep._directives[dirv]);
|
||||
else
|
||||
newRep._directives[dirv] = aCSPRep._directives[dirv];
|
||||
}
|
||||
|
||||
// REPORT_URI
|
||||
@ -498,12 +536,6 @@ CSPRep.prototype = {
|
||||
newRep._directives[reportURIDir] = aCSPRep._directives[reportURIDir].concat();
|
||||
}
|
||||
|
||||
for (var dir in CSPRep.SRC_DIRECTIVES) {
|
||||
var dirv = CSPRep.SRC_DIRECTIVES[dir];
|
||||
newRep._directives[dirv] = this._directives[dirv]
|
||||
.intersectWith(aCSPRep._directives[dirv]);
|
||||
}
|
||||
|
||||
newRep._allowEval = this.allowsEvalInScripts
|
||||
&& aCSPRep.allowsEvalInScripts;
|
||||
|
||||
@ -588,11 +620,8 @@ function CSPSourceList() {
|
||||
* an instance of CSPSourceList
|
||||
*/
|
||||
CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
// Source list is:
|
||||
// <host-dir-value> ::= <source-list>
|
||||
// | "'none'"
|
||||
// <source-list> ::= <source>
|
||||
// | <source-list>" "<source>
|
||||
// source-list = *WSP [ source-expression *( 1*WSP source-expression ) *WSP ]
|
||||
// / *WSP "'none'" *WSP
|
||||
|
||||
/* If self parameter is passed, convert to CSPSource,
|
||||
unless it is already a CSPSource. */
|
||||
@ -601,23 +630,33 @@ CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
}
|
||||
|
||||
var slObj = new CSPSourceList();
|
||||
if (aStr === "'none'")
|
||||
return slObj;
|
||||
|
||||
if (aStr === "*") {
|
||||
slObj._permitAllSources = true;
|
||||
aStr = aStr.trim();
|
||||
// w3 specifies case insensitive equality
|
||||
if (aStr.toUpperCase() === "'NONE'"){
|
||||
slObj._permitAllSources = false;
|
||||
return slObj;
|
||||
}
|
||||
|
||||
var tokens = aStr.split(/\s+/);
|
||||
for (var i in tokens) {
|
||||
if (tokens[i] === "") continue;
|
||||
var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
|
||||
if (!src) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource", [tokens[i]]));
|
||||
if (!R_SOURCEEXP.test(tokens[i])){
|
||||
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
|
||||
[tokens[i]]));
|
||||
continue;
|
||||
}
|
||||
slObj._sources.push(src);
|
||||
var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
|
||||
if (!src) {
|
||||
CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
|
||||
[tokens[i]]));
|
||||
continue;
|
||||
}
|
||||
// if a source is a *, then we can permit all sources
|
||||
if (src.permitAll){
|
||||
slObj._permitAllSources = true;
|
||||
return slObj;
|
||||
} else {
|
||||
slObj._sources.push(src);
|
||||
}
|
||||
}
|
||||
|
||||
return slObj;
|
||||
@ -736,6 +775,8 @@ CSPSourceList.prototype = {
|
||||
|
||||
var newCSPSrcList = null;
|
||||
|
||||
if (!that) return this.clone();
|
||||
|
||||
if (this.isNone() || that.isNone())
|
||||
newCSPSrcList = CSPSourceList.fromString("'none'");
|
||||
|
||||
@ -787,6 +828,9 @@ function CSPSource() {
|
||||
this._port = undefined;
|
||||
this._host = undefined;
|
||||
|
||||
//when set to true, this allows all source
|
||||
this._permitAll = false;
|
||||
|
||||
// when set to true, this source represents 'self'
|
||||
this._isSelf = false;
|
||||
}
|
||||
@ -924,6 +968,15 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var sObj = new CSPSource();
|
||||
sObj._self = self;
|
||||
|
||||
// if equal, return does match
|
||||
if (aStr === "*"){
|
||||
sObj._permitAll = true;
|
||||
return sObj;
|
||||
}
|
||||
|
||||
if (!self && enforceSelfChecks) {
|
||||
CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
|
||||
return null;
|
||||
@ -933,12 +986,50 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
self = CSPSource.create(self, undefined, false);
|
||||
}
|
||||
|
||||
var sObj = new CSPSource();
|
||||
sObj._self = self;
|
||||
// check for scheme-source match
|
||||
if (R_SCHEMESRC.test(aStr)){
|
||||
var schemeSrcMatch = R_GETSCHEME.exec(aStr);
|
||||
sObj._scheme = schemeSrcMatch[0];
|
||||
if (!sObj._host) sObj._host = CSPHost.fromString("*");
|
||||
if (!sObj._port) sObj._port = "*";
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// take care of 'self' keyword
|
||||
if (aStr === "'self'") {
|
||||
if (!self) {
|
||||
// check for host-source or ext-host-source match
|
||||
if (R_HOSTSRC.test(aStr) || R_EXTHOSTSRC.test(aStr)){
|
||||
var schemeMatch = R_GETSCHEME.exec(aStr);
|
||||
if (!schemeMatch)
|
||||
sObj._scheme = self.scheme;
|
||||
else {
|
||||
sObj._scheme = schemeMatch[0];
|
||||
}
|
||||
|
||||
var hostMatch = R_HOST.exec(aStr);
|
||||
if (!hostMatch) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
|
||||
return null;
|
||||
}
|
||||
sObj._host = CSPHost.fromString(hostMatch[0]);
|
||||
var portMatch = R_PORT.exec(aStr);
|
||||
if (!portMatch) {
|
||||
// gets the default port for the given scheme
|
||||
defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
|
||||
if (!defPort) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
|
||||
return null;
|
||||
}
|
||||
sObj._port = defPort;
|
||||
}
|
||||
else {
|
||||
// strip the ':' from the port
|
||||
sObj._port = portMatch[0].substr(1);
|
||||
}
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// check for 'self' (case insensitive)
|
||||
if (aStr.toUpperCase() === "'SELF'"){
|
||||
if (!self){
|
||||
CSPError(CSPLocalizer.getStr("selfKeywordNoSelfData"));
|
||||
return null;
|
||||
}
|
||||
@ -946,125 +1037,14 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
|
||||
sObj._isSelf = true;
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// We could just create a URI and then send this off to fromURI, but
|
||||
// there's no way to leave out the scheme or wildcard the port in an nsURI.
|
||||
// That has to be supported here.
|
||||
|
||||
// split it up
|
||||
var chunks = aStr.split(":");
|
||||
|
||||
// If there is only one chunk, it's gotta be a host.
|
||||
if (chunks.length == 1) {
|
||||
sObj._host = CSPHost.fromString(chunks[0]);
|
||||
if (!sObj._host) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
return null;
|
||||
}
|
||||
|
||||
// enforce 'self' inheritance
|
||||
if (enforceSelfChecks) {
|
||||
// note: the non _scheme accessor checks sObj._self
|
||||
if (!sObj.scheme || !sObj.port) {
|
||||
CSPError(CSPLocalizer.getFormatStr("hostSourceWithoutData",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// If there are two chunks, it's either scheme://host or host:port
|
||||
// ... but scheme://host can have an empty host.
|
||||
// ... and host:port can have an empty host
|
||||
if (chunks.length == 2) {
|
||||
|
||||
// is the last bit a port?
|
||||
if (chunks[1] === "*" || chunks[1].match(/^\d+$/)) {
|
||||
sObj._port = chunks[1];
|
||||
// then the previous chunk *must* be a host or empty.
|
||||
if (chunks[0] !== "") {
|
||||
sObj._host = CSPHost.fromString(chunks[0]);
|
||||
if (!sObj._host) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// enforce 'self' inheritance
|
||||
// (scheme:host requires port, host:port does too. Wildcard support is
|
||||
// only available if the scheme and host are wildcarded)
|
||||
if (enforceSelfChecks) {
|
||||
// note: the non _scheme accessor checks sObj._self
|
||||
if (!sObj.scheme || !sObj.host || !sObj.port) {
|
||||
CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// is the first bit a scheme?
|
||||
else if (CSPSource.validSchemeName(chunks[0])) {
|
||||
sObj._scheme = chunks[0];
|
||||
// then the second bit *must* be a host or empty
|
||||
if (chunks[1] === "") {
|
||||
// Allow scheme-only sources! These default to wildcard host/port,
|
||||
// especially since host and port don't always matter.
|
||||
// Example: "javascript:" and "data:"
|
||||
if (!sObj._host) sObj._host = CSPHost.fromString("*");
|
||||
if (!sObj._port) sObj._port = "*";
|
||||
} else {
|
||||
// some host was defined.
|
||||
// ... remove <= 3 leading slashes (from the scheme) and parse
|
||||
var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
|
||||
// ... and parse
|
||||
sObj._host = CSPHost.fromString(cleanHost);
|
||||
if (!sObj._host) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidHost",[cleanHost]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// enforce 'self' inheritance (scheme-only should be scheme:*:* now, and
|
||||
// if there was a host provided it should be scheme:host:selfport
|
||||
if (enforceSelfChecks) {
|
||||
// note: the non _scheme accessor checks sObj._self
|
||||
if (!sObj.scheme || !sObj.host || !sObj.port) {
|
||||
CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// AAAH! Don't know what to do! No valid scheme or port!
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
return null;
|
||||
}
|
||||
|
||||
return sObj;
|
||||
}
|
||||
|
||||
// If there are three chunks, we got 'em all!
|
||||
if (!CSPSource.validSchemeName(chunks[0])) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseScheme",[aStr]));
|
||||
return null;
|
||||
}
|
||||
sObj._scheme = chunks[0];
|
||||
if (!(chunks[2] === "*" || chunks[2].match(/^\d+$/))) {
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParsePort",[aStr]));
|
||||
return null;
|
||||
}
|
||||
|
||||
sObj._port = chunks[2];
|
||||
|
||||
// ... remove <= 3 leading slashes (from the scheme) and parse
|
||||
var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
|
||||
sObj._host = CSPHost.fromString(cleanHost);
|
||||
|
||||
return sObj._host ? sObj : null;
|
||||
CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
|
||||
return null;
|
||||
};
|
||||
|
||||
CSPSource.validSchemeName = function(aStr) {
|
||||
// <scheme-name> ::= <alpha><scheme-suffix>
|
||||
// <scheme-suffix> ::= <scheme-chr>
|
||||
// | <scheme-suffix><scheme-chr>
|
||||
// <scheme-suffix> ::= <scheme-chr>
|
||||
// | <scheme-suffix><scheme-chr>
|
||||
// <scheme-chr> ::= <letter> | <digit> | "+" | "." | "-"
|
||||
|
||||
return aStr.match(/^[a-zA-Z][a-zA-Z0-9+.-]*$/);
|
||||
@ -1088,7 +1068,13 @@ CSPSource.prototype = {
|
||||
return this._host;
|
||||
},
|
||||
|
||||
/**
|
||||
get permitAll () {
|
||||
if (this._isSelf && this._self)
|
||||
return this._self.permitAll;
|
||||
return this._permitAll;
|
||||
},
|
||||
|
||||
/**
|
||||
* If this doesn't have a nonstandard port (hard-defined), use the default
|
||||
* port for this source's scheme. Should never inherit port from 'self'.
|
||||
*/
|
||||
@ -1199,32 +1185,32 @@ CSPSource.prototype = {
|
||||
// when a scheme, host or port is undefined.)
|
||||
|
||||
// port
|
||||
if (!this._port)
|
||||
newSource._port = that._port;
|
||||
else if (!that._port)
|
||||
newSource._port = this._port;
|
||||
else if (this._port === "*")
|
||||
newSource._port = that._port;
|
||||
else if (that._port === "*")
|
||||
newSource._port = this._port;
|
||||
else if (that._port === this._port)
|
||||
newSource._port = this._port;
|
||||
if (!this.port)
|
||||
newSource._port = that.port;
|
||||
else if (!that.port)
|
||||
newSource._port = this.port;
|
||||
else if (this.port === "*")
|
||||
newSource._port = that.port;
|
||||
else if (that.port === "*")
|
||||
newSource._port = this.port;
|
||||
else if (that.port === this.port)
|
||||
newSource._port = this.port;
|
||||
else {
|
||||
CSPError(CSPLocalizer.getFormatStr("notIntersectPort", [this.toString(), that.toString()]));
|
||||
return null;
|
||||
}
|
||||
|
||||
// scheme
|
||||
if (!this._scheme)
|
||||
newSource._scheme = that._scheme;
|
||||
else if (!that._scheme)
|
||||
newSource._scheme = this._scheme;
|
||||
if (this._scheme === "*")
|
||||
newSource._scheme = that._scheme;
|
||||
else if (that._scheme === "*")
|
||||
newSource._scheme = this._scheme;
|
||||
else if (that._scheme === this._scheme)
|
||||
newSource._scheme = this._scheme;
|
||||
if (!this.scheme)
|
||||
newSource._scheme = that.scheme;
|
||||
else if (!that.scheme)
|
||||
newSource._scheme = this.scheme;
|
||||
if (this.scheme === "*")
|
||||
newSource._scheme = that.scheme;
|
||||
else if (that.scheme === "*")
|
||||
newSource._scheme = this.scheme;
|
||||
else if (that.scheme === this.scheme)
|
||||
newSource._scheme = this.scheme;
|
||||
else {
|
||||
CSPError(CSPLocalizer.getFormatStr("notIntersectScheme", [this.toString(), that.toString()]));
|
||||
return null;
|
||||
@ -1239,14 +1225,14 @@ CSPSource.prototype = {
|
||||
// error should still be reported.
|
||||
|
||||
// host
|
||||
if (this._host && that._host) {
|
||||
newSource._host = this._host.intersectWith(that._host);
|
||||
} else if (this._host) {
|
||||
if (this.host && that.host) {
|
||||
newSource._host = this.host.intersectWith(that.host);
|
||||
} else if (this.host) {
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [that.toString()]));
|
||||
newSource._host = this._host.clone();
|
||||
} else if (that._host) {
|
||||
newSource._host = this.host.clone();
|
||||
} else if (that.host) {
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [this.toString()]));
|
||||
newSource._host = that._host.clone();
|
||||
newSource._host = that.host.clone();
|
||||
} else {
|
||||
CSPError(CSPLocalizer.getFormatStr("intersectingSourcesWithUndefinedHosts", [this.toString(), that.toString()]));
|
||||
newSource._host = CSPHost.fromString("*");
|
||||
|
@ -40,6 +40,7 @@ EXPORTS = \
|
||||
nsGenericElement.h \
|
||||
nsMappedAttributeElement.h \
|
||||
nsStyledElement.h \
|
||||
nsSandboxFlags.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla/dom
|
||||
|
@ -1064,7 +1064,7 @@ nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
|
||||
}
|
||||
|
||||
// Documents must list a manifest from the same origin
|
||||
rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, true);
|
||||
rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, true, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "Layers.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAString.h"
|
||||
@ -159,6 +160,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
|
||||
@ -922,6 +924,53 @@ nsContentUtils::GetParserService()
|
||||
return sParserService;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that parses a sandbox attribute (of an <iframe> or
|
||||
* a CSP directive) and converts it to the set of flags used internally.
|
||||
*
|
||||
* @param aAttribute the value of the sandbox attribute
|
||||
* @return the set of flags
|
||||
*/
|
||||
PRUint32
|
||||
nsContentUtils::ParseSandboxAttributeToFlags(const nsAString& aSandboxAttrValue)
|
||||
{
|
||||
// If there's a sandbox attribute at all (and there is if this is being
|
||||
// called), start off by setting all the restriction flags.
|
||||
PRUint32 out = SANDBOXED_NAVIGATION |
|
||||
SANDBOXED_TOPLEVEL_NAVIGATION |
|
||||
SANDBOXED_PLUGINS |
|
||||
SANDBOXED_ORIGIN |
|
||||
SANDBOXED_FORMS |
|
||||
SANDBOXED_SCRIPTS |
|
||||
SANDBOXED_AUTOMATIC_FEATURES;
|
||||
|
||||
if (!aSandboxAttrValue.IsEmpty()) {
|
||||
// The separator optional flag is used because the HTML5 spec says any
|
||||
// whitespace is ok as a separator, which is what this does.
|
||||
HTMLSplitOnSpacesTokenizer tokenizer(aSandboxAttrValue, ' ',
|
||||
nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>::SEPARATOR_OPTIONAL);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
nsDependentSubstring token = tokenizer.nextToken();
|
||||
|
||||
if (token.LowerCaseEqualsLiteral("allow-same-origin")) {
|
||||
out &= ~SANDBOXED_ORIGIN;
|
||||
} else if (token.LowerCaseEqualsLiteral("allow-forms")) {
|
||||
out &= ~SANDBOXED_FORMS;
|
||||
} else if (token.LowerCaseEqualsLiteral("allow-scripts")) {
|
||||
// allow-scripts removes both SANDBOXED_SCRIPTS and
|
||||
// SANDBOXED_AUTOMATIC_FEATURES.
|
||||
out &= ~SANDBOXED_SCRIPTS;
|
||||
out &= ~SANDBOXED_AUTOMATIC_FEATURES;
|
||||
} else if (token.LowerCaseEqualsLiteral("allow-top-navigation")) {
|
||||
out &= ~SANDBOXED_TOPLEVEL_NAVIGATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XTF
|
||||
nsIXTFService*
|
||||
nsContentUtils::GetXTFService()
|
||||
@ -4557,7 +4606,7 @@ nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true);
|
||||
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true, false);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -5707,9 +5756,9 @@ nsContentUtils::CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel
|
||||
|
||||
NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
|
||||
|
||||
nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
|
||||
nsresult rv = oldPrincipal->CheckMayLoad(newURI, false, false);
|
||||
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -5880,13 +5929,13 @@ nsContentUtils::GetDocumentFromScriptContext(nsIScriptContext *aScriptContext)
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel)
|
||||
nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal)
|
||||
{
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false));
|
||||
return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false, aAllowIfInheritsPrincipal));
|
||||
}
|
||||
|
||||
nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
|
||||
@ -6555,6 +6604,18 @@ nsContentUtils::FindInternalContentViewer(const char* aType,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_MEDIA_PLUGINS
|
||||
if (nsHTMLMediaElement::IsMediaPluginsEnabled() &&
|
||||
nsHTMLMediaElement::IsMediaPluginsType(nsDependentCString(aType))) {
|
||||
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
||||
if (docFactory && aLoaderType) {
|
||||
*aLoaderType = TYPE_CONTENT;
|
||||
}
|
||||
return docFactory.forget();
|
||||
}
|
||||
#endif // MOZ_MEDIA_PLUGINS
|
||||
|
||||
#endif // MOZ_MEDIA
|
||||
|
||||
return NULL;
|
||||
@ -6610,7 +6671,8 @@ bool
|
||||
nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
bool aSetUpForAboutBlank)
|
||||
bool aSetUpForAboutBlank,
|
||||
bool aForceOwner)
|
||||
{
|
||||
//
|
||||
// Set the owner of the channel, but only for channels that can't
|
||||
@ -6628,13 +6690,25 @@ nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
|
||||
// (Currently chrome URIs set the owner when they are created!
|
||||
// So setting a NULL owner would be bad!)
|
||||
//
|
||||
// If aForceOwner is true, the owner will be set, even for a channel that
|
||||
// can provide its own security context. This is used for the HTML5 IFRAME
|
||||
// sandbox attribute, so we can force the channel (and its document) to
|
||||
// explicitly have a null principal.
|
||||
bool inherit;
|
||||
// We expect URIInheritsSecurityContext to return success for an
|
||||
// about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
|
||||
// This condition needs to match the one in nsDocShell::InternalLoad where
|
||||
// we're checking for things that will use the owner.
|
||||
if (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherit)) &&
|
||||
(inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))) {
|
||||
if (aForceOwner || ((NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherit)) &&
|
||||
(inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))))) {
|
||||
#ifdef DEBUG
|
||||
// Assert that aForceOwner is only set for null principals
|
||||
if (aForceOwner) {
|
||||
nsCOMPtr<nsIURI> ownerURI;
|
||||
nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(ownerURI));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) && SchemeIs(ownerURI, NS_NULLPRINCIPAL_SCHEME));
|
||||
}
|
||||
#endif
|
||||
aChannel->SetOwner(aLoadingPrincipal);
|
||||
return true;
|
||||
}
|
||||
@ -6648,7 +6722,7 @@ nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
|
||||
// based on its own codebase later.
|
||||
//
|
||||
if (URIIsLocalFile(aURI) && aLoadingPrincipal &&
|
||||
NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false)) &&
|
||||
NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false, false)) &&
|
||||
// One more check here. CheckMayLoad will always return true for the
|
||||
// system principal, but we do NOT want to inherit in that case.
|
||||
!IsSystemPrincipal(aLoadingPrincipal)) {
|
||||
|
@ -743,10 +743,10 @@ nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel, bool aAllowDataURI)
|
||||
}
|
||||
|
||||
if (!mHasBeenCrossSite &&
|
||||
NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false)) &&
|
||||
NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false, false)) &&
|
||||
(originalURI == uri ||
|
||||
NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(originalURI,
|
||||
false)))) {
|
||||
false, false)))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,7 @@
|
||||
|
||||
#include "imgILoader.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -1064,18 +1065,12 @@ nsExternalResourceMap::PendingLoad::StartLoad(nsIURI* aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Allow data URIs (let them skip the CheckMayLoad call), since we want
|
||||
// Allow data URIs and other URI's that inherit their principal by passing
|
||||
// true as the 3rd argument of CheckMayLoad, since we want
|
||||
// to allow external resources from data URIs regardless of the difference
|
||||
// in URI scheme.
|
||||
bool doesInheritSecurityContext;
|
||||
rv =
|
||||
NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&doesInheritSecurityContext);
|
||||
if (NS_FAILED(rv) || !doesInheritSecurityContext) {
|
||||
rv = requestingPrincipal->CheckMayLoad(aURI, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
rv = requestingPrincipal->CheckMayLoad(aURI, true, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OTHER,
|
||||
@ -2412,6 +2407,15 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
||||
|
||||
mChannel = aChannel;
|
||||
|
||||
// If this document is being loaded by a docshell, copy its sandbox flags
|
||||
// to the document. These are immutable after being set here.
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aContainer);
|
||||
|
||||
if (docShell) {
|
||||
nsresult rv = docShell->GetSandboxFlags(&mSandboxFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsresult rv = InitCSP();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -2720,6 +2724,24 @@ nsDocument::SetContentType(const nsAString& aContentType)
|
||||
SetContentTypeInternal(NS_ConvertUTF16toUTF8(aContentType));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::GetAllowPlugins(bool * aAllowPlugins)
|
||||
{
|
||||
// First, we ask our docshell if it allows plugins.
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
|
||||
|
||||
if (docShell) {
|
||||
docShell->GetAllowPlugins(aAllowPlugins);
|
||||
|
||||
// If the docshell allows plugins, we check whether
|
||||
// we are sandboxed and plugins should not be allowed.
|
||||
if (*aAllowPlugins)
|
||||
*aAllowPlugins = !(mSandboxFlags & SANDBOXED_PLUGINS);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Return true if the document is in the focused top-level window, and is an
|
||||
* ancestor of the focused DOMWindow. */
|
||||
NS_IMETHODIMP
|
||||
@ -6415,6 +6437,12 @@ nsDocument::GetXMLDeclaration(nsAString& aVersion, nsAString& aEncoding,
|
||||
bool
|
||||
nsDocument::IsScriptEnabled()
|
||||
{
|
||||
// If this document is sandboxed without 'allow-scripts'
|
||||
// script is not enabled
|
||||
if (mSandboxFlags & SANDBOXED_SCRIPTS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
|
||||
NS_ENSURE_TRUE(sm, false);
|
||||
|
||||
@ -8492,10 +8520,13 @@ DispatchFullScreenChange(nsIDocument* aTarget)
|
||||
NS_IMETHODIMP
|
||||
nsDocument::MozCancelFullScreen()
|
||||
{
|
||||
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
|
||||
return NS_OK;
|
||||
// Only perform fullscreen changes if we're running in a webapp
|
||||
// same-origin to the web app, or if we're in a user generated event
|
||||
// handler.
|
||||
if (NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
|
||||
nsContentUtils::IsRequestFullScreenAllowed()) {
|
||||
RestorePreviousFullScreenState();
|
||||
}
|
||||
RestorePreviousFullScreenState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -9124,6 +9155,7 @@ nsDocument::RequestFullScreen(Element* aElement,
|
||||
// trusted and so are automatically approved.
|
||||
if (!mIsApprovedForFullscreen) {
|
||||
mIsApprovedForFullscreen =
|
||||
!Preferences::GetBool("full-screen-api.approval-required") ||
|
||||
NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
|
||||
nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
|
||||
}
|
||||
|
@ -567,6 +567,8 @@ public:
|
||||
nsIPresShell** aInstancePtrResult);
|
||||
virtual void DeleteShell();
|
||||
|
||||
virtual nsresult GetAllowPlugins(bool* aAllowPlugins);
|
||||
|
||||
virtual nsresult SetSubDocumentFor(Element* aContent,
|
||||
nsIDocument* aSubDoc);
|
||||
virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const;
|
||||
|
@ -86,6 +86,9 @@
|
||||
#include "nsIAppsService.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsHTMLIFrameElement.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -288,6 +291,7 @@ NS_INTERFACE_MAP_END
|
||||
|
||||
nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
|
||||
: mOwnerContent(aOwner)
|
||||
, mDetachedSubdocViews(nullptr)
|
||||
, mDepthTooGreat(false)
|
||||
, mIsTopLevelContent(false)
|
||||
, mDestroyCalled(false)
|
||||
@ -450,6 +454,30 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo));
|
||||
NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
|
||||
|
||||
// Is this an <iframe> with a sandbox attribute or a parent which is
|
||||
// sandboxed ?
|
||||
nsHTMLIFrameElement* iframe =
|
||||
nsHTMLIFrameElement::FromContent(mOwnerContent);
|
||||
|
||||
PRUint32 sandboxFlags = 0;
|
||||
|
||||
if (iframe) {
|
||||
sandboxFlags = iframe->GetSandboxFlags();
|
||||
|
||||
PRUint32 parentSandboxFlags = iframe->OwnerDoc()->GetSandboxFlags();
|
||||
|
||||
if (sandboxFlags || parentSandboxFlags) {
|
||||
// The child can only add restrictions, not remove them.
|
||||
sandboxFlags |= parentSandboxFlags;
|
||||
|
||||
mDocShell->SetSandboxFlags(sandboxFlags);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is an <iframe> and it's sandboxed with respect to origin
|
||||
// we will set it up with a null principal later in nsDocShell::DoURILoad.
|
||||
// We do it there to correctly sandbox content that was loaded into
|
||||
// the iframe via other methods than the src attribute.
|
||||
// We'll use our principal, not that of the document loaded inside us. This
|
||||
// is very important; needed to prevent XSS attacks on documents loaded in
|
||||
// subframes!
|
||||
@ -2372,8 +2400,24 @@ nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
|
||||
{
|
||||
MOZ_ASSERT(!mRemoteBrowser);
|
||||
MOZ_ASSERT(!mCurrentRemoteFrame);
|
||||
mRemoteFrame = true;
|
||||
mRemoteBrowser = static_cast<TabParent*>(aTabParent);
|
||||
|
||||
ShowRemoteFrame(nsIntSize(0, 0));
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::SetDetachedSubdocView(nsIView* aDetachedViews,
|
||||
nsIDocument* aContainerDoc)
|
||||
{
|
||||
mDetachedSubdocViews = aDetachedViews;
|
||||
mContainerDocWhileDetached = aContainerDoc;
|
||||
}
|
||||
|
||||
nsIView*
|
||||
nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
|
||||
{
|
||||
NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
|
||||
return mDetachedSubdocViews;
|
||||
}
|
||||
|
||||
|
@ -268,6 +268,25 @@ public:
|
||||
*/
|
||||
void SetRemoteBrowser(nsITabParent* aTabParent);
|
||||
|
||||
/**
|
||||
* Stashes a detached view on the frame loader. We do this when we're
|
||||
* destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
|
||||
* being reframed we'll restore the detached view when it's recreated,
|
||||
* otherwise we'll discard the old presentation and set the detached
|
||||
* subdoc view to null. aContainerDoc is the document containing the
|
||||
* the subdoc frame. This enables us to detect when the containing
|
||||
* document has changed during reframe, so we can discard the presentation
|
||||
* in that case.
|
||||
*/
|
||||
void SetDetachedSubdocView(nsIView* aDetachedView,
|
||||
nsIDocument* aContainerDoc);
|
||||
|
||||
/**
|
||||
* Retrieves the detached view and the document containing the view,
|
||||
* as set by SetDetachedSubdocView().
|
||||
*/
|
||||
nsIView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
|
||||
|
||||
private:
|
||||
|
||||
void SetOwnerContent(mozilla::dom::Element* aContent);
|
||||
@ -326,6 +345,16 @@ public:
|
||||
nsRefPtr<nsFrameMessageManager> mMessageManager;
|
||||
nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
|
||||
private:
|
||||
// Stores the root view of the subdocument while the subdocument is being
|
||||
// reframed. Used to restore the presentation after reframing.
|
||||
nsIView* mDetachedSubdocViews;
|
||||
// Stores the containing document of the frame corresponding to this
|
||||
// frame loader. This is reference is kept valid while the subframe's
|
||||
// presentation is detached and stored in mDetachedSubdocViews. This
|
||||
// enables us to detect whether the frame has moved documents during
|
||||
// a reframe, so that we know not to restore the presentation.
|
||||
nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
|
||||
|
||||
bool mDepthTooGreat : 1;
|
||||
bool mIsTopLevelContent : 1;
|
||||
bool mDestroyCalled : 1;
|
||||
|
@ -70,7 +70,11 @@ GK_ATOM(align, "align")
|
||||
GK_ATOM(alink, "alink")
|
||||
GK_ATOM(all, "all")
|
||||
GK_ATOM(allowevents, "allowevents")
|
||||
GK_ATOM(allowforms, "allow-forms")
|
||||
GK_ATOM(allownegativeassertions, "allownegativeassertions")
|
||||
GK_ATOM(allowsameorigin, "allow-same-origin")
|
||||
GK_ATOM(allowscripts, "allow-scripts")
|
||||
GK_ATOM(allowtopnavigation, "allow-top-navigation")
|
||||
GK_ATOM(allowuntrusted, "allowuntrusted")
|
||||
GK_ATOM(alt, "alt")
|
||||
GK_ATOM(alternate, "alternate")
|
||||
@ -848,6 +852,7 @@ GK_ATOM(rule, "rule")
|
||||
GK_ATOM(rules, "rules")
|
||||
GK_ATOM(s, "s")
|
||||
GK_ATOM(samp, "samp")
|
||||
GK_ATOM(sandbox, "sandbox")
|
||||
GK_ATOM(sbattr, "sbattr")
|
||||
GK_ATOM(scale, "scale")
|
||||
GK_ATOM(scan, "scan")
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "nsHyphenator.h"
|
||||
|
||||
nsLineBreaker::nsLineBreaker()
|
||||
: mCurrentWordLangGroup(nullptr),
|
||||
: mCurrentWordLanguage(nullptr),
|
||||
mCurrentWordContainsMixedLang(false),
|
||||
mCurrentWordContainsComplexChar(false),
|
||||
mAfterBreakableSpace(false), mBreakHere(false),
|
||||
@ -77,7 +77,7 @@ nsLineBreaker::FlushCurrentWord()
|
||||
breakState.Elements());
|
||||
}
|
||||
|
||||
bool autoHyphenate = mCurrentWordLangGroup &&
|
||||
bool autoHyphenate = mCurrentWordLanguage &&
|
||||
!mCurrentWordContainsMixedLang;
|
||||
PRUint32 i;
|
||||
for (i = 0; autoHyphenate && i < mTextItems.Length(); ++i) {
|
||||
@ -88,7 +88,7 @@ nsLineBreaker::FlushCurrentWord()
|
||||
}
|
||||
if (autoHyphenate) {
|
||||
nsRefPtr<nsHyphenator> hyphenator =
|
||||
nsHyphenationManager::Instance()->GetHyphenator(mCurrentWordLangGroup);
|
||||
nsHyphenationManager::Instance()->GetHyphenator(mCurrentWordLanguage);
|
||||
if (hyphenator) {
|
||||
FindHyphenationPoints(hyphenator,
|
||||
mCurrentWord.Elements(),
|
||||
@ -140,12 +140,12 @@ nsLineBreaker::FlushCurrentWord()
|
||||
mTextItems.Clear();
|
||||
mCurrentWordContainsComplexChar = false;
|
||||
mCurrentWordContainsMixedLang = false;
|
||||
mCurrentWordLangGroup = nullptr;
|
||||
mCurrentWordLanguage = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32 aLength,
|
||||
nsLineBreaker::AppendText(nsIAtom* aHyphenationLanguage, const PRUnichar* aText, PRUint32 aLength,
|
||||
PRUint32 aFlags, nsILineBreakSink* aSink)
|
||||
{
|
||||
NS_ASSERTION(aLength > 0, "Appending empty text...");
|
||||
@ -161,7 +161,7 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32
|
||||
if (!mCurrentWordContainsComplexChar && IsComplexChar(aText[offset])) {
|
||||
mCurrentWordContainsComplexChar = true;
|
||||
}
|
||||
UpdateCurrentWordLangGroup(aLangGroup);
|
||||
UpdateCurrentWordLanguage(aHyphenationLanguage);
|
||||
++offset;
|
||||
}
|
||||
|
||||
@ -211,8 +211,10 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32
|
||||
bool wordHasComplexChar = false;
|
||||
|
||||
nsRefPtr<nsHyphenator> hyphenator;
|
||||
if ((aFlags & BREAK_USE_AUTO_HYPHENATION) && !(aFlags & BREAK_SUPPRESS_INSIDE)) {
|
||||
hyphenator = nsHyphenationManager::Instance()->GetHyphenator(aLangGroup);
|
||||
if ((aFlags & BREAK_USE_AUTO_HYPHENATION) &&
|
||||
!(aFlags & BREAK_SUPPRESS_INSIDE) &&
|
||||
aHyphenationLanguage) {
|
||||
hyphenator = nsHyphenationManager::Instance()->GetHyphenator(aHyphenationLanguage);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@ -275,7 +277,7 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32
|
||||
mTextItems.AppendElement(TextItem(aSink, wordStart, len, aFlags));
|
||||
// Ensure that the break-before for this word is written out
|
||||
offset = wordStart + 1;
|
||||
UpdateCurrentWordLangGroup(aLangGroup);
|
||||
UpdateCurrentWordLanguage(aHyphenationLanguage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -311,7 +313,7 @@ nsLineBreaker::FindHyphenationPoints(nsHyphenator *aHyphenator,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aLength,
|
||||
nsLineBreaker::AppendText(nsIAtom* aHyphenationLanguage, const PRUint8* aText, PRUint32 aLength,
|
||||
PRUint32 aFlags, nsILineBreakSink* aSink)
|
||||
{
|
||||
NS_ASSERTION(aLength > 0, "Appending empty text...");
|
||||
@ -321,7 +323,7 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aL
|
||||
nsAutoString str;
|
||||
const char* cp = reinterpret_cast<const char*>(aText);
|
||||
CopyASCIItoUTF16(nsDependentCSubstring(cp, cp + aLength), str);
|
||||
return AppendText(aLangGroup, str.get(), aLength, aFlags, aSink);
|
||||
return AppendText(aHyphenationLanguage, str.get(), aLength, aFlags, aSink);
|
||||
}
|
||||
|
||||
PRUint32 offset = 0;
|
||||
@ -446,12 +448,12 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aL
|
||||
}
|
||||
|
||||
void
|
||||
nsLineBreaker::UpdateCurrentWordLangGroup(nsIAtom *aLangGroup)
|
||||
nsLineBreaker::UpdateCurrentWordLanguage(nsIAtom *aHyphenationLanguage)
|
||||
{
|
||||
if (mCurrentWordLangGroup && mCurrentWordLangGroup != aLangGroup) {
|
||||
if (mCurrentWordLanguage && mCurrentWordLanguage != aHyphenationLanguage) {
|
||||
mCurrentWordContainsMixedLang = true;
|
||||
} else {
|
||||
mCurrentWordLangGroup = aLangGroup;
|
||||
mCurrentWordLanguage = aHyphenationLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ nsNodeInfo::nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
|
||||
PRUint16 aNodeType, nsIAtom* aExtraName,
|
||||
nsNodeInfoManager *aOwnerManager)
|
||||
{
|
||||
CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
|
||||
CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
|
||||
NS_ABORT_IF_FALSE(aOwnerManager, "Invalid aOwnerManager");
|
||||
|
||||
// Initialize mInner
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "plhash.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
class nsFixedSizeAllocator;
|
||||
|
||||
@ -63,45 +65,49 @@ private:
|
||||
* this object, instead of always deleting the object we'll put the
|
||||
* object in the cache unless the cache is already full.
|
||||
*/
|
||||
void LastRelease();
|
||||
void LastRelease();
|
||||
};
|
||||
|
||||
#define CHECK_VALID_NODEINFO(_nodeType, _name, _namespaceID, _extraName) \
|
||||
NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE || \
|
||||
_nodeType == nsIDOMNode::ATTRIBUTE_NODE || \
|
||||
_nodeType == nsIDOMNode::TEXT_NODE || \
|
||||
_nodeType == nsIDOMNode::CDATA_SECTION_NODE || \
|
||||
_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE || \
|
||||
_nodeType == nsIDOMNode::COMMENT_NODE || \
|
||||
_nodeType == nsIDOMNode::DOCUMENT_NODE || \
|
||||
_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE || \
|
||||
_nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE || \
|
||||
_nodeType == PR_UINT16_MAX, \
|
||||
"Invalid nodeType"); \
|
||||
NS_ABORT_IF_FALSE((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE || \
|
||||
_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) == \
|
||||
(_extraName != nullptr), \
|
||||
"Supply aExtraName for and only for PIs and doctypes"); \
|
||||
NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE || \
|
||||
_nodeType == nsIDOMNode::ATTRIBUTE_NODE || \
|
||||
_nodeType == PR_UINT16_MAX || \
|
||||
aNamespaceID == kNameSpaceID_None, \
|
||||
"Only attributes and elements can be in a namespace"); \
|
||||
NS_ABORT_IF_FALSE(_name && _name != nsGkAtoms::_empty, "Invalid localName");\
|
||||
NS_ABORT_IF_FALSE(((_nodeType == nsIDOMNode::TEXT_NODE) == \
|
||||
(_name == nsGkAtoms::textTagName)) && \
|
||||
((_nodeType == nsIDOMNode::CDATA_SECTION_NODE) == \
|
||||
(_name == nsGkAtoms::cdataTagName)) && \
|
||||
((_nodeType == nsIDOMNode::COMMENT_NODE) == \
|
||||
(_name == nsGkAtoms::commentTagName)) && \
|
||||
((_nodeType == nsIDOMNode::DOCUMENT_NODE) == \
|
||||
(_name == nsGkAtoms::documentNodeName)) && \
|
||||
((_nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) == \
|
||||
(_name == nsGkAtoms::documentFragmentNodeName)) && \
|
||||
((_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) == \
|
||||
(_name == nsGkAtoms::documentTypeNodeName)) && \
|
||||
((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==\
|
||||
(_name == nsGkAtoms::processingInstructionTagName)), \
|
||||
"Wrong localName for nodeType");
|
||||
inline void
|
||||
CheckValidNodeInfo(PRUint16 aNodeType, nsIAtom *aName, PRInt32 aNamespaceID,
|
||||
nsIAtom* aExtraName)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
|
||||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
|
||||
aNodeType == nsIDOMNode::TEXT_NODE ||
|
||||
aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
|
||||
aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
|
||||
aNodeType == nsIDOMNode::COMMENT_NODE ||
|
||||
aNodeType == nsIDOMNode::DOCUMENT_NODE ||
|
||||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
|
||||
aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
|
||||
aNodeType == PR_UINT16_MAX,
|
||||
"Invalid nodeType");
|
||||
NS_ABORT_IF_FALSE((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
|
||||
aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
|
||||
!!aExtraName,
|
||||
"Supply aExtraName for and only for PIs and doctypes");
|
||||
NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
|
||||
aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
|
||||
aNodeType == PR_UINT16_MAX ||
|
||||
aNamespaceID == kNameSpaceID_None,
|
||||
"Only attributes and elements can be in a namespace");
|
||||
NS_ABORT_IF_FALSE(aName && aName != nsGkAtoms::_empty, "Invalid localName");
|
||||
NS_ABORT_IF_FALSE(((aNodeType == nsIDOMNode::TEXT_NODE) ==
|
||||
(aName == nsGkAtoms::textTagName)) &&
|
||||
((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
|
||||
(aName == nsGkAtoms::cdataTagName)) &&
|
||||
((aNodeType == nsIDOMNode::COMMENT_NODE) ==
|
||||
(aName == nsGkAtoms::commentTagName)) &&
|
||||
((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
|
||||
(aName == nsGkAtoms::documentNodeName)) &&
|
||||
((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
|
||||
(aName == nsGkAtoms::documentFragmentNodeName)) &&
|
||||
((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
|
||||
(aName == nsGkAtoms::documentTypeNodeName)) &&
|
||||
((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
|
||||
(aName == nsGkAtoms::processingInstructionTagName)),
|
||||
"Wrong localName for nodeType");
|
||||
}
|
||||
|
||||
#endif /* nsNodeInfo_h___ */
|
||||
|
@ -210,7 +210,7 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
|
||||
PRInt32 aNamespaceID, PRUint16 aNodeType,
|
||||
nsIAtom* aExtraName /* = nullptr */)
|
||||
{
|
||||
CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
|
||||
CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
|
||||
|
||||
nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType,
|
||||
aExtraName);
|
||||
@ -256,7 +256,7 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
|
||||
#ifdef DEBUG
|
||||
{
|
||||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
|
||||
CHECK_VALID_NODEINFO(aNodeType, nameAtom, aNamespaceID, nullptr);
|
||||
CheckValidNodeInfo(aNodeType, nameAtom, aNamespaceID, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1069,88 +1069,92 @@ nsObjectLoadingContent::ObjectState() const
|
||||
return NS_EVENT_STATE_LOADING;
|
||||
}
|
||||
|
||||
// Helper to call CheckURILoad on URI -> BaseURI and BaseURI -> Origin
|
||||
bool nsObjectLoadingContent::CheckObjectURIs(PRInt16 *aContentPolicy,
|
||||
PRInt32 aContentPolicyType)
|
||||
bool
|
||||
nsObjectLoadingContent::CheckLoadPolicy(PRInt16 *aContentPolicy)
|
||||
{
|
||||
if (!aContentPolicy || !mURI) {
|
||||
NS_NOTREACHED("Doing it wrong");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ASSERTION(thisContent, "Must be an instance of content");
|
||||
|
||||
nsCOMPtr<nsIURI> docBaseURI = thisContent->GetBaseURI();
|
||||
nsIDocument* doc = thisContent->OwnerDoc();
|
||||
|
||||
// Must have these to load
|
||||
if (!aContentPolicy || !mBaseURI) {
|
||||
*aContentPolicy = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OBJECT,
|
||||
mURI,
|
||||
doc->NodePrincipal(),
|
||||
thisContent,
|
||||
mContentType,
|
||||
nullptr, //extra
|
||||
aContentPolicy,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
nsContentUtils::GetSecurityManager());
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
if (NS_CP_REJECTED(*aContentPolicy)) {
|
||||
nsCAutoString uri;
|
||||
nsCAutoString baseUri;
|
||||
mURI->GetSpec(uri);
|
||||
mURI->GetSpec(baseUri);
|
||||
LOG(("OBJLC [%p]: Content policy denied load of %s (base %s)",
|
||||
this, uri.get(), baseUri.get()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret;
|
||||
if (!URIEquals(mBaseURI, docBaseURI)) {
|
||||
// If our object sets a new baseURI, make sure that base URI could be
|
||||
// loaded by the document
|
||||
ret = CheckURILoad(mBaseURI, aContentPolicy, aContentPolicyType);
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mURI) {
|
||||
return CheckURILoad(mURI, aContentPolicy, aContentPolicyType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nsObjectLoadingContent::CheckURILoad(nsIURI *aURI,
|
||||
PRInt16 *aContentPolicy,
|
||||
PRInt32 aContentPolicyType)
|
||||
bool
|
||||
nsObjectLoadingContent::CheckProcessPolicy(PRInt16 *aContentPolicy)
|
||||
{
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ASSERTION(secMan, "No security manager!?");
|
||||
if (!aContentPolicy) {
|
||||
NS_NOTREACHED("Null out variable");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ASSERTION(thisContent, "Must be an instance of content");
|
||||
|
||||
nsCOMPtr<nsIURI> docBaseURI = thisContent->GetBaseURI();
|
||||
|
||||
nsIDocument* doc = thisContent->OwnerDoc();
|
||||
nsresult rv =
|
||||
secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), aURI, 0);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCAutoString uri;
|
||||
nsCAutoString baseUri;
|
||||
aURI->GetSpec(uri);
|
||||
aURI->GetSpec(baseUri);
|
||||
LOG(("OBJLC [%p]: CheckLoadURIWithPrincipal denied load of %s (base %s)",
|
||||
this, uri.get(), baseUri.get()));
|
||||
return false;
|
||||
PRInt32 objectType;
|
||||
switch (mType) {
|
||||
case eType_Image:
|
||||
objectType = nsIContentPolicy::TYPE_IMAGE;
|
||||
break;
|
||||
case eType_Document:
|
||||
objectType = nsIContentPolicy::TYPE_DOCUMENT;
|
||||
break;
|
||||
case eType_Plugin:
|
||||
objectType = nsIContentPolicy::TYPE_OBJECT;
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Calling checkProcessPolicy with a unloadable type");
|
||||
return false;
|
||||
}
|
||||
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; // default permit
|
||||
rv = NS_CheckContentLoadPolicy(aContentPolicyType,
|
||||
aURI,
|
||||
*aContentPolicy = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv =
|
||||
NS_CheckContentProcessPolicy(objectType,
|
||||
mURI,
|
||||
doc->NodePrincipal(),
|
||||
static_cast<nsIImageLoadingContent*>(this),
|
||||
mContentType,
|
||||
nullptr, //extra
|
||||
&shouldLoad,
|
||||
aContentPolicy,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
secMan);
|
||||
nsContentUtils::GetSecurityManager());
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
if (aContentPolicy) {
|
||||
*aContentPolicy = shouldLoad;
|
||||
}
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
nsCAutoString uri;
|
||||
nsCAutoString baseUri;
|
||||
aURI->GetSpec(uri);
|
||||
aURI->GetSpec(baseUri);
|
||||
LOG(("OBJLC [%p]: Content policy denied load of %s (base %s)",
|
||||
this, uri.get(), baseUri.get()));
|
||||
|
||||
if (NS_CP_REJECTED(*aContentPolicy)) {
|
||||
LOG(("OBJLC [%p]: CheckContentProcessPolicy rejected load", this));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1169,6 +1173,7 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
nsCOMPtr<nsIURI> newBaseURI;
|
||||
ObjectType newType;
|
||||
bool isJava = false;
|
||||
// Set if this state can't be used to load anything, forces eType_Null
|
||||
bool stateInvalid = false;
|
||||
// Indicates what parameters changed.
|
||||
@ -1189,11 +1194,13 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
///
|
||||
if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
|
||||
newMime.AssignLiteral("application/x-java-vm");
|
||||
isJava = true;
|
||||
} else {
|
||||
nsAutoString typeAttr;
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, typeAttr);
|
||||
if (!typeAttr.IsEmpty()) {
|
||||
CopyUTF16toUTF8(typeAttr, newMime);
|
||||
isJava = nsPluginHost::IsJavaMIMEType(newMime.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1201,13 +1208,17 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
/// classID
|
||||
///
|
||||
|
||||
bool usingClassID = false;
|
||||
if (caps & eSupportClassID) {
|
||||
nsAutoString classIDAttr;
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::classid, classIDAttr);
|
||||
if (!classIDAttr.IsEmpty()) {
|
||||
usingClassID = true;
|
||||
if (NS_FAILED(TypeForClassID(classIDAttr, newMime))) {
|
||||
// Our classid support is limited to 'java:' ids
|
||||
rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
StringBeginsWith(classIDAttr, NS_LITERAL_STRING("java:"))) {
|
||||
newMime.Assign("application/x-java-vm");
|
||||
isJava = true;
|
||||
} else {
|
||||
// XXX(johns): Our de-facto behavior since forever was to refuse to load
|
||||
// Objects who don't have a classid we support, regardless of other type
|
||||
// or uri info leads to a valid plugin.
|
||||
@ -1261,13 +1272,16 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
|
||||
nsAutoString uriStr;
|
||||
// Different elements keep this in various locations
|
||||
if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
|
||||
if (isJava) {
|
||||
// Applet tags and embed/object with explicit java MIMEs have
|
||||
// src/data attributes that are not parsed as URIs, so we will
|
||||
// act as if URI is null
|
||||
} else if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, uriStr);
|
||||
} else if (thisContent->NodeInfo()->Equals(nsGkAtoms::embed)) {
|
||||
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, uriStr);
|
||||
} else if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
|
||||
// Applet tags have no URI, and their 'code=' parameter is not parsed as one
|
||||
} else {
|
||||
// Applet tags should always have a java MIME type at this point
|
||||
NS_NOTREACHED("Unrecognized plugin-loading tag");
|
||||
}
|
||||
|
||||
@ -1369,20 +1383,21 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
mChannel->SetContentType(newMime);
|
||||
} else {
|
||||
newMime = channelType;
|
||||
if (nsPluginHost::IsJavaMIMEType(newMime.get())) {
|
||||
// Java does not load with a channel, and being java retroactively changes
|
||||
// how we may have interpreted the codebase to construct this URI above.
|
||||
// Because the behavior here is more or less undefined, play it safe and
|
||||
// reject the load.
|
||||
LOG(("OBJLC [%p]: Refusing to load with channel with java MIME",
|
||||
this));
|
||||
stateInvalid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isJava = nsPluginHost::IsJavaMIMEType(newMime.get());
|
||||
if (useChannel && (!mChannel || isJava)) {
|
||||
// Sanity checks
|
||||
// - Java does not load with a channel, and being java retroactively changes
|
||||
// how we may have interpreted the codebase to construct this URI above.
|
||||
// Because the behavior here is more or less undefined, play it safe and
|
||||
// reject the load.
|
||||
//
|
||||
// - (useChannel && !mChannel) is true if a channel was opened but was
|
||||
// subsequently invalidated
|
||||
// in that case.
|
||||
if (useChannel && !mChannel) {
|
||||
// - (useChannel && !mChannel) is true if a channel was opened but
|
||||
// is no longer around, in which case we can't load.
|
||||
stateInvalid = true;
|
||||
}
|
||||
|
||||
@ -1395,13 +1410,10 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
// use that type.
|
||||
// 3) Otherwise, See if we can load this as a plugin without a channel
|
||||
// (image/document types always need a channel).
|
||||
// - If we have indication this is a plugin (mime, extension, or classID)
|
||||
// - If we have indication this is a plugin (mime, extension)
|
||||
// AND:
|
||||
// - We have eAllowPluginSkipChannel OR
|
||||
// - We have no URI in the first place OR
|
||||
// - We're loading based on classID
|
||||
// XXX(johns): Legacy behavior is to skip channel loading if we have
|
||||
// a classID. I don't know why.
|
||||
// - We have no URI in the first place (including java)
|
||||
// 3) Otherwise, if we have a URI, set type to loading to indicate
|
||||
// we'd need a channel to proceed.
|
||||
// 4) Otherwise, type null to indicate unloadable content (fallback)
|
||||
@ -1411,8 +1423,6 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
// are not going to open a channel for it. The old objLC code did this (in a
|
||||
// less obviously-intended way), so it's probably best not to change our
|
||||
// behavior at this point.
|
||||
// We ALSO skip channel loading for objects whose type is found by ClassID
|
||||
// (We only support a tiny subset of classid: java and ActiveX, above)
|
||||
//
|
||||
|
||||
if (stateInvalid) {
|
||||
@ -1421,7 +1431,7 @@ nsObjectLoadingContent::UpdateObjectParameters()
|
||||
// If useChannel is set above, we considered it in setting newMime
|
||||
newType = GetTypeOfContent(newMime);
|
||||
LOG(("OBJLC [%p]: Using channel type", this));
|
||||
} else if (((caps & eAllowPluginSkipChannel) || !newURI || usingClassID) &&
|
||||
} else if (((caps & eAllowPluginSkipChannel) || !newURI) &&
|
||||
(GetTypeOfContent(newMime) == eType_Plugin)) {
|
||||
newType = eType_Plugin;
|
||||
LOG(("OBJLC [%p]: Skipping loading channel, type plugin", this));
|
||||
@ -1519,9 +1529,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
|
||||
ParameterUpdateFlags stateChange = UpdateObjectParameters();
|
||||
|
||||
// If nothing changed and we are not force-loading, or we're in state loading
|
||||
// but continuing to wait on a channel, we're done
|
||||
if ((!stateChange && !aForceLoad) || (mType == eType_Loading && mChannel)) {
|
||||
if (!stateChange && !aForceLoad) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1564,6 +1572,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Determine what's going on with our channel
|
||||
if (stateChange & eParamChannelChanged) {
|
||||
// If the channel params changed, throw away the channel, but unset
|
||||
// mChannelLoaded so we'll still try to open a new one for this load if
|
||||
@ -1575,6 +1584,10 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
// away. mChannelLoaded will indicate that we tried to load a channel at one
|
||||
// point so we wont recurse
|
||||
CloseChannel();
|
||||
} else if (mType == eType_Loading && mChannel) {
|
||||
// We're still waiting on a channel load, already opened one, and
|
||||
// channel parameters didn't change
|
||||
return NS_OK;
|
||||
} else if (mChannelLoaded && mChannel != aLoadingChannel) {
|
||||
// The only time we should have a loaded channel with a changed state is
|
||||
// when the channel has just opened -- in which case this call should
|
||||
@ -1587,40 +1600,33 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
// Security checks
|
||||
//
|
||||
|
||||
// NOTE For eType_Loading we'll try all three types, as we want to go ahead
|
||||
// with the channel if it could be any acceptable type. This type is
|
||||
// passed to OpenChannel() as the LoadType. We pass through LoadObject
|
||||
// again once the channel is opened and we're actually loading, so if
|
||||
// the final URI doesn't pass the now-known type, we'll abort.
|
||||
PRInt32 policyType;
|
||||
if (mType != eType_Null) {
|
||||
bool allowLoad = false;
|
||||
PRInt16 contentPolicy = nsIContentPolicy::ACCEPT;
|
||||
PRUint32 caps = GetCapabilities();
|
||||
bool supportImage = caps & eSupportImages;
|
||||
bool supportDoc = (caps & eSupportDocuments) || (caps & eSupportSVG);
|
||||
bool supportPlugin = caps & eSupportPlugins;
|
||||
if (mType == eType_Image || (mType == eType_Loading && supportImage)) {
|
||||
policyType = nsIContentPolicy::TYPE_IMAGE;
|
||||
allowLoad = CheckObjectURIs(&contentPolicy, policyType);
|
||||
bool allowLoad = false;
|
||||
// We check load policy before opening a channel, and process policy before
|
||||
// going ahead with any final-type load
|
||||
if (mType == eType_Loading) {
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
if (!secMan) {
|
||||
NS_NOTREACHED("No security manager?");
|
||||
} else {
|
||||
rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(),
|
||||
mURI, 0);
|
||||
allowLoad = NS_SUCCEEDED(rv) && CheckLoadPolicy(&contentPolicy);
|
||||
}
|
||||
} else {
|
||||
allowLoad = CheckProcessPolicy(&contentPolicy);
|
||||
}
|
||||
if (!allowLoad &&
|
||||
(mType == eType_Document || (mType == eType_Loading && supportDoc))) {
|
||||
contentPolicy = nsIContentPolicy::ACCEPT;
|
||||
policyType = nsIContentPolicy::TYPE_SUBDOCUMENT;
|
||||
allowLoad = CheckObjectURIs(&contentPolicy, policyType);
|
||||
}
|
||||
if (!allowLoad &&
|
||||
(mType == eType_Plugin || (mType == eType_Loading && supportPlugin))) {
|
||||
contentPolicy = nsIContentPolicy::ACCEPT;
|
||||
policyType = nsIContentPolicy::TYPE_OBJECT;
|
||||
allowLoad = CheckObjectURIs(&contentPolicy, policyType);
|
||||
}
|
||||
|
||||
|
||||
// Load denied, switch to fallback and set disabled/suppressed if applicable
|
||||
if (!allowLoad) {
|
||||
LOG(("OBJLC [%p]: Load denied by policy", this));
|
||||
mType = eType_Null;
|
||||
if (contentPolicy == nsIContentPolicy::REJECT_TYPE) {
|
||||
// XXX(johns) This is assuming that we were rejected by
|
||||
// nsContentBlocker, which rejects by type if permissions
|
||||
// reject plugins
|
||||
fallbackType = eFallbackUserDisabled;
|
||||
} else {
|
||||
fallbackType = eFallbackSuppressed;
|
||||
@ -1772,7 +1778,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
break;
|
||||
case eType_Loading:
|
||||
// If our type remains Loading, we need a channel to proceed
|
||||
rv = OpenChannel(policyType);
|
||||
rv = OpenChannel();
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("OBJLC [%p]: OpenChannel returned failure (%u)", this, rv));
|
||||
}
|
||||
@ -1841,7 +1847,7 @@ nsObjectLoadingContent::CloseChannel()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectLoadingContent::OpenChannel(PRInt32 aPolicyType)
|
||||
nsObjectLoadingContent::OpenChannel()
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
@ -1868,7 +1874,7 @@ nsObjectLoadingContent::OpenChannel(PRInt32 aPolicyType)
|
||||
if (csp) {
|
||||
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
|
||||
channelPolicy->SetContentSecurityPolicy(csp);
|
||||
channelPolicy->SetLoadType(aPolicyType);
|
||||
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
|
||||
}
|
||||
rv = NS_NewChannel(getter_AddRefs(chan), mURI, nullptr, group, this,
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
|
||||
@ -1942,7 +1948,11 @@ nsObjectLoadingContent::UnloadObject(bool aResetState)
|
||||
|
||||
if (aResetState) {
|
||||
CloseChannel();
|
||||
mChannelLoaded = false;
|
||||
mType = eType_Loading;
|
||||
mURI = mOriginalURI = mBaseURI = nullptr;
|
||||
mContentType.Truncate();
|
||||
mOriginalContentType.Truncate();
|
||||
}
|
||||
|
||||
// This call should be last as it may re-enter
|
||||
@ -2051,34 +2061,6 @@ nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType)
|
||||
return eType_Null;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
|
||||
nsACString& aType)
|
||||
{
|
||||
if (StringBeginsWith(aClassID, NS_LITERAL_STRING("java:"))) {
|
||||
// Supported if we have a java plugin
|
||||
aType.AssignLiteral("application/x-java-vm");
|
||||
nsresult rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
|
||||
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// If it starts with "clsid:", this is ActiveX content
|
||||
if (StringBeginsWith(aClassID, NS_LITERAL_STRING("clsid:"), nsCaseInsensitiveStringComparator())) {
|
||||
// Check if we have a plugin for that
|
||||
|
||||
if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-oleobject")))) {
|
||||
aType.AssignLiteral("application/x-oleobject");
|
||||
return NS_OK;
|
||||
}
|
||||
if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/oleobject")))) {
|
||||
aType.AssignLiteral("application/oleobject");
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsObjectFrame*
|
||||
nsObjectLoadingContent::GetExistingFrame()
|
||||
{
|
||||
@ -2495,7 +2477,6 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
|
||||
rv = topWindow->GetDocument(getter_AddRefs(topDocument));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDocument);
|
||||
nsIURI* topUri = topDoc->GetDocumentURI();
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
@ -267,10 +267,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
|
||||
/**
|
||||
* Opens the channel pointed to by mURI into mChannel.
|
||||
*
|
||||
* @param aPolicyType The value to be passed to channelPolicy->SetLoadType
|
||||
*/
|
||||
nsresult OpenChannel(PRInt32 aPolicyType);
|
||||
nsresult OpenChannel();
|
||||
|
||||
/**
|
||||
* Closes and releases references to mChannel and, if opened, mFinalListener
|
||||
@ -285,35 +283,23 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
bool ShouldPlay(FallbackType &aReason);
|
||||
|
||||
/**
|
||||
* Checks if a URI passes security checks and content policy, relative to
|
||||
* the current document's principal
|
||||
* Helper to check if our current URI passes policy
|
||||
*
|
||||
* @param aURI The URI to consider
|
||||
* @param aContentPolicy [in/out] A pointer to the initial content
|
||||
* policy, that will be updated to contain the
|
||||
* final determined policy
|
||||
* @param aContentPolicyType The 'contentType' parameter passed to
|
||||
* NS_CheckContentLoadPolicy
|
||||
* @param aContentPolicy [out] The result of the content policy decision
|
||||
*
|
||||
* @return true if this URI is acceptable for loading
|
||||
* @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
|
||||
*/
|
||||
bool CheckURILoad(nsIURI *aURI,
|
||||
PRInt16 *aContentPolicy,
|
||||
PRInt32 aContentPolicyType);
|
||||
bool CheckLoadPolicy(PRInt16 *aContentPolicy);
|
||||
|
||||
/**
|
||||
* Checks if the current mURI and mBaseURI pass content policy and security
|
||||
* checks for loading
|
||||
* Helper to check if the object passes process policy. Assumes we have a
|
||||
* final determined type.
|
||||
*
|
||||
* @param aContentPolicy [in/out] A pointer to the initial content
|
||||
* policy, that will be updated to contain the
|
||||
* final determined policy if a URL is rejected
|
||||
* @param aContentPolicyType The 'contentType' parameter passed to
|
||||
* NS_CheckContentLoadPolicy
|
||||
* @param aContentPolicy [out] The result of the content policy decision
|
||||
*
|
||||
* @return true if the URIs are acceptable for loading
|
||||
* @return true if call succeeded and NS_CP_ACCEPTED(*aContentPolicy)
|
||||
*/
|
||||
bool CheckObjectURIs(PRInt16 *aContentPolicy, PRInt32 aContentPolicyType);
|
||||
bool CheckProcessPolicy(PRInt16 *aContentPolicy);
|
||||
|
||||
/**
|
||||
* Checks whether the given type is a supported document type
|
||||
@ -362,16 +348,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
*/
|
||||
ObjectType GetTypeOfContent(const nsCString& aMIMEType);
|
||||
|
||||
/**
|
||||
* For a classid, returns the MIME type that can be used to instantiate
|
||||
* a plugin for this ID.
|
||||
*
|
||||
* @param aClassID The class ID in question
|
||||
* @param aType [out] The corresponding type, if the call is successful
|
||||
* @return NS_ERROR_NOT_AVAILABLE Unsupported class ID.
|
||||
*/
|
||||
nsresult TypeForClassID(const nsAString& aClassID, nsACString& aType);
|
||||
|
||||
/**
|
||||
* Gets the frame that's associated with this content node.
|
||||
* Does not flush.
|
||||
|
58
content/base/src/nsSandboxFlags.h
Normal file
58
content/base/src/nsSandboxFlags.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* Constant flags that describe how a document is sandboxed according to the
|
||||
* HTML5 spec.
|
||||
*/
|
||||
|
||||
#ifndef nsSandboxFlags_h___
|
||||
#define nsSandboxFlags_h___
|
||||
|
||||
/**
|
||||
* This flag prevents content from navigating browsing contexts other than
|
||||
* the sandboxed browsing context itself (or browsing contexts further
|
||||
* nested inside it), and the top-level browsing context.
|
||||
*/
|
||||
const unsigned long SANDBOXED_NAVIGATION = 0x1;
|
||||
|
||||
/**
|
||||
* This flag prevents content from navigating their top-level browsing
|
||||
* context.
|
||||
*/
|
||||
const unsigned long SANDBOXED_TOPLEVEL_NAVIGATION = 0x2;
|
||||
|
||||
/**
|
||||
* This flag prevents content from instantiating plugins, whether using the
|
||||
* embed element, the object element, the applet element, or through
|
||||
* navigation of a nested browsing context, unless those plugins can be
|
||||
* secured.
|
||||
*/
|
||||
const unsigned long SANDBOXED_PLUGINS = 0x4;
|
||||
|
||||
/**
|
||||
* This flag forces content into a unique origin, thus preventing it from
|
||||
* accessing other content from the same origin.
|
||||
* This flag also prevents script from reading from or writing to the
|
||||
* document.cookie IDL attribute, and blocks access to localStorage.
|
||||
*/
|
||||
const unsigned long SANDBOXED_ORIGIN = 0x8;
|
||||
|
||||
/**
|
||||
* This flag blocks form submission.
|
||||
*/
|
||||
const unsigned long SANDBOXED_FORMS = 0x10;
|
||||
|
||||
/**
|
||||
* This flag blocks script execution.
|
||||
*/
|
||||
const unsigned long SANDBOXED_SCRIPTS = 0x20;
|
||||
|
||||
/**
|
||||
* This flag blocks features that trigger automatically, such as
|
||||
* automatically playing a video or automatically focusing a form control.
|
||||
*/
|
||||
const unsigned long SANDBOXED_AUTOMATIC_FEATURES = 0x40;
|
||||
#endif
|
@ -42,6 +42,7 @@
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsGenericElement.h"
|
||||
#include "nsCrossSiteListenerProxy.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
#include "mozilla/FunctionTimer.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
@ -278,6 +279,11 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
|
||||
|
||||
// If this document is sandboxed without 'allow-scripts', abort.
|
||||
if (mDocument->GetSandboxFlags() & SANDBOXED_SCRIPTS) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// check for a Content Security Policy to pass down to the channel
|
||||
// that will be created to load the script
|
||||
nsCOMPtr<nsIChannelPolicy> channelPolicy;
|
||||
@ -591,6 +597,11 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
||||
}
|
||||
|
||||
// inline script
|
||||
// Is this document sandboxed without 'allow-scripts'?
|
||||
if (mDocument->GetSandboxFlags() & SANDBOXED_SCRIPTS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = mDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include "nsIDOMFormData.h"
|
||||
#include "DictionaryHelpers.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
@ -572,9 +573,16 @@ nsXMLHttpRequest::InitParameters(bool aAnon, bool aSystem)
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
|
||||
if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.systemXHR.whitelist")) {
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
nsCOMPtr<nsIPermissionManager> permMgr =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permMgr)
|
||||
return;
|
||||
|
||||
PRUint32 permission;
|
||||
nsresult rv =
|
||||
permMgr->TestPermissionFromPrincipal(principal, "systemXHR", &permission);
|
||||
if (NS_FAILED(rv) || permission != nsIPermissionManager::ALLOW_ACTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1705,18 +1713,9 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ...or if this is a same-origin request.
|
||||
if (nsContentUtils::CheckMayLoad(mPrincipal, aChannel)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// exempt data URIs from the same origin check.
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
bool dataScheme = false;
|
||||
if (NS_SUCCEEDED(NS_GetFinalChannelURI(aChannel,
|
||||
getter_AddRefs(channelURI))) &&
|
||||
NS_SUCCEEDED(channelURI->SchemeIs("data", &dataScheme)) &&
|
||||
dataScheme) {
|
||||
// If this is a same-origin request or the channel's URI inherits
|
||||
// its principal, it's allowed.
|
||||
if (nsContentUtils::CheckMayLoad(mPrincipal, aChannel, true)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -28,12 +28,11 @@ function runTests() {
|
||||
authMgr.setAuthIdentity("http", "example.com", 80, "basic", "testrealm",
|
||||
"", "example.com", "user1", "password1");
|
||||
|
||||
SpecialPowers.setCharPref("dom.systemXHR.whitelist",
|
||||
"http://mochi.test:8888");
|
||||
SpecialPowers.addPermission("systemXHR", true, document);
|
||||
|
||||
return function tearDown() {
|
||||
authMgr.clearAll();
|
||||
SpecialPowers.clearUserPref("dom.systemXHR.whitelist");
|
||||
SpecialPowers.removePermission("systemXHR", document);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}());
|
||||
|
@ -84,11 +84,11 @@ function runTests() {
|
||||
|
||||
// ...and once with privileges.
|
||||
havePrivileges = true;
|
||||
SpecialPowers.setCharPref("dom.systemXHR.whitelist",
|
||||
"http://mochi.test:8888");
|
||||
SpecialPowers.addPermission("systemXHR", true, document);
|
||||
|
||||
validParameters.forEach(testValidParameter);
|
||||
invalidParameters.forEach(testInvalidParameter);
|
||||
SpecialPowers.clearUserPref("dom.systemXHR.whitelist");
|
||||
SpecialPowers.removePermission("systemXHR", document);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -16,12 +16,12 @@
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
|
||||
function runTests() {
|
||||
var comp = SpecialPowers.wrap(Components);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.setCharPref("dom.systemXHR.whitelist",
|
||||
"http://mochi.test:8888");
|
||||
SpecialPowers.addPermission("systemXHR", true, document);
|
||||
|
||||
function tearDown() {
|
||||
SpecialPowers.clearUserPref("dom.systemXHR.whitelist");
|
||||
SpecialPowers.removePermission("systemXHR", document);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -159,29 +159,35 @@ test(
|
||||
function test_CSPSource_fromString() {
|
||||
// can't do these tests because "self" is not defined.
|
||||
//"basic source should not be null.");
|
||||
do_check_neq(null, CSPSource.fromString("a.com"));
|
||||
do_check_neq(null, CSPSource.fromString("a.com", "http://abc.com"));
|
||||
|
||||
//"ldh characters should all work for host.");
|
||||
do_check_neq(null, CSPSource.fromString("a2-c.com"));
|
||||
do_check_neq(null, CSPSource.fromString("a2-c.com", "https://a.com"));
|
||||
|
||||
//"wildcard should work in first token for host.");
|
||||
do_check_neq(null, CSPSource.fromString("*.a.com"));
|
||||
do_check_neq(null, CSPSource.fromString("*.a.com", "http://abc.com"));
|
||||
|
||||
//print(" --- Ignore the following two errors if they print ---");
|
||||
//"wildcard should not work in non-first token for host.");
|
||||
do_check_eq(null, CSPSource.fromString("x.*.a.com"));
|
||||
do_check_eq(null, CSPSource.fromString("x.*.a.com", "http://a.com"));
|
||||
|
||||
//"funny characters (#) should not work for host.");
|
||||
do_check_eq(null, CSPSource.fromString("a#2-c.com"));
|
||||
do_check_eq(null, CSPSource.fromString("a#2-c.com", "http://a.com"));
|
||||
|
||||
//print(" --- Stop ignoring errors that print ---\n");
|
||||
|
||||
//"failed to parse host with port.");
|
||||
do_check_neq(null, CSPSource.create("a.com:23"));
|
||||
do_check_neq(null, CSPSource.create("a.com:23", "http://a.com"));
|
||||
//"failed to parse host with scheme.");
|
||||
do_check_neq(null, CSPSource.create("https://a.com"));
|
||||
do_check_neq(null, CSPSource.create("https://a.com", "http://a.com"));
|
||||
//"failed to parse host with scheme and port.");
|
||||
do_check_neq(null, CSPSource.create("https://a.com:200"));
|
||||
do_check_neq(null, CSPSource.create("https://a.com:200", "http://a.com"));
|
||||
|
||||
//Check to make sure we don't match multiple instances with regex
|
||||
do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23"));
|
||||
//Port parsing should work for all schemes
|
||||
do_check_neq(null, CSPSource.create("data:"));
|
||||
do_check_neq(null, CSPSource.create("javascript:"));
|
||||
});
|
||||
|
||||
test(
|
||||
@ -270,6 +276,7 @@ test(
|
||||
var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
|
||||
URI("http://self.com:88"));
|
||||
var allSourceList = CSPSourceList.fromString("*");
|
||||
var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'");
|
||||
|
||||
//'none' should permit none."
|
||||
do_check_false( nullSourceList.permits("http://a.com"));
|
||||
@ -293,6 +300,8 @@ test(
|
||||
//"* does not permit a long host with no port"
|
||||
do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com"));
|
||||
|
||||
//* short circuts parsing
|
||||
do_check_true(allAndMoreSourceList.permits("http://a.com"));
|
||||
});
|
||||
|
||||
test(
|
||||
@ -301,7 +310,7 @@ test(
|
||||
// policy a /\ policy b intersects policies, not context (where 'self'
|
||||
// values come into play)
|
||||
var nullSourceList = CSPSourceList.fromString("'none'");
|
||||
var simpleSourceList = CSPSourceList.fromString("a.com");
|
||||
var simpleSourceList = CSPSourceList.fromString("http://a.com");
|
||||
var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88");
|
||||
var singleFooSourceList = CSPSourceList.fromString("https://foo.com");
|
||||
var allSourceList = CSPSourceList.fromString("*");
|
||||
@ -626,6 +635,57 @@ test(
|
||||
do_check_false(p_none.permits("http://bar.com"));
|
||||
});
|
||||
|
||||
test(
|
||||
function test_bug783497_refinePolicyIssues() {
|
||||
|
||||
const firstPolicy = "allow 'self'; img-src 'self'; script-src 'self'; options 'bogus-option'";
|
||||
const secondPolicy = "default-src 'none'; script-src 'self'";
|
||||
var cspObj = Cc["@mozilla.org/contentsecuritypolicy;1"]
|
||||
.createInstance(Ci.nsIContentSecurityPolicy);
|
||||
var selfURI = URI("http://self.com/");
|
||||
|
||||
function testPermits(aUri, aContext) {
|
||||
return cspObj.shouldLoad(aContext, aUri, null, null, null, null)
|
||||
== Ci.nsIContentPolicy.ACCEPT;
|
||||
};
|
||||
|
||||
// everything is allowed by the default policy
|
||||
do_check_true(testPermits(URI("http://self.com/foo.js"),
|
||||
Ci.nsIContentPolicy.TYPE_SCRIPT));
|
||||
do_check_true(testPermits(URI("http://other.com/foo.js"),
|
||||
Ci.nsIContentPolicy.TYPE_SCRIPT));
|
||||
do_check_true(testPermits(URI("http://self.com/foo.png"),
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE));
|
||||
do_check_true(testPermits(URI("http://other.com/foo.png"),
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE));
|
||||
|
||||
// fold in the first policy
|
||||
cspObj.refinePolicy(firstPolicy, selfURI);
|
||||
|
||||
// script-src and img-src are limited to self after the first policy
|
||||
do_check_true(testPermits(URI("http://self.com/foo.js"),
|
||||
Ci.nsIContentPolicy.TYPE_SCRIPT));
|
||||
do_check_false(testPermits(URI("http://other.com/foo.js"),
|
||||
Ci.nsIContentPolicy.TYPE_SCRIPT));
|
||||
do_check_true(testPermits(URI("http://self.com/foo.png"),
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE));
|
||||
do_check_false(testPermits(URI("http://other.com/foo.png"),
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE));
|
||||
|
||||
// fold in the second policy
|
||||
cspObj.refinePolicy(secondPolicy, selfURI);
|
||||
|
||||
// script-src is self and img-src is none after the merge
|
||||
do_check_true(testPermits(URI("http://self.com/foo.js"),
|
||||
Ci.nsIContentPolicy.TYPE_SCRIPT));
|
||||
do_check_false(testPermits(URI("http://other.com/foo.js"),
|
||||
Ci.nsIContentPolicy.TYPE_SCRIPT));
|
||||
do_check_false(testPermits(URI("http://self.com/foo.png"),
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE));
|
||||
do_check_false(testPermits(URI("http://other.com/foo.png"),
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE));
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::layers;
|
||||
|
@ -124,8 +124,7 @@ ok(ctx.canvas === canvas, "ctx.canvas === canvas");
|
||||
function isPixel(ctx, x,y, r,g,b,a, d) {
|
||||
var pos = x + "," + y;
|
||||
var colour = r + "," + g + "," + b + "," + a;
|
||||
var pixel = SpecialPowers.unwrap(SpecialPowers.wrap(ctx)
|
||||
.getImageData(x, y, 1, 1));
|
||||
var pixel = ctx.getImageData(x, y, 1, 1);
|
||||
var pr = pixel.data[0],
|
||||
pg = pixel.data[1],
|
||||
pb = pixel.data[2],
|
||||
|
@ -36,7 +36,6 @@ CPPSRCS = \
|
||||
nsDOMMouseScrollEvent.cpp \
|
||||
nsDOMDragEvent.cpp \
|
||||
nsDOMMutationEvent.cpp \
|
||||
nsDOMPopupBlockedEvent.cpp \
|
||||
nsDOMDeviceMotionEvent.cpp \
|
||||
nsDOMBeforeUnloadEvent.cpp \
|
||||
nsDOMXULCommandEvent.cpp \
|
||||
|
@ -1,83 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsDOMPopupBlockedEvent.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMPopupBlockedEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMPopupBlockedEvent, nsDOMEvent)
|
||||
|
||||
DOMCI_DATA(PopupBlockedEvent, nsDOMPopupBlockedEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMPopupBlockedEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMPopupBlockedEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(PopupBlockedEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMPopupBlockedEvent::InitPopupBlockedEvent(const nsAString & aTypeArg,
|
||||
bool aCanBubbleArg, bool aCancelableArg,
|
||||
nsIDOMWindow *aRequestingWindow,
|
||||
nsIURI *aPopupWindowURI,
|
||||
const nsAString & aPopupWindowName,
|
||||
const nsAString & aPopupWindowFeatures)
|
||||
{
|
||||
nsresult rv = nsDOMEvent::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mRequestingWindow = do_GetWeakReference(aRequestingWindow);
|
||||
mPopupWindowURI = aPopupWindowURI;
|
||||
mPopupWindowFeatures = aPopupWindowFeatures;
|
||||
mPopupWindowName = aPopupWindowName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMPopupBlockedEvent::GetRequestingWindow(nsIDOMWindow **aRequestingWindow)
|
||||
{
|
||||
*aRequestingWindow = nullptr;
|
||||
if (mRequestingWindow)
|
||||
CallQueryReferent(mRequestingWindow.get(), aRequestingWindow);
|
||||
|
||||
return NS_OK; // Don't throw an exception
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMPopupBlockedEvent::GetPopupWindowURI(nsIURI **aPopupWindowURI)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPopupWindowURI);
|
||||
|
||||
*aPopupWindowURI = mPopupWindowURI;
|
||||
NS_IF_ADDREF(*aPopupWindowURI);
|
||||
return NS_OK; // Don't throw an exception
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMPopupBlockedEvent::GetPopupWindowFeatures(nsAString &aPopupWindowFeatures)
|
||||
{
|
||||
|
||||
aPopupWindowFeatures = mPopupWindowFeatures;
|
||||
return NS_OK; // Don't throw an exception
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMPopupBlockedEvent::GetPopupWindowName(nsAString &aPopupWindowName)
|
||||
{
|
||||
aPopupWindowName = mPopupWindowName;
|
||||
return NS_OK; // Don't throw an exception
|
||||
}
|
||||
|
||||
nsresult NS_NewDOMPopupBlockedEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsEvent *aEvent)
|
||||
{
|
||||
nsDOMPopupBlockedEvent* it = new nsDOMPopupBlockedEvent(aPresContext, aEvent);
|
||||
if (nullptr == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return CallQueryInterface(it, aInstancePtrResult);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user