Merge from mozilla-central.

This commit is contained in:
David Anderson 2012-08-21 15:59:12 -07:00
commit a264d0ebc8
1089 changed files with 27875 additions and 10214 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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"
}
]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,8 @@ let {
allPages: gAllPages,
linkChecker: gLinkChecker,
pinnedLinks: gPinnedLinks,
blockedLinks: gBlockedLinks
blockedLinks: gBlockedLinks,
gridPrefs: gGridPrefs
} = NewTabUtils;
XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {

View File

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

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -110,6 +110,12 @@
.menu-iconic-accel {
color: graytext;
}
.chatbar-button,
chatbar > chatbox {
border-color: #A9B7C9;
}
}
@media (-moz-windows-compositor) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@
#include "nsIPrincipal.h"
#include "nsJSPrincipals.h"
#include "nsCOMPtr.h"
#include "nsPrincipal.h"
class nsIURI;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -40,6 +40,7 @@ EXPORTS = \
nsGenericElement.h \
nsMappedAttributeElement.h \
nsStyledElement.h \
nsSandboxFlags.h \
$(NULL)
EXPORTS_NAMESPACES = mozilla/dom

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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___ */

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,7 +36,6 @@ CPPSRCS = \
nsDOMMouseScrollEvent.cpp \
nsDOMDragEvent.cpp \
nsDOMMutationEvent.cpp \
nsDOMPopupBlockedEvent.cpp \
nsDOMDeviceMotionEvent.cpp \
nsDOMBeforeUnloadEvent.cpp \
nsDOMXULCommandEvent.cpp \

View File

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