Merge m-c to inbound a=merge CLOSED TREE

--HG--
rename : xpcom/tests/TestUTF.cpp => xpcom/tests/gtest/TestUTF.cpp
rename : xpcom/tests/UTFStrings.h => xpcom/tests/gtest/UTFStrings.h
This commit is contained in:
Wes Kocher 2015-01-27 16:16:21 -08:00
Родитель 6797dfdced a092ea34c3
Коммит e523c1b047
82 изменённых файлов: 2103 добавлений и 2240 удалений

Просмотреть файл

@ -693,65 +693,50 @@ pref("dom.ipc.processPriorityManager.backgroundLRUPoolLevels", 5);
// Kernel parameters for process priorities. These affect how processes are // Kernel parameters for process priorities. These affect how processes are
// killed on low-memory and their relative CPU priorities. // killed on low-memory and their relative CPU priorities.
// //
// Note: The maximum nice value on Linux is 19, but the max value you should
// use here is 18. NSPR adds 1 to some threads' nice values, to mark
// low-priority threads. If the process priority manager were to renice a
// process (and all its threads) to 19, all threads would have the same
// niceness. Then when we reniced the process to (say) 10, all threads would
// /still/ have the same niceness; we'd effectively have erased NSPR's thread
// priorities.
// The kernel can only accept 6 (OomScoreAdjust, KillUnderKB) pairs. But it is // The kernel can only accept 6 (OomScoreAdjust, KillUnderKB) pairs. But it is
// okay, kernel will still kill processes with larger OomScoreAdjust first even // okay, kernel will still kill processes with larger OomScoreAdjust first even
// its OomScoreAdjust don't have a corresponding KillUnderKB. // its OomScoreAdjust don't have a corresponding KillUnderKB.
pref("hal.processPriorityManager.gonk.MASTER.OomScoreAdjust", 0); pref("hal.processPriorityManager.gonk.MASTER.OomScoreAdjust", 0);
pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096); pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096);
pref("hal.processPriorityManager.gonk.MASTER.cgroup", ""); pref("hal.processPriorityManager.gonk.MASTER.Nice", 0);
pref("hal.processPriorityManager.gonk.PREALLOC.OomScoreAdjust", 67); pref("hal.processPriorityManager.gonk.PREALLOC.OomScoreAdjust", 67);
pref("hal.processPriorityManager.gonk.PREALLOC.cgroup", "apps/bg_non_interactive"); pref("hal.processPriorityManager.gonk.PREALLOC.Nice", 18);
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67); pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67);
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120); pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120);
pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.cgroup", "apps/critical"); pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.Nice", 0);
pref("hal.processPriorityManager.gonk.FOREGROUND.OomScoreAdjust", 134); pref("hal.processPriorityManager.gonk.FOREGROUND.OomScoreAdjust", 134);
pref("hal.processPriorityManager.gonk.FOREGROUND.KillUnderKB", 6144); pref("hal.processPriorityManager.gonk.FOREGROUND.KillUnderKB", 6144);
pref("hal.processPriorityManager.gonk.FOREGROUND.cgroup", "apps"); pref("hal.processPriorityManager.gonk.FOREGROUND.Nice", 1);
pref("hal.processPriorityManager.gonk.FOREGROUND_KEYBOARD.OomScoreAdjust", 200); pref("hal.processPriorityManager.gonk.FOREGROUND_KEYBOARD.OomScoreAdjust", 200);
pref("hal.processPriorityManager.gonk.FOREGROUND_KEYBOARD.cgroup", "apps"); pref("hal.processPriorityManager.gonk.FOREGROUND_KEYBOARD.Nice", 1);
pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.OomScoreAdjust", 400); pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.OomScoreAdjust", 400);
pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.KillUnderKB", 7168); pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.KillUnderKB", 7168);
pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.cgroup", "apps/bg_perceivable"); pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.Nice", 7);
pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.OomScoreAdjust", 534); pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.OomScoreAdjust", 534);
pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.KillUnderKB", 8192); pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.KillUnderKB", 8192);
pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.cgroup", "apps/bg_non_interactive"); pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.Nice", 18);
pref("hal.processPriorityManager.gonk.BACKGROUND.OomScoreAdjust", 667); pref("hal.processPriorityManager.gonk.BACKGROUND.OomScoreAdjust", 667);
pref("hal.processPriorityManager.gonk.BACKGROUND.KillUnderKB", 20480); pref("hal.processPriorityManager.gonk.BACKGROUND.KillUnderKB", 20480);
pref("hal.processPriorityManager.gonk.BACKGROUND.cgroup", "apps/bg_non_interactive"); pref("hal.processPriorityManager.gonk.BACKGROUND.Nice", 18);
// Control group definitions (i.e., CPU priority groups) for B2G processes. // Processes get this niceness when they have low CPU priority.
// pref("hal.processPriorityManager.gonk.LowCPUNice", 18);
// memory_swappiness - 0 - The kernel will swap only to avoid an out of memory condition
// memory_swappiness - 60 - The default value.
// memory_swappiness - 100 - The kernel will swap aggressively.
// Foreground apps
pref("hal.processPriorityManager.gonk.cgroups.apps.cpu_shares", 1024);
pref("hal.processPriorityManager.gonk.cgroups.apps.cpu_notify_on_migrate", 1);
pref("hal.processPriorityManager.gonk.cgroups.apps.memory_swappiness", 10);
// Foreground apps with high priority, 16x more CPU than foreground ones
pref("hal.processPriorityManager.gonk.cgroups.apps/critical.cpu_shares", 16384);
pref("hal.processPriorityManager.gonk.cgroups.apps/critical.cpu_notify_on_migrate", 1);
pref("hal.processPriorityManager.gonk.cgroups.apps/critical.memory_swappiness", 0);
// Background perceivable apps, ~10x less CPU than foreground ones
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.cpu_shares", 103);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.cpu_notify_on_migrate", 0);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.memory_swappiness", 60);
// Background apps, ~20x less CPU than foreground ones and ~2x less than perceivable ones
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.cpu_shares", 52);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.cpu_notify_on_migrate", 0);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.memory_swappiness", 100);
// By default the compositor thread on gonk runs without real-time priority. RT // By default the compositor thread on gonk runs without real-time priority. RT
// priority can be enabled by setting this pref to a value between 1 and 99. // priority can be enabled by setting this pref to a value between 1 and 99.

Просмотреть файл

@ -4,15 +4,23 @@
/* jshint moz: true */ /* jshint moz: true */
/* global Uint8Array, Components, dump */ /* global Uint8Array, Components, dump */
'use strict'; "use strict";
this.EXPORTED_SYMBOLS = ['LogCapture']; const Cu = Components.utils;
const Ci = Components.interfaces;
const Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm");
this.EXPORTED_SYMBOLS = ["LogCapture"];
const SYSTEM_PROPERTY_KEY_MAX = 32; const SYSTEM_PROPERTY_KEY_MAX = 32;
const SYSTEM_PROPERTY_VALUE_MAX = 92; const SYSTEM_PROPERTY_VALUE_MAX = 92;
function debug(msg) { function debug(msg) {
dump('LogCapture.jsm: ' + msg + '\n'); dump("LogCapture.jsm: " + msg + "\n");
} }
let LogCapture = { let LogCapture = {
@ -24,11 +32,11 @@ let LogCapture = {
load: function() { load: function() {
// load in everything on first use // load in everything on first use
Components.utils.import('resource://gre/modules/ctypes.jsm', this); Cu.import("resource://gre/modules/ctypes.jsm", this);
this.libc = this.ctypes.open(this.ctypes.libraryName('c')); this.libc = this.ctypes.open(this.ctypes.libraryName("c"));
this.read = this.libc.declare('read', this.read = this.libc.declare("read",
this.ctypes.default_abi, this.ctypes.default_abi,
this.ctypes.int, // bytes read (out) this.ctypes.int, // bytes read (out)
this.ctypes.int, // file descriptor (in) this.ctypes.int, // file descriptor (in)
@ -36,19 +44,24 @@ let LogCapture = {
this.ctypes.size_t // size_t size of buffer (in) this.ctypes.size_t // size_t size of buffer (in)
); );
this.open = this.libc.declare('open', this.open = this.libc.declare("open",
this.ctypes.default_abi, this.ctypes.default_abi,
this.ctypes.int, // file descriptor (returned) this.ctypes.int, // file descriptor (returned)
this.ctypes.char.ptr, // path this.ctypes.char.ptr, // path
this.ctypes.int // flags this.ctypes.int // flags
); );
this.close = this.libc.declare('close', this.close = this.libc.declare("close",
this.ctypes.default_abi, this.ctypes.default_abi,
this.ctypes.int, // error code (returned) this.ctypes.int, // error code (returned)
this.ctypes.int // file descriptor this.ctypes.int // file descriptor
); );
this.getpid = this.libc.declare("getpid",
this.ctypes.default_abi,
this.ctypes.int // PID
);
this.property_find_nth = this.property_find_nth =
this.libc.declare("__system_property_find_nth", this.libc.declare("__system_property_find_nth",
this.ctypes.default_abi, this.ctypes.default_abi,
@ -153,6 +166,26 @@ let LogCapture = {
} }
return propertyDict; return propertyDict;
},
/**
* Dumping about:memory to a file in /data/local/tmp/, returning a Promise.
* Will be resolved with the dumped file name.
*/
readAboutMemory: function() {
this.ensureLoaded();
let deferred = Promise.defer();
// Perform the dump
let dumper = Cc["@mozilla.org/memory-info-dumper;1"]
.getService(Ci.nsIMemoryInfoDumper);
let file = "/data/local/tmp/logshake-about_memory-" + this.getpid() + ".json.gz";
dumper.dumpMemoryReportsToNamedFile(file, function() {
deferred.resolve(file);
}, null, false);
return deferred.promise;
} }
}; };

Просмотреть файл

@ -21,32 +21,32 @@
/* global Services, Components, dump, LogCapture, LogParser, /* global Services, Components, dump, LogCapture, LogParser,
OS, Promise, volumeService, XPCOMUtils, SystemAppProxy */ OS, Promise, volumeService, XPCOMUtils, SystemAppProxy */
'use strict'; "use strict";
const Cu = Components.utils; const Cu = Components.utils;
const Ci = Components.interfaces; const Ci = Components.interfaces;
Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'LogCapture', 'resource://gre/modules/LogCapture.jsm'); XPCOMUtils.defineLazyModuleGetter(this, "LogCapture", "resource://gre/modules/LogCapture.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'LogParser', 'resource://gre/modules/LogParser.jsm'); XPCOMUtils.defineLazyModuleGetter(this, "LogParser", "resource://gre/modules/LogParser.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'OS', 'resource://gre/modules/osfile.jsm'); XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'Promise', 'resource://gre/modules/Promise.jsm'); XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'Services', 'resource://gre/modules/Services.jsm'); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'SystemAppProxy', 'resource://gre/modules/SystemAppProxy.jsm'); XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy", "resource://gre/modules/SystemAppProxy.jsm");
XPCOMUtils.defineLazyServiceGetter(this, 'powerManagerService', XPCOMUtils.defineLazyServiceGetter(this, "powerManagerService",
'@mozilla.org/power/powermanagerservice;1', "@mozilla.org/power/powermanagerservice;1",
'nsIPowerManagerService'); "nsIPowerManagerService");
XPCOMUtils.defineLazyServiceGetter(this, 'volumeService', XPCOMUtils.defineLazyServiceGetter(this, "volumeService",
'@mozilla.org/telephony/volume-service;1', "@mozilla.org/telephony/volume-service;1",
'nsIVolumeService'); "nsIVolumeService");
this.EXPORTED_SYMBOLS = ['LogShake']; this.EXPORTED_SYMBOLS = ["LogShake"];
function debug(msg) { function debug(msg) {
dump('LogShake.jsm: '+msg+'\n'); dump("LogShake.jsm: "+msg+"\n");
} }
/** /**
@ -54,11 +54,11 @@ function debug(msg) {
* shake * shake
*/ */
const EXCITEMENT_THRESHOLD = 500; const EXCITEMENT_THRESHOLD = 500;
const DEVICE_MOTION_EVENT = 'devicemotion'; const DEVICE_MOTION_EVENT = "devicemotion";
const SCREEN_CHANGE_EVENT = 'screenchange'; const SCREEN_CHANGE_EVENT = "screenchange";
const CAPTURE_LOGS_START_EVENT = 'capture-logs-start'; const CAPTURE_LOGS_START_EVENT = "capture-logs-start";
const CAPTURE_LOGS_ERROR_EVENT = 'capture-logs-error'; const CAPTURE_LOGS_ERROR_EVENT = "capture-logs-error";
const CAPTURE_LOGS_SUCCESS_EVENT = 'capture-logs-success'; const CAPTURE_LOGS_SUCCESS_EVENT = "capture-logs-success";
let LogShake = { let LogShake = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
@ -79,17 +79,18 @@ let LogShake = {
* Map of files which have log-type information to their parsers * Map of files which have log-type information to their parsers
*/ */
LOGS_WITH_PARSERS: { LOGS_WITH_PARSERS: {
'/dev/log/main': LogParser.prettyPrintLogArray, "/dev/log/main": LogParser.prettyPrintLogArray,
'/dev/log/system': LogParser.prettyPrintLogArray, "/dev/log/system": LogParser.prettyPrintLogArray,
'/dev/log/radio': LogParser.prettyPrintLogArray, "/dev/log/radio": LogParser.prettyPrintLogArray,
'/dev/log/events': LogParser.prettyPrintLogArray, "/dev/log/events": LogParser.prettyPrintLogArray,
'/proc/cmdline': LogParser.prettyPrintArray, "/proc/cmdline": LogParser.prettyPrintArray,
'/proc/kmsg': LogParser.prettyPrintArray, "/proc/kmsg": LogParser.prettyPrintArray,
'/proc/meminfo': LogParser.prettyPrintArray, "/proc/meminfo": LogParser.prettyPrintArray,
'/proc/uptime': LogParser.prettyPrintArray, "/proc/uptime": LogParser.prettyPrintArray,
'/proc/version': LogParser.prettyPrintArray, "/proc/version": LogParser.prettyPrintArray,
'/proc/vmallocinfo': LogParser.prettyPrintArray, "/proc/vmallocinfo": LogParser.prettyPrintArray,
'/proc/vmstat': LogParser.prettyPrintArray "/proc/vmstat": LogParser.prettyPrintArray,
"/system/b2g/application.ini": LogParser.prettyPrintArray
}, },
/** /**
@ -109,7 +110,7 @@ let LogShake = {
SystemAppProxy.addEventListener(SCREEN_CHANGE_EVENT, this, false); SystemAppProxy.addEventListener(SCREEN_CHANGE_EVENT, this, false);
Services.obs.addObserver(this, 'xpcom-shutdown', false); Services.obs.addObserver(this, "xpcom-shutdown", false);
}, },
/** /**
@ -134,7 +135,7 @@ let LogShake = {
* Handle an observation from Services.obs * Handle an observation from Services.obs
*/ */
observe: function(subject, topic) { observe: function(subject, topic) {
if (topic === 'xpcom-shutdown') { if (topic === "xpcom-shutdown") {
this.uninit(); this.uninit();
} }
}, },
@ -152,8 +153,8 @@ let LogShake = {
}, },
/** /**
* Handle a motion event, keeping track of 'excitement', the magnitude * Handle a motion event, keeping track of "excitement", the magnitude
* of the device's acceleration. * of the device"s acceleration.
*/ */
handleDeviceMotionEvent: function(event) { handleDeviceMotionEvent: function(event) {
// There is a lag between disabling the event listener and event arrival // There is a lag between disabling the event listener and event arrival
@ -217,11 +218,33 @@ let LogShake = {
Cu.reportError("Unable to get device properties: " + ex); Cu.reportError("Unable to get device properties: " + ex);
} }
// Let Gecko perfom the dump to a file, and just collect it
try {
LogCapture.readAboutMemory().then(aboutMemory => {
let file = OS.Path.basename(aboutMemory);
let logArray;
try {
logArray = LogCapture.readLogFile(aboutMemory);
if (!logArray) {
debug("LogCapture.readLogFile() returned nothing about:memory ");
}
// We need to remove the dumped file, now that we have it in memory
OS.File.remove(aboutMemory);
} catch (ex) {
Cu.reportError("Unable to handle about:memory dump: " + ex);
}
logArrays[file] = LogParser.prettyPrintArray(logArray);
});
} catch (ex) {
Cu.reportError("Unable to get about:memory dump: " + ex);
}
for (let loc in this.LOGS_WITH_PARSERS) { for (let loc in this.LOGS_WITH_PARSERS) {
let logArray; let logArray;
try { try {
logArray = LogCapture.readLogFile(loc); logArray = LogCapture.readLogFile(loc);
if (!logArray) { if (!logArray) {
debug("LogCapture.readLogFile() returned nothing for: " + loc);
continue; continue;
} }
} catch (ex) { } catch (ex) {
@ -245,32 +268,40 @@ let LogShake = {
uninit: function() { uninit: function() {
this.stopDeviceMotionListener(); this.stopDeviceMotionListener();
SystemAppProxy.removeEventListener(SCREEN_CHANGE_EVENT, this, false); SystemAppProxy.removeEventListener(SCREEN_CHANGE_EVENT, this, false);
Services.obs.removeObserver(this, 'xpcom-shutdown'); Services.obs.removeObserver(this, "xpcom-shutdown");
} }
}; };
function getLogFilename(logLocation) { function getLogFilename(logLocation) {
// sanitize the log location // sanitize the log location
let logName = logLocation.replace(/\//g, '-'); let logName = logLocation.replace(/\//g, "-");
if (logName[0] === '-') { if (logName[0] === "-") {
logName = logName.substring(1); logName = logName.substring(1);
} }
return logName + '.log';
// If no extension is provided, default to forcing .log
let extension = ".log";
let logLocationExt = logLocation.split(".");
if (logLocationExt.length > 1) {
// otherwise, just append nothing
extension = "";
}
return logName + extension;
} }
function getSdcardPrefix() { function getSdcardPrefix() {
return volumeService.getVolumeByName('sdcard').mountPoint; return volumeService.getVolumeByName("sdcard").mountPoint;
} }
function getLogDirectoryRoot() { function getLogDirectoryRoot() {
return 'logs'; return "logs";
} }
function getLogDirectory() { function getLogDirectory() {
let d = new Date(); let d = new Date();
d = new Date(d.getTime() - d.getTimezoneOffset() * 60000); d = new Date(d.getTime() - d.getTimezoneOffset() * 60000);
let timestamp = d.toISOString().slice(0, -5).replace(/[:T]/g, '-'); let timestamp = d.toISOString().slice(0, -5).replace(/[:T]/g, "-");
// return directory name of format 'logs/timestamp/'
return timestamp; return timestamp;
} }
@ -281,7 +312,7 @@ function saveLogs(logArrays) {
if (!logArrays || Object.keys(logArrays).length === 0) { if (!logArrays || Object.keys(logArrays).length === 0) {
return Promise.resolve({ return Promise.resolve({
logFilenames: [], logFilenames: [],
logPrefix: '' logPrefix: ""
}); });
} }
@ -296,19 +327,24 @@ function saveLogs(logArrays) {
return Promise.reject(e); return Promise.reject(e);
} }
debug('making a directory all the way from '+sdcardPrefix+' to '+(sdcardPrefix + '/' + dirNameRoot + '/' + dirName)); debug("making a directory all the way from " + sdcardPrefix + " to " + (sdcardPrefix + "/" + dirNameRoot + "/" + dirName) );
let logsRoot = OS.Path.join(sdcardPrefix, dirNameRoot); let logsRoot = OS.Path.join(sdcardPrefix, dirNameRoot);
return OS.File.makeDir(logsRoot, {from: sdcardPrefix}).then( return OS.File.makeDir(logsRoot, {from: sdcardPrefix}).then(
function() { function() {
debug("First OS.File.makeDir done");
let logsDir = OS.Path.join(logsRoot, dirName); let logsDir = OS.Path.join(logsRoot, dirName);
debug("Creating " + logsDir);
return OS.File.makeDir(logsDir, {ignoreExisting: false}).then( return OS.File.makeDir(logsDir, {ignoreExisting: false}).then(
function() { function() {
debug("Created: " + logsDir);
// Now the directory is guaranteed to exist, save the logs // Now the directory is guaranteed to exist, save the logs
let logFilenames = []; let logFilenames = [];
let saveRequests = []; let saveRequests = [];
debug("Will now traverse logArrays: " + logArrays.length);
for (let logLocation in logArrays) { for (let logLocation in logArrays) {
debug('requesting save of ' + logLocation); debug("requesting save of " + logLocation);
let logArray = logArrays[logLocation]; let logArray = logArrays[logLocation];
// The filename represents the relative path within the SD card, not the // The filename represents the relative path within the SD card, not the
// absolute path because Gaia will refer to it using the DeviceStorage // absolute path because Gaia will refer to it using the DeviceStorage
@ -321,13 +357,22 @@ function saveLogs(logArrays) {
return Promise.all(saveRequests).then( return Promise.all(saveRequests).then(
function() { function() {
debug('returning logfilenames: '+logFilenames.toSource()); debug("returning logfilenames: "+logFilenames.toSource());
return { return {
logFilenames: logFilenames, logFilenames: logFilenames,
logPrefix: OS.Path.join(dirNameRoot, dirName) logPrefix: OS.Path.join(dirNameRoot, dirName)
}; };
}, function(err) {
debug("Error at some save request: " + err);
return Promise.reject(err);
}); });
}, function(err) {
debug("Error at OS.File.makeDir for " + logsDir + ": " + err);
return Promise.reject(err);
}); });
}, function(err) {
debug("Error at first OS.File.makeDir: " + err);
return Promise.reject(err);
}); });
} }

Просмотреть файл

@ -1,30 +1,13 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/** /**
* Test that LogCapture successfully reads from the /dev/log devices, returning * Testing non Gonk-specific code path
* a Uint8Array of some length, including zero. This tests a few standard
* log devices
*/ */
function run_test() { function run_test() {
Components.utils.import("resource:///modules/LogCapture.jsm"); Components.utils.import("resource:///modules/LogCapture.jsm");
run_next_test();
function verifyLog(log) {
// log exists
notEqual(log, null);
// log has a length and it is non-negative (is probably array-like)
ok(log.length >= 0);
}
let propertiesLog = LogCapture.readProperties();
notEqual(propertiesLog, null, "Properties should not be null");
notEqual(propertiesLog, undefined, "Properties should not be undefined");
equal(propertiesLog["ro.kernel.qemu"], "1", "QEMU property should be 1");
let mainLog = LogCapture.readLogFile("/dev/log/main");
verifyLog(mainLog);
let meminfoLog = LogCapture.readLogFile("/proc/meminfo");
verifyLog(meminfoLog);
} }
// Trivial test just to make sure we have no syntax error
add_test(function test_logCapture_loads() {
ok(LogCapture, "LogCapture object exists");
run_next_test();
});

Просмотреть файл

@ -0,0 +1,61 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that LogCapture successfully reads from the /dev/log devices, returning
* a Uint8Array of some length, including zero. This tests a few standard
* log devices
*/
function run_test() {
Components.utils.import("resource:///modules/LogCapture.jsm");
run_next_test();
}
function verifyLog(log) {
// log exists
notEqual(log, null);
// log has a length and it is non-negative (is probably array-like)
ok(log.length >= 0);
}
add_test(function test_readLogFile() {
let mainLog = LogCapture.readLogFile("/dev/log/main");
verifyLog(mainLog);
let meminfoLog = LogCapture.readLogFile("/proc/meminfo");
verifyLog(meminfoLog);
run_next_test();
});
add_test(function test_readProperties() {
let propertiesLog = LogCapture.readProperties();
notEqual(propertiesLog, null, "Properties should not be null");
notEqual(propertiesLog, undefined, "Properties should not be undefined");
equal(propertiesLog["ro.kernel.qemu"], "1", "QEMU property should be 1");
run_next_test();
});
add_test(function test_readAppIni() {
let appIni = LogCapture.readLogFile("/system/b2g/application.ini");
verifyLog(appIni);
run_next_test();
});
add_test(function test_get_about_memory() {
let memLog = LogCapture.readAboutMemory();
ok(memLog, "Should have returned a valid Promise object");
memLog.then(file => {
ok(file, "Should have returned a filename");
run_next_test();
}, error => {
ok(false, "Dumping about:memory promise rejected: " + error);
run_next_test();
});
});

Просмотреть файл

@ -0,0 +1,121 @@
/**
* Test the log capturing capabilities of LogShake.jsm, checking
* for Gonk-specific parts
*/
/* jshint moz: true */
/* global Components, LogCapture, LogShake, ok, add_test, run_next_test, dump */
/* exported run_test */
/* disable use strict warning */
/* jshint -W097 */
"use strict";
const Cu = Components.utils;
const Ci = Components.interfaces;
const Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "volumeService",
"@mozilla.org/telephony/volume-service;1",
"nsIVolumeService");
let sdcard;
function run_test() {
Cu.import("resource://gre/modules/LogShake.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
do_get_profile();
debug("Starting");
run_next_test();
}
function debug(msg) {
var timestamp = Date.now();
dump("LogShake: " + timestamp + ": " + msg + "\n");
}
add_test(function setup_fs() {
OS.File.makeDir("/data/local/tmp/sdcard/", {from: "/data"}).then(function() {
run_next_test();
});
});
add_test(function setup_sdcard() {
let volName = "sdcard";
let mountPoint = "/data/local/tmp/sdcard";
volumeService.createFakeVolume(volName, mountPoint);
let vol = volumeService.getVolumeByName(volName);
ok(vol, "volume shouldn't be null");
equal(volName, vol.name, "name");
volumeService.SetFakeVolumeState(volName, Ci.nsIVolume.STATE_MOUNTED);
equal(Ci.nsIVolume.STATE_MOUNTED, vol.state, "state");
run_next_test();
});
add_test(function test_ensure_sdcard() {
sdcard = volumeService.getVolumeByName("sdcard").mountPoint;
ok(sdcard, "Should have a valid sdcard mountpoint");
run_next_test();
});
add_test(function test_logShake_captureLogs_returns() {
// Enable LogShake
LogShake.init();
LogShake.captureLogs().then(logResults => {
LogShake.uninit();
ok(logResults.logFilenames.length > 0, "Should have filenames");
ok(logResults.logPrefix.length > 0, "Should have prefix");
run_next_test();
},
error => {
LogShake.uninit();
ok(false, "Should not have received error: " + error);
run_next_test();
});
});
add_test(function test_logShake_captureLogs_writes() {
// Enable LogShake
LogShake.init();
let expectedFiles = [];
LogShake.captureLogs().then(logResults => {
LogShake.uninit();
logResults.logFilenames.forEach(f => {
let p = OS.Path.join(sdcard, f);
ok(p, "Should have a valid result path: " + p);
let t = OS.File.exists(p).then(rv => {
ok(rv, "File exists: " + p);
});
expectedFiles.push(t);
});
Promise.all(expectedFiles).then(() => {
ok(true, "Completed all files checks");
run_next_test();
});
},
error => {
LogShake.uninit();
ok(false, "Should not have received error: " + error);
run_next_test();
});
});

Просмотреть файл

@ -14,10 +14,17 @@ support-files =
head = head_identity.js head = head_identity.js
tail = tail =
# testing non gonk-specific stuff
[test_logcapture.js] [test_logcapture.js]
[test_logcapture_gonk.js]
# only run on b2g builds due to requiring b2g-specific log files to exist # only run on b2g builds due to requiring b2g-specific log files to exist
skip-if = toolkit != "gonk" skip-if = toolkit != "gonk"
[test_logparser.js] [test_logparser.js]
[test_logshake.js] [test_logshake.js]
[test_logshake_gonk.js]
# only run on b2g builds due to requiring b2g-specific log files to exist
skip-if = ((toolkit != "gonk") || ((toolkit == "gonk") && (debug == true))) # bug 1125989: disabled because of race condition in OS.File.makeDir

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be"> <project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -115,7 +115,7 @@
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/> <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/> <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/> <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="dcb7c6ba2c6aec23a76d95094c4cbc17eeca5d44"/> <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="a3a900615b89cbd67acfb8b750baa43b321ef68b"/>
<project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/> <project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
<project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/> <project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/> <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/>
@ -117,7 +117,7 @@
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/> <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/> <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/> <project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="dcb7c6ba2c6aec23a76d95094c4cbc17eeca5d44"/> <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="a3a900615b89cbd67acfb8b750baa43b321ef68b"/>
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/> <project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/> <project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/> <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/>
@ -135,7 +135,7 @@
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c5f8d282efe4a4e8b1e31a37300944e338e60e4f"/> <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c5f8d282efe4a4e8b1e31a37300944e338e60e4f"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/> <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="13374490fc0c989347448f0b2d6b220adff5e630"/> <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/> <project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/> <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
</manifest> </manifest>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be"> <project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -115,7 +115,7 @@
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/> <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/> <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/> <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="dcb7c6ba2c6aec23a76d95094c4cbc17eeca5d44"/> <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="a3a900615b89cbd67acfb8b750baa43b321ef68b"/>
<project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/> <project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
<project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/> <project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/> <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/> <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be"> <project name="platform_build" path="build" remote="b2g" revision="e06971db7acf7a35c32eb74d675a4e12e288e6be">
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -110,7 +110,7 @@
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/> <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/> <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/> <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="dcb7c6ba2c6aec23a76d95094c4cbc17eeca5d44"/> <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="a3a900615b89cbd67acfb8b750baa43b321ef68b"/>
<project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/> <project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/> <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/>
<project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/> <project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
@ -145,8 +145,8 @@
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/> <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/> <project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/> <project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
<project name="platform/system/core" path="system/core" revision="350eac5403124dacb2a5fd9e28ac290a59fc3b8e"/> <project name="platform/system/core" path="system/core" revision="42839aedcf70bf6bc92a3b7ea4a5cc9bf9aef3f9"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="13374490fc0c989347448f0b2d6b220adff5e630"/> <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
<project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/> <project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/> <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4c187c1f3a0dffd8e51a961735474ea703535b99"/> <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4c187c1f3a0dffd8e51a961735474ea703535b99"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project> </project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/>
@ -145,7 +145,7 @@
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/> <project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/> <project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
<project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/> <project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="13374490fc0c989347448f0b2d6b220adff5e630"/> <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/> <project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/> <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/> <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>

Просмотреть файл

@ -1,9 +1,9 @@
{ {
"git": { "git": {
"git_revision": "1eedbee8f26efbaa4a113e002c46f64e9b90249d", "git_revision": "1d53fb07984298253aad64bfa4236b7167ee3d4d",
"remote": "https://git.mozilla.org/releases/gaia.git", "remote": "https://git.mozilla.org/releases/gaia.git",
"branch": "" "branch": ""
}, },
"revision": "080bbea403be57fffcbb800eb6f7e2fcd0b4c7d2", "revision": "08a288892d8f0b41a960104150fba34f113629e6",
"repo_path": "integration/gaia-central" "repo_path": "integration/gaia-central"
} }

Просмотреть файл

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>

Просмотреть файл

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project> </project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/> <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="d6a27295acb0a25926bf6290dd2532a7f9027864"/>
@ -117,7 +117,7 @@
<project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/> <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="842e33e43a55ea44833b9e23e4d180fa17c843af"/>
<project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/> <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5db24726f0f42124304195a6bdea129039eeeaeb"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/> <project name="platform/system/bluetooth" path="system/bluetooth" revision="930ae098543881f47eac054677726ee4b998b2f8"/>
<project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="dcb7c6ba2c6aec23a76d95094c4cbc17eeca5d44"/> <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="a3a900615b89cbd67acfb8b750baa43b321ef68b"/>
<project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/> <project name="platform_system_core" path="system/core" remote="b2g" revision="542d1f59dc331b472307e5bd043101d14d5a3a3e"/>
<project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/> <project name="platform/system/extras" path="system/extras" revision="18c1180e848e7ab8691940481f5c1c8d22c37b3e"/>
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/> <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="8fcd25d64f0f67d1a6f7037a4c83ce6d95466770"/>
@ -130,7 +130,7 @@
<project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/> <project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/> <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
<project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/> <project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="13374490fc0c989347448f0b2d6b220adff5e630"/> <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/> <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/> <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
<project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/> <project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>

Просмотреть файл

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/> <copyfile dest="Makefile" src="core/root.mk"/>
</project> </project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1eedbee8f26efbaa4a113e002c46f64e9b90249d"/> <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d53fb07984298253aad64bfa4236b7167ee3d4d"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -26,8 +26,6 @@ let gDataNotificationInfoBar = {
init: function() { init: function() {
window.addEventListener("unload", function onUnload() { window.addEventListener("unload", function onUnload() {
window.removeEventListener("unload", onUnload, false);
for (let o of this._OBSERVERS) { for (let o of this._OBSERVERS) {
Services.obs.removeObserver(this, o); Services.obs.removeObserver(this, o);
} }

Просмотреть файл

@ -1012,8 +1012,8 @@ chatbox:-moz-full-screen-ancestor > .chat-titlebar {
} }
/* Combobox dropdown renderer */ /* Combobox dropdown renderer */
#ContentSelectDropdown { #ContentSelectDropdown > menupopup {
-moz-binding: url("chrome://global/content/bindings/popup.xml#popup-scrollbars"); max-height: 350px;
} }
.contentSelectDropdown-optgroup { .contentSelectDropdown-optgroup {

Просмотреть файл

@ -146,8 +146,13 @@
<!-- for url bar autocomplete --> <!-- for url bar autocomplete -->
<panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/> <panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
<!-- for select dropdowns --> <!-- for select dropdowns. The menupopup is what shows the list of options,
<menupopup id="ContentSelectDropdown" rolluponmousewheel="true" hidden="true"/> and the popuponly menulist makes things like the menuactive attributes
work correctly on the menupopup. ContentSelectDropdown expects the
popuponly menulist to be its immediate parent. -->
<menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
<menupopup rolluponmousewheel="true"/>
</menulist>
<!-- for invalid form error message --> <!-- for invalid form error message -->
<panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent"> <panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent">
@ -1169,7 +1174,7 @@
tabcontainer="tabbrowser-tabs" tabcontainer="tabbrowser-tabs"
contentcontextmenu="contentAreaContextMenu" contentcontextmenu="contentAreaContextMenu"
autocompletepopup="PopupAutoComplete" autocompletepopup="PopupAutoComplete"
selectpopup="ContentSelectDropdown"/> selectmenulist="ContentSelectDropdown"/>
<chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/> <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
</vbox> </vbox>
<splitter id="social-sidebar-splitter" <splitter id="social-sidebar-splitter"

Просмотреть файл

@ -30,7 +30,7 @@
<xul:vbox flex="1" class="browserContainer"> <xul:vbox flex="1" class="browserContainer">
<xul:stack flex="1" class="browserStack" anonid="browserStack"> <xul:stack flex="1" class="browserStack" anonid="browserStack">
<xul:browser anonid="initialBrowser" type="content-primary" message="true" messagemanagergroup="browsers" <xul:browser anonid="initialBrowser" type="content-primary" message="true" messagemanagergroup="browsers"
xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectpopup"/> xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectmenulist"/>
</xul:stack> </xul:stack>
</xul:vbox> </xul:vbox>
</xul:hbox> </xul:hbox>
@ -1600,8 +1600,8 @@
if (!isPreloadBrowser && this.hasAttribute("autocompletepopup")) if (!isPreloadBrowser && this.hasAttribute("autocompletepopup"))
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup")); b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
if (this.hasAttribute("selectpopup")) if (this.hasAttribute("selectmenulist"))
b.setAttribute("selectpopup", this.getAttribute("selectpopup")); b.setAttribute("selectmenulist", this.getAttribute("selectmenulist"));
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id); b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);

Просмотреть файл

@ -203,7 +203,6 @@ loop.shared.mixins = (function() {
publishVideo: options.publishVideo, publishVideo: options.publishVideo,
style: { style: {
audioLevelDisplayMode: "off", audioLevelDisplayMode: "off",
bugDisplayMode: "off",
buttonDisplayMode: "off", buttonDisplayMode: "off",
nameDisplayMode: "off", nameDisplayMode: "off",
videoDisabledDisplayMode: "off" videoDisabledDisplayMode: "off"

Просмотреть файл

@ -118,216 +118,88 @@
/* Modal dialog styles */ /* Modal dialog styles */
.OT_dialog-centering {
display: table;
width: 100%;
height: 100%;
}
.OT_dialog-centering-child {
display: table-cell;
vertical-align: middle;
}
.OT_dialog { .OT_dialog {
border: none; position: relative;
border-radius: 0;
top: 50%; box-sizing: border-box;
left: 50%; max-width: 576px;
position: absolute; margin-right: auto;
position: fixed; margin-left: auto;
padding: 0; padding: 36px;
text-align: center; /* centers all the inline content */
background-color: #363636; background-color: #363636;
color: #fff; color: #fff;
z-index: 9999;
box-shadow: 2px 4px 6px #999; box-shadow: 2px 4px 6px #999;
font-family: 'Didact Gothic', sans-serif; font-family: 'Didact Gothic', sans-serif;
} font-size: 13px;
line-height: 1.4;
.OT_dialog-blackout {
position: absolute;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #363636;
}
.OT_dialog-blackout .OT_dialog {
box-shadow: 0 0 0 transparent;
} }
.OT_dialog * { .OT_dialog * {
font-family: 'Didact Gothic', sans-serif; font-family: inherit;
} box-sizing: inherit;
.OT_dialog-plugin-prompt {
margin-left: -350px;
margin-top: -127px;
width: 650px;
height: 254px;
}
.OT_dialog-plugin-reinstall {
margin-left: -271px;
margin-top: -107px;
width: 542px;
height: 214px;
}
.OT_dialog-plugin-upgrading {
margin-left: -267px;
margin-top: -94px;
width: 514px;
height: 188px;
}
.OT_dialog-plugin-upgraded {
margin-left: -300px;
margin-top: -100px;
width: 600px;
height: 200px;
}
.OT_dialog-allow-deny-chrome-first {
margin-left: -227px;
margin-top: -122px;
width: 453px;
height: 244px;
}
.OT_dialog-allow-deny-chrome-pre-denied {
margin-left: -263px;
margin-top: -135px;
width: 526px;
height: 270px;
}
.OT_dialog-allow-deny-chrome-now-denied {
margin-left: -120px;
margin-top: -85px;
width: 256px;
height: 170px;
}
.OT_dialog-allow-deny-firefox-denied {
margin-left: -160px;
margin-top: -105px;
width: 320px;
height: 190px;
}
.OT_dialog-allow-deny-firefox-maybe-denied {
margin-left: -281px;
margin-top: -126px;
width: 562px;
height: 252px;
}
.OT_dialog-allow-highlight-chrome {
display: inline-block;
margin-top: 20px;
width: 227px;
height: 94px;
background-image: url(../images/rtc/access-prompt-chrome.png);
} }
.OT_closeButton { .OT_closeButton {
color: #999999; color: #999999;
cursor: pointer; cursor: pointer;
font-size: 32px; font-size: 32px;
line-height: 30px; line-height: 36px;
position: absolute; position: absolute;
right: 15px; right: 18px;
top: 0; top: 0;
} }
.OT_dialog-messages { .OT_dialog-messages {
position: absolute;
top: 32px;
left: 32px;
right: 32px;
text-align: center; text-align: center;
} }
.OT_dialog-allow-deny-firefox-maybe-denied .OT_dialog-messages {
top: 45px;
}
.OT_dialog-messages-main { .OT_dialog-messages-main {
margin-bottom: 36px;
line-height: 36px;
font-weight: 300; font-weight: 300;
font-size: 18pt; font-size: 24px;
line-height: 24px;
} }
.OT_dialog-messages-minor { .OT_dialog-messages-minor {
font-weight: 300; margin-bottom: 18px;
margin-top: 12px;
font-size: 13px; font-size: 13px;
line-height: 18px; line-height: 18px;
color: #A4A4A4; color: #A4A4A4;
} }
.OT_dialog-allow-deny-firefox-maybe-denied .OT_dialog-messages-minor {
margin-top: 4px;
}
.OT_dialog-messages-minor strong { .OT_dialog-messages-minor strong {
font-weight: 300;
color: #ffffff; color: #ffffff;
} }
.OT_dialog-hidden { .OT_dialog-actions-card {
display: none; display: inline-block;
}
.OT_dialog-single-button {
position: absolute;
bottom: 41px;
left: 50%;
margin-left: -97px;
height: 47px;
width: 193px;
}
.OT_dialog-single-button-wide {
bottom: 35px;
height: 140px;
left: 5px;
position: absolute;
right: 0;
}
.OT_dialog-single-button-with-title {
margin: 0 auto;
padding-left: 30px;
padding-right: 30px;
width: 270px;
}
.OT_dialog-button-pair {
position: absolute;
bottom: 45px;
left: 5px;
right: 0;
height: 94px;
}
.OT_dialog-button-with-title {
padding-left: 30px;
padding-right: 30px;
width: 260px;
float: left;
}
.OT_dialog-button-pair-seperator {
border-right: 1px solid #555555;
height: 112px;
width: 1px;
float: left;
} }
.OT_dialog-button-title { .OT_dialog-button-title {
margin-bottom: 18px;
line-height: 18px;
font-weight: 300; font-weight: 300;
text-align: center; text-align: center;
margin-bottom: 15px;
font-size: 14px; font-size: 14px;
line-height: 150%;
color: #999999; color: #999999;
} }
.OT_dialog-button-title label { .OT_dialog-button-title label {
color: #999999; color: #999999;
} }
@ -345,13 +217,13 @@
} }
.OT_dialog-button { .OT_dialog-button {
font-weight: 100; display: inline-block;
display: block;
line-height: 50px; margin-bottom: 18px;
height: 47px; padding: 0 1em;
background-color: #1CA3DC; background-color: #1CA3DC;
text-align: center; text-align: center;
font-size: 16pt;
cursor: pointer; cursor: pointer;
} }
@ -364,138 +236,67 @@
opacity: 0.5; opacity: 0.5;
} }
.OT_dialog-button.OT_dialog-button-large { .OT_dialog-button-large {
line-height: 60px; line-height: 36px;
height: 58px; padding-top: 9px;
padding-bottom: 9px;
font-weight: 100;
font-size: 24px;
} }
.OT_dialog-button.OT_dialog-button-small { .OT_dialog-button-small {
line-height: 18px;
padding-top: 9px;
padding-bottom: 9px;
background-color: #444444; background-color: #444444;
color: #999999; color: #999999;
font-size: 12pt; font-size: 16px;
height: 40px;
line-height: 40px;
margin: 20px auto 0 auto;
width: 86px;
} }
.OT_dialog-progress-bar { .OT_dialog-progress-bar {
display: inline-block; /* prevents margin collapse */
width: 100%;
margin-top: 5px;
margin-bottom: 41px;
border: 1px solid #4E4E4E; border: 1px solid #4E4E4E;
height: 8px; height: 8px;
} }
.OT_dialog-progress-bar-fill { .OT_dialog-progress-bar-fill {
height: 100%;
background-color: #29A4DA; background-color: #29A4DA;
height: 10px;
margin-top: -1px;
margin-left: -1px;
margin-right: -1px;
} }
.OT_dialog-plugin-upgrading .OT_dialog-plugin-upgrade-percentage { .OT_dialog-plugin-upgrading .OT_dialog-plugin-upgrade-percentage {
font-size: 36pt; line-height: 54px;
font-size: 48px;
font-weight: 100; font-weight: 100;
} }
.OT_dialog-plugin-upgrading .OT_dialog-progress-bar { /* Helpers */
margin-top: 25px;
margin-bottom: 25px;
}
.OT_dialog-3steps {
margin-top: 24px;
}
.OT_dialog-allow-deny-firefox-maybe-denied .OT_dialog-3steps {
margin-top: 21px;
}
.OT_dialog-3steps-step {
float: left;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 33%;
height: 140px;
padding: 0 10px;
color: #A4A4A4;
}
.OT_dialog-3steps-seperator {
float: left;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin-top: 10px;
width: 1px;
height: 68px;
background-color: #555555;
}
.OT_dialog-allow-deny-chrome-pre-denied .OT_dialog-3steps-seperator {
margin-top: 16px;
}
.OT_dialog-3steps-step-num {
font-size: 20px;
background-color: #2AA3D8;
border-radius: 20px;
line-height: 33px;
height: 33px;
width: 33px;
margin: 0 auto 17px;
}
.OT_dialog-allow-deny-chrome-pre-denied .OT_dialog-3steps-step-num {
margin-bottom: 10px;
}
.OT_dialog-allow-camera-icon {
background-color: #000;
width: 113px;
height: 48px;
margin: 10px auto 0;
background-image: url(../images/rtc/access-predenied-chrome.png);
}
/* Publisher Deny Helpers */
.OT_publisher-denied-firefox {
background-color: #fff;
}
.OT_publisher-denied-firefox p {
width: 232px;
height: 103px;
top: 50%;
left: 50%;
display: block;
position: absolute;
margin-top: -52px;
margin-left: -116px;
background-image: url(../images/rtc/access-denied-firefox.png);
background-position: 50% 0;
background-repeat: no-repeat;
}
.OT_publisher-denied-firefox span {
display: block;
position: absolute;
bottom: 0;
right: 0;
left: 0;
margin: 0 auto;
width: 232px;
height: 31px;
background-image: url(../images/rtc/access-denied-copy-firefox.png);
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
.OT_centered { .OT_centered {
position: fixed; position: fixed;
left: 50%; left: 50%;
top: 50%; top: 50%;
margin: 0; margin: 0;
}
.OT_dialog-hidden {
display: none;
}
.OT_dialog-button-block {
display: block;
}
.OT_dialog-no-natural-margin {
margin-bottom: 0;
} }
/* Publisher and Subscriber styles */ /* Publisher and Subscriber styles */
@ -803,21 +604,14 @@
.OT_publisher .OT_name, .OT_publisher .OT_name,
.OT_subscriber .OT_name { .OT_subscriber .OT_name {
left: 24px; left: 10px;
right: 37px; right: 37px;
height: 34px; height: 34px;
}
.OT_publisher .OT_name-no-bug,
.OT_subscriber .OT_name-no-bug {
left: 10px;
padding-left: 0; padding-left: 0;
} }
.OT_publisher .OT_mute, .OT_publisher .OT_mute,
.OT_subscriber .OT_mute, .OT_subscriber .OT_mute {
.OT_publisher .OT_opentok,
.OT_subscriber .OT_opentok {
border: none; border: none;
cursor: pointer; cursor: pointer;
display: block; display: block;
@ -828,21 +622,6 @@
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.OT_publisher .OT_opentok,
.OT_subscriber .OT_opentok {
background: url(../images/rtc/buttons.png) 0 -32px no-repeat;
cursor: default;
height: 18px;
left: 8px;
line-height: 18px;
top: 8px;
width: 16px;
}
.OT_micro .OT_opentok {
display: none !important;
}
.OT_publisher .OT_mute, .OT_publisher .OT_mute,
.OT_subscriber .OT_mute { .OT_subscriber .OT_mute {
right: 0; right: 0;
@ -883,21 +662,6 @@
background-position: 7px 7px; background-position: 7px 7px;
} }
/* Disabling this for now - see https://jira.tokbox.com/browse/OPENTOK-8870
.OT_publisher .OT_opentok:hover:after,
.OT_subscriber .OT_opentok:hover:after {
content: 'tokbox';
color: #fff;
font-weight: bold;
font-size: 14px;
letter-spacing: -1px;
top: 20px;
opacity: 0.5;
position: absolute;
text-indent: 0;
top: 0;
}*/
/** /**
* Styles for display modes * Styles for display modes
* *
@ -975,23 +739,6 @@
opacity: 1; opacity: 1;
} }
.OT_publisher .OT_opentok.OT_mode-off,
.OT_publisher .OT_opentok.OT_mode-auto,
.OT_subscriber .OT_opentok.OT_mode-off,
.OT_subscriber .OT_opentok.OT_mode-auto {
top: -17px;
}
.OT_publisher .OT_opentok.OT_mode-on,
.OT_publisher .OT_opentok.OT_mode-auto.OT_mode-on-hold,
.OT_publisher:hover .OT_opentok.OT_mode-auto,
.OT_subscriber .OT_opentok.OT_mode-on,
.OT_subscriber .OT_opentok.OT_mode-auto.OT_mode-on-hold,
.OT_subscriber:hover .OT_opentok.OT_mode-auto {
top: 8px;
}
/* Contains the video element, used to fix video letter-boxing */ /* Contains the video element, used to fix video letter-boxing */
.OT_video-container { .OT_video-container {
position: absolute; position: absolute;
@ -1095,7 +842,7 @@
background-image: radial-gradient(circle, rgba(151,206,0,1) 0%, rgba(151,206,0,0) 100%); background-image: radial-gradient(circle, rgba(151,206,0,1) 0%, rgba(151,206,0,0) 100%);
} }
.OT_audio-level-meter { .OT_audio-level-meter.OT_mode-off {
display: none; display: none;
} }

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,5 @@
. "$topsrcdir/browser/config/mozconfigs/common" . "$topsrcdir/browser/config/mozconfigs/common"
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging ac_add_options --enable-update-packaging

Просмотреть файл

@ -701,7 +701,7 @@ let CallsListView = Heritage.extend(WidgetMethods, {
let dimensionsNode = $("#screenshot-dimensions"); let dimensionsNode = $("#screenshot-dimensions");
let actualWidth = (width / scaling) | 0; let actualWidth = (width / scaling) | 0;
let actualHeight = (height / scaling) | 0; let actualHeight = (height / scaling) | 0;
dimensionsNode.setAttribute("value", actualWidth + " x " + actualHeight); dimensionsNode.setAttribute("value", actualWidth + " \u00D7 " + actualHeight);
window.emit(EVENTS.CALL_SCREENSHOT_DISPLAYED); window.emit(EVENTS.CALL_SCREENSHOT_DISPLAYED);
}, },

Просмотреть файл

@ -20,7 +20,7 @@ function ifTestingSupported() {
is($("#screenshot-container").hidden, false, is($("#screenshot-container").hidden, false,
"The screenshot container should now be visible."); "The screenshot container should now be visible.");
is($("#screenshot-dimensions").getAttribute("value"), "128 x 128", is($("#screenshot-dimensions").getAttribute("value"), "128" + " \u00D7 " + "128",
"The screenshot dimensions label has the expected value."); "The screenshot dimensions label has the expected value.");
is($("#screenshot-image").getAttribute("flipped"), "false", is($("#screenshot-image").getAttribute("flipped"), "false",

Просмотреть файл

@ -20,7 +20,7 @@ add_task(function*() {
tag: "DIV", tag: "DIV",
id: "top", id: "top",
classes: ".class1.class2", classes: ".class1.class2",
dims: "500 x 100" dims: "500" + " \u00D7 " + "100"
}, },
{ {
selector: "#vertical", selector: "#vertical",
@ -36,7 +36,7 @@ add_task(function*() {
tag: "DIV", tag: "DIV",
id: "bottom", id: "bottom",
classes: "", classes: "",
dims: "500 x 100" dims: "500" + " \u00D7 " + "100"
}, },
{ {
selector: "body", selector: "body",

Просмотреть файл

@ -9,8 +9,8 @@
// Expected values: // Expected values:
let res1 = [ let res1 = [
{selector: "#element-size", value: "160x160"}, {selector: "#element-size", value: "160" + "\u00D7" + "160"},
{selector: ".size > span", value: "100x100"}, {selector: ".size > span", value: "100" + "\u00D7" + "100"},
{selector: ".margin.top > span", value: 30}, {selector: ".margin.top > span", value: 30},
{selector: ".margin.left > span", value: "auto"}, {selector: ".margin.left > span", value: "auto"},
{selector: ".margin.bottom > span", value: 30}, {selector: ".margin.bottom > span", value: 30},
@ -26,8 +26,8 @@ let res1 = [
]; ];
let res2 = [ let res2 = [
{selector: "#element-size", value: "190x210"}, {selector: "#element-size", value: "190" + "\u00D7" + "210"},
{selector: ".size > span", value: "100x150"}, {selector: ".size > span", value: "100" + "\u00D7" + "150"},
{selector: ".margin.top > span", value: 30}, {selector: ".margin.top > span", value: 30},
{selector: ".margin.left > span", value: "auto"}, {selector: ".margin.left > span", value: "auto"},
{selector: ".margin.bottom > span", value: 30}, {selector: ".margin.bottom > span", value: 30},

Просмотреть файл

@ -45,7 +45,7 @@ function*(inspector, view) {
info("Checking that the layout-view shows the right value"); info("Checking that the layout-view shows the right value");
let sizeElt = view.doc.querySelector(".size > span"); let sizeElt = view.doc.querySelector(".size > span");
is(sizeElt.textContent, "100x100"); is(sizeElt.textContent, "100" + "\u00D7" + "100");
info("Listening for layout-view changes and modifying the size"); info("Listening for layout-view changes and modifying the size");
let onUpdated = waitForUpdate(inspector); let onUpdated = waitForUpdate(inspector);
@ -54,7 +54,7 @@ function*(inspector, view) {
ok(true, "Layout-view got updated"); ok(true, "Layout-view got updated");
info("Checking that the layout-view shows the right value after update"); info("Checking that the layout-view shows the right value after update");
is(sizeElt.textContent, "200x100"); is(sizeElt.textContent, "200" + "\u00D7" + "100");
}); });
addTest("Go back to the first page", addTest("Go back to the first page",

Просмотреть файл

@ -401,7 +401,7 @@ LayoutView.prototype = {
this._lastRequest = null; this._lastRequest = null;
let width = layout.width; let width = layout.width;
let height = layout.height; let height = layout.height;
let newLabel = width + "x" + height; let newLabel = width + "\u00D7" + height;
if (this.sizeHeadingLabel.textContent != newLabel) { if (this.sizeHeadingLabel.textContent != newLabel) {
this.sizeHeadingLabel.textContent = newLabel; this.sizeHeadingLabel.textContent = newLabel;
} }
@ -452,7 +452,7 @@ LayoutView.prototype = {
height -= this.map.borderTop.value + this.map.borderBottom.value + height -= this.map.borderTop.value + this.map.borderBottom.value +
this.map.paddingTop.value + this.map.paddingBottom.value; this.map.paddingTop.value + this.map.paddingBottom.value;
let newValue = width + "x" + height; let newValue = width + "\u00D7" + height;
if (this.sizeLabel.textContent != newValue) { if (this.sizeLabel.textContent != newValue) {
this.sizeLabel.textContent = newValue; this.sizeLabel.textContent = newValue;
} }

Просмотреть файл

@ -16,10 +16,10 @@ const PAGE_CONTENT = [
].join("\n"); ].join("\n");
const TEST_NODES = [ const TEST_NODES = [
{selector: "img.local", size: "192 x 192"}, {selector: "img.local", size: "192" + " \u00D7 " + "192"},
{selector: "img.data", size: "64 x 64"}, {selector: "img.data", size: "64" + " \u00D7 " + "64"},
{selector: "img.remote", size: "22 x 23"}, {selector: "img.remote", size: "22" + " \u00D7 " + "23"},
{selector: ".canvas", size: "600 x 600"} {selector: ".canvas", size: "600" + " \u00D7 " + "600"}
]; ];
add_task(function*() { add_task(function*() {

Просмотреть файл

@ -1683,7 +1683,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
*/ */
_onSecurityIconClick: function(e) { _onSecurityIconClick: function(e) {
let state = this.selectedItem.attachment.securityState; let state = this.selectedItem.attachment.securityState;
if (state === "broken" || state === "secure") { if (state !== "insecure") {
// Choose the security tab. // Choose the security tab.
NetMonitorView.NetworkDetails.widget.selectedIndex = 5; NetMonitorView.NetworkDetails.widget.selectedIndex = 5;
} }
@ -2605,7 +2605,7 @@ NetworkDetailsView.prototype = {
// in width and height attributes like the rest of the folk. Hack around // in width and height attributes like the rest of the folk. Hack around
// this by getting the bounding client rect and subtracting the margins. // this by getting the bounding client rect and subtracting the margins.
let { width, height } = e.target.getBoundingClientRect(); let { width, height } = e.target.getBoundingClientRect();
let dimensions = (width - 2) + " x " + (height - 2); let dimensions = (width - 2) + " \u00D7 " + (height - 2);
$("#response-content-image-dimensions-value").setAttribute("value", dimensions); $("#response-content-image-dimensions-value").setAttribute("value", dimensions);
}; };
} }
@ -2765,10 +2765,22 @@ NetworkDetailsView.prototype = {
let errorbox = $("#security-error"); let errorbox = $("#security-error");
let infobox = $("#security-information"); let infobox = $("#security-information");
if (securityInfo.state === "secure") { if (securityInfo.state === "secure" || securityInfo.state === "weak") {
infobox.hidden = false; infobox.hidden = false;
errorbox.hidden = true; errorbox.hidden = true;
// Warning icons
let cipher = $("#security-warning-cipher");
let sslv3 = $("#security-warning-sslv3");
if (securityInfo.state === "weak") {
cipher.hidden = securityInfo.weaknessReasons.indexOf("cipher") === -1;
sslv3.hidden = securityInfo.weaknessReasons.indexOf("sslv3") === -1;
} else {
cipher.hidden = true;
sslv3.hidden = true;
}
let enabledLabel = L10N.getStr("netmonitor.security.enabled"); let enabledLabel = L10N.getStr("netmonitor.security.enabled");
let disabledLabel = L10N.getStr("netmonitor.security.disabled"); let disabledLabel = L10N.getStr("netmonitor.security.disabled");

Просмотреть файл

@ -506,6 +506,9 @@
class="plain tabpanel-summary-value devtools-monospace" class="plain tabpanel-summary-value devtools-monospace"
crop="end" crop="end"
flex="1"/> flex="1"/>
<image class="security-warning-icon"
id="security-warning-sslv3"
tooltiptext="&netmonitorUI.security.warning.sslv3;" />
</hbox> </hbox>
<hbox id="security-ciphersuite" <hbox id="security-ciphersuite"
class="tabpanel-summary-container" class="tabpanel-summary-container"
@ -516,6 +519,9 @@
class="plain tabpanel-summary-value devtools-monospace" class="plain tabpanel-summary-value devtools-monospace"
crop="end" crop="end"
flex="1"/> flex="1"/>
<image class="security-warning-icon"
id="security-warning-cipher"
tooltiptext="&netmonitorUI.security.warning.cipher;" />
</hbox> </hbox>
</vbox> </vbox>
</vbox> </vbox>

Просмотреть файл

@ -92,6 +92,7 @@ skip-if = e10s # Bug 1091612
[browser_net_security-state.js] [browser_net_security-state.js]
[browser_net_security-tab-deselect.js] [browser_net_security-tab-deselect.js]
[browser_net_security-tab-visibility.js] [browser_net_security-tab-visibility.js]
[browser_net_security-warnings.js]
[browser_net_simple-init.js] [browser_net_simple-init.js]
[browser_net_simple-request-data.js] [browser_net_simple-request-data.js]
[browser_net_simple-request-details.js] [browser_net_simple-request-details.js]

Просмотреть файл

@ -208,7 +208,7 @@ function test() {
.getAttribute("value"), "base64", .getAttribute("value"), "base64",
"The image encoding info isn't correct."); "The image encoding info isn't correct.");
is(tabpanel.querySelector("#response-content-image-dimensions-value") is(tabpanel.querySelector("#response-content-image-dimensions-value")
.getAttribute("value"), "16 x 16", .getAttribute("value"), "16" + " \u00D7 " + "16",
"The image dimensions info isn't correct."); "The image dimensions info isn't correct.");
deferred.resolve(); deferred.resolve();

Просмотреть файл

@ -13,6 +13,7 @@ add_task(function* () {
"test1.example.com": "security-state-insecure", "test1.example.com": "security-state-insecure",
"example.com": "security-state-secure", "example.com": "security-state-secure",
"nocert.example.com": "security-state-broken", "nocert.example.com": "security-state-broken",
"rc4.example.com": "security-state-weak",
}; };
let [tab, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL); let [tab, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL);
@ -70,7 +71,12 @@ add_task(function* () {
debuggee.performRequests(1, "https://example.com" + CORS_SJS_PATH); debuggee.performRequests(1, "https://example.com" + CORS_SJS_PATH);
yield done; yield done;
is(RequestsMenu.itemCount, 3, "Three events logged."); done = waitForNetworkEvents(monitor, 1);
info("Requesting a resource over HTTPS with RC4.");
debuggee.performRequests(1, "https://rc4.example.com" + CORS_SJS_PATH);
yield done;
is(RequestsMenu.itemCount, 4, "Four events logged.");
} }
/** /**

Просмотреть файл

@ -0,0 +1,81 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test that warning indicators are shown when appropriate.
*/
const TEST_CASES = [
{
desc: "no warnings",
uri: "https://example.com" + CORS_SJS_PATH,
warnCipher: false,
warnSSLv3: false,
},
{
desc: "sslv3 warning",
uri: "https://ssl3.example.com" + CORS_SJS_PATH,
warnCipher: false,
warnSSLv3: true,
},
{
desc: "cipher warning",
uri: "https://rc4.example.com" + CORS_SJS_PATH,
warnCipher: true,
warnSSLv3: false,
},
{
desc: "cipher and sslv3 warning",
uri: "https://ssl3rc4.example.com" + CORS_SJS_PATH,
warnCipher: true,
warnSSLv3: true,
},
];
add_task(function* () {
let [tab, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL);
let { $, EVENTS, NetMonitorView } = monitor.panelWin;
let { RequestsMenu, NetworkDetails } = NetMonitorView;
RequestsMenu.lazyUpdate = false;
info("Enabling SSLv3 for the test.");
yield new promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [["security.tls.version.min", 0]]}, resolve);
});
let cipher = $("#security-warning-cipher");
let sslv3 = $("#security-warning-sslv3");
for (let test of TEST_CASES) {
info("Testing site with " + test.desc);
info("Performing request to " + test.uri);
debuggee.performRequests(1, test.uri);
yield waitForNetworkEvents(monitor, 1);
info("Selecting the request.");
RequestsMenu.selectedIndex = 0;
info("Waiting for details pane to be updated.");
yield monitor.panelWin.once(EVENTS.TAB_UPDATED);
if (NetworkDetails.widget.selectedIndex !== 5) {
info("Selecting security tab.");
NetworkDetails.widget.selectedIndex = 5;
info("Waiting for details pane to be updated.");
yield monitor.panelWin.once(EVENTS.TAB_UPDATED);
}
is(cipher.hidden, !test.warnCipher, "Cipher suite warning is hidden.");
is(sslv3.hidden, !test.warnSSLv3, "SSLv3 warning is hidden.");
RequestsMenu.clear();
}
yield teardown(monitor);
});

Просмотреть файл

@ -604,7 +604,7 @@ ResponsiveUI.prototype = {
* @param aPreset associated preset. * @param aPreset associated preset.
*/ */
setMenuLabel: function RUI_setMenuLabel(aMenuitem, aPreset) { setMenuLabel: function RUI_setMenuLabel(aMenuitem, aPreset) {
let size = Math.round(aPreset.width) + "x" + Math.round(aPreset.height); let size = Math.round(aPreset.width) + "\u00D7" + Math.round(aPreset.height);
// .inputField might be not reachable yet (async XBL loading) // .inputField might be not reachable yet (async XBL loading)
if (this.menulist.inputField) { if (this.menulist.inputField) {

Просмотреть файл

@ -210,7 +210,7 @@ function test() {
initialWidth = content.innerWidth; initialWidth = content.innerWidth;
initialHeight = content.innerHeight; initialHeight = content.innerHeight;
index = instance.menulist.selectedIndex; index = instance.menulist.selectedIndex;
let expectedValue = initialWidth + "x" + initialHeight; let expectedValue = initialWidth + "\u00D7" + initialHeight;
let expectedLabel = instance.menulist.firstChild.firstChild.getAttribute("label"); let expectedLabel = instance.menulist.firstChild.firstChild.getAttribute("label");
userInput = "I'm wrong"; userInput = "I'm wrong";

Просмотреть файл

@ -115,7 +115,7 @@ function test() {
instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab); instance = mgr.getResponsiveUIForTab(gBrowser.selectedTab);
let customPresetIndex = getPresetIndex("456x123 (Testing preset)"); let customPresetIndex = getPresetIndex("456" + "\u00D7" + "123 (Testing preset)");
info(customPresetIndex); info(customPresetIndex);
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items"); ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");

Просмотреть файл

@ -726,7 +726,7 @@ Tooltip.prototype = {
this.content = vbox; this.content = vbox;
}, },
_getImageDimensionLabel: (w, h) => w + " x " + h, _getImageDimensionLabel: (w, h) => w + " \u00D7 " + h,
/** /**
* Fill the tooltip with a new instance of the spectrum color picker widget * Fill the tooltip with a new instance of the spectrum color picker widget

Просмотреть файл

@ -896,16 +896,13 @@ Messages.Simple.prototype = Heritage.extend(Messages.BaseMessage.prototype,
let body = this.document.createElementNS(XHTML_NS, "span"); let body = this.document.createElementNS(XHTML_NS, "span");
body.className = "message-body-wrapper message-body devtools-monospace"; body.className = "message-body-wrapper message-body devtools-monospace";
let bodyInner = this.document.createElementNS(XHTML_NS, "span"); let anchor, container = body;
body.appendChild(bodyInner);
let anchor, container = bodyInner;
if (this._link || this._linkCallback) { if (this._link || this._linkCallback) {
container = anchor = this.document.createElementNS(XHTML_NS, "a"); container = anchor = this.document.createElementNS(XHTML_NS, "a");
anchor.href = this._link || "#"; anchor.href = this._link || "#";
anchor.draggable = false; anchor.draggable = false;
this._addLinkCallback(anchor, this._linkCallback); this._addLinkCallback(anchor, this._linkCallback);
bodyInner.appendChild(anchor); body.appendChild(anchor);
} }
if (typeof this._message == "function") { if (typeof this._message == "function") {

Просмотреть файл

@ -57,9 +57,7 @@ function consoleOpened(aHud) {
controller = top.document.commandDispatcher.getControllerForCommand("cmd_copy"); controller = top.document.commandDispatcher.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled"); is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
// Remove new lines since getSelection() includes one between message and line let selection = HUD.iframeWindow.getSelection() + "";
// number, but the clipboard doesn't (see bug 1119503)
let selection = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
isnot(selection.indexOf("bug587617"), -1, isnot(selection.indexOf("bug587617"), -1,
"selection text includes 'bug587617'"); "selection text includes 'bug587617'");
@ -82,9 +80,7 @@ function testContextMenuCopy() {
let copyItem = contextMenu.querySelector("*[command='cmd_copy']"); let copyItem = contextMenu.querySelector("*[command='cmd_copy']");
ok(copyItem, "the context menu on the output node has a \"Copy\" item"); ok(copyItem, "the context menu on the output node has a \"Copy\" item");
// Remove new lines since getSelection() includes one between message and line let selection = HUD.iframeWindow.getSelection() + "";
// number, but the clipboard doesn't (see bug 1119503)
let selection = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
copyItem.doCommand(); copyItem.doCommand();

Просмотреть файл

@ -69,9 +69,7 @@ function performTest(HUD, [result]) {
getControllerForCommand("cmd_copy"); getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled"); is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
// Remove new lines since getSelection() includes one between message and line let selectionText = HUD.iframeWindow.getSelection() + "";
// number, but the clipboard doesn't (see bug 1119503)
let selectionText = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
isnot(selectionText.indexOf("foobarBazBug613280"), -1, isnot(selectionText.indexOf("foobarBazBug613280"), -1,
"selection text includes 'foobarBazBug613280'"); "selection text includes 'foobarBazBug613280'");

Просмотреть файл

@ -202,6 +202,14 @@
- in a "receive" state. --> - in a "receive" state. -->
<!ENTITY netmonitorUI.timings.receive "Receiving:"> <!ENTITY netmonitorUI.timings.receive "Receiving:">
<!-- LOCALIZATION NOTE (netmonitorUI.security.warning.protocol): A tooltip
- for warning icon that indicates a connection uses insecure protocol. -->
<!ENTITY netmonitorUI.security.warning.sslv3 "The protocol SSL 3.0 is deprecated and insecure.">
<!-- LOCALIZATION NOTE (netmonitorUI.security.warning.cipher): A tooltip
- for warning icon that indicates a connection uses insecure cipher suite. -->
<!ENTITY netmonitorUI.security.warning.cipher "The cipher used for encryption is deprecated and insecure.">
<!-- LOCALIZATION NOTE (netmonitorUI.security.error): This is the label displayed <!-- LOCALIZATION NOTE (netmonitorUI.security.error): This is the label displayed
- in the security tab if a security error prevented the connection. --> - in the security tab if a security error prevented the connection. -->
<!ENTITY netmonitorUI.security.error "An error occured:"> <!ENTITY netmonitorUI.security.error "An error occured:">

Просмотреть файл

@ -44,6 +44,10 @@ netmonitor.security.state.insecure=The connection used to fetch this resource wa
# issues. # issues.
netmonitor.security.state.broken=A security error prevented the resource from being loaded. netmonitor.security.state.broken=A security error prevented the resource from being loaded.
# LOCALIZATION NOTE (netmonitor.security.state.weak)
# This string is used as an tooltip for request that had minor security issues
netmonitor.security.state.weak=This resource was transferred over a connection that used weak encryption.
# LOCALIZATION NOTE (netmonitor.security.enabled): # LOCALIZATION NOTE (netmonitor.security.enabled):
# This string is used to indicate that a specific security feature is used by # This string is used to indicate that a specific security feature is used by
# a connection in the security details tab. # a connection in the security details tab.

Просмотреть файл

@ -178,6 +178,11 @@
list-style-image: url(chrome://browser/skin/identity-icons-https.png); list-style-image: url(chrome://browser/skin/identity-icons-https.png);
} }
.security-state-weak {
cursor: pointer;
list-style-image: url(chrome://browser/skin/identity-icons-https-mixed-display.png);
}
.security-state-broken { .security-state-broken {
cursor: pointer; cursor: pointer;
list-style-image: url(chrome://browser/skin/identity-icons-https-mixed-active.png); list-style-image: url(chrome://browser/skin/identity-icons-https-mixed-active.png);
@ -578,6 +583,21 @@ label.requests-menu-status-code {
white-space: pre-wrap; white-space: pre-wrap;
} }
.security-warning-icon {
background-image: url(alerticon-warning.png);
background-size: 13px 12px;
-moz-margin-start: 5px;
vertical-align: top;
width: 13px;
height: 12px;
}
@media (min-resolution: 2dppx) {
.security-warning-icon {
background-image: url(alerticon-warning@2x.png);
}
}
/* Custom request form */ /* Custom request form */
#custom-pane { #custom-pane {

Просмотреть файл

@ -117,7 +117,7 @@ a {
display: flex; display: flex;
} }
.message-body > * { .message-body {
white-space: pre-wrap; white-space: pre-wrap;
word-wrap: break-word; word-wrap: break-word;
} }

Просмотреть файл

@ -25,6 +25,14 @@ treecol {
/* Category List */ /* Category List */
#categories {
max-height: 100vh;
}
#categories > scrollbox {
overflow-x: hidden !important;
}
.category-icon { .category-icon {
list-style-image: url("chrome://browser/skin/preferences/in-content/icons.png"); list-style-image: url("chrome://browser/skin/preferences/in-content/icons.png");
} }

Просмотреть файл

@ -97,8 +97,7 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
// Do the first and potentially trial encoding as preformatted and raw. // Do the first and potentially trial encoding as preformatted and raw.
uint32_t flags = aFlags | nsIDocumentEncoder::OutputPreformatted uint32_t flags = aFlags | nsIDocumentEncoder::OutputPreformatted
| nsIDocumentEncoder::OutputRaw | nsIDocumentEncoder::OutputRaw;
| nsIDocumentEncoder::OutputForPlainTextClipboardCopy;
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc); nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
NS_ASSERTION(domDoc, "Need a document"); NS_ASSERTION(domDoc, "Need a document");

Просмотреть файл

@ -227,13 +227,6 @@ interface nsIDocumentEncoder : nsISupports
*/ */
const unsigned long OutputDontRemoveLineEndingSpaces = (1 << 24); const unsigned long OutputDontRemoveLineEndingSpaces = (1 << 24);
/**
* Serialize in a way that is suitable for copying a plaintext version of the
* document to the clipboard. This can for example cause line endings to be
* injected at preformatted block element boundaries.
*/
const unsigned long OutputForPlainTextClipboardCopy = (1 << 25);
/** /**
* Initialize with a pointer to the document and the mime type. * Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode. * @param aDocument Document to encode.

Просмотреть файл

@ -91,8 +91,6 @@ nsPlainTextSerializer::nsPlainTextSerializer()
mPreFormatted = false; mPreFormatted = false;
mStartedOutput = false; mStartedOutput = false;
mPreformattedBlockBoundary = false;
// initialize the tag stack to zero: // initialize the tag stack to zero:
// The stack only ever contains pointers to static atoms, so they don't // The stack only ever contains pointers to static atoms, so they don't
// need refcounting. // need refcounting.
@ -169,8 +167,6 @@ nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn,
mLineBreakDue = false; mLineBreakDue = false;
mFloatingLines = -1; mFloatingLines = -1;
mPreformattedBlockBoundary = false;
if (mFlags & nsIDocumentEncoder::OutputFormatted) { if (mFlags & nsIDocumentEncoder::OutputFormatted) {
// Get some prefs that controls how we do formatted output // Get some prefs that controls how we do formatted output
mStructs = Preferences::GetBool(PREF_STRUCTS, mStructs); mStructs = Preferences::GetBool(PREF_STRUCTS, mStructs);
@ -441,16 +437,6 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
return NS_OK; return NS_OK;
} }
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (mPreformattedBlockBoundary && DoOutput()) {
// Should always end a line, but get no more whitespace
if (mFloatingLines < 0)
mFloatingLines = 0;
mLineBreakDue = true;
}
mPreformattedBlockBoundary = false;
}
if (mFlags & nsIDocumentEncoder::OutputRaw) { if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy // Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other // here like indenting, adding line breaks or any other
@ -684,7 +670,7 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
// Else make sure we'll separate block level tags, // Else make sure we'll separate block level tags,
// even if we're about to leave, before doing any other formatting. // even if we're about to leave, before doing any other formatting.
else if (IsElementBlock(mElement)) { else if (nsContentUtils::IsHTMLBlock(aTag)) {
EnsureVerticalSpace(0); EnsureVerticalSpace(0);
} }
@ -781,14 +767,6 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
return NS_OK; return NS_OK;
} }
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (DoOutput() && IsInPre() && IsElementBlock(mElement)) {
// If we're closing a preformatted block element, output a line break
// when we find a new container.
mPreformattedBlockBoundary = true;
}
}
if (mFlags & nsIDocumentEncoder::OutputRaw) { if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy // Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other // here like indenting, adding line breaks or any other
@ -909,7 +887,8 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
else if (aTag == nsGkAtoms::q) { else if (aTag == nsGkAtoms::q) {
Write(NS_LITERAL_STRING("\"")); Write(NS_LITERAL_STRING("\""));
} }
else if (IsElementBlock(mElement) && aTag != nsGkAtoms::script) { else if (nsContentUtils::IsHTMLBlock(aTag)
&& aTag != nsGkAtoms::script) {
// All other blocks get 1 vertical space after them // All other blocks get 1 vertical space after them
// in formatted mode, otherwise 0. // in formatted mode, otherwise 0.
// This is hard. Sometimes 0 is a better number, but // This is hard. Sometimes 0 is a better number, but
@ -1058,8 +1037,6 @@ nsPlainTextSerializer::DoAddText(bool aIsLineBreak, const nsAString& aText)
nsresult nsresult
nsPlainTextSerializer::DoAddLeaf(nsIAtom* aTag) nsPlainTextSerializer::DoAddLeaf(nsIAtom* aTag)
{ {
mPreformattedBlockBoundary = false;
// If we don't want any output, just return // If we don't want any output, just return
if (!DoOutput()) { if (!DoOutput()) {
return NS_OK; return NS_OK;
@ -1801,20 +1778,6 @@ nsPlainTextSerializer::IsElementPreformatted(Element* aElement)
return GetIdForContent(aElement) == nsGkAtoms::pre; return GetIdForContent(aElement) == nsGkAtoms::pre;
} }
bool
nsPlainTextSerializer::IsElementBlock(Element* aElement)
{
nsRefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
if (styleContext) {
const nsStyleDisplay* displayStyle = styleContext->StyleDisplay();
return displayStyle->IsBlockOutsideStyle();
}
// Fall back to looking at the tag, in case there is no style information.
return nsContentUtils::IsHTMLBlock(GetIdForContent(aElement));
}
/** /**
* This method is required only to identify LI's inside OL. * This method is required only to identify LI's inside OL.
* Returns TRUE if we are inside an OL tag and FALSE otherwise. * Returns TRUE if we are inside an OL tag and FALSE otherwise.

Просмотреть файл

@ -115,7 +115,6 @@ private:
bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag); bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag);
bool IsElementPreformatted(mozilla::dom::Element* aElement); bool IsElementPreformatted(mozilla::dom::Element* aElement);
bool IsElementBlock(mozilla::dom::Element* aElement);
private: private:
nsString mCurrentLine; nsString mCurrentLine;
@ -170,9 +169,7 @@ private:
// While handling a new tag, this variable should remind if any line break // While handling a new tag, this variable should remind if any line break
// is due because of a closing tag. Setting it to "TRUE" while closing the tags. // is due because of a closing tag. Setting it to "TRUE" while closing the tags.
// Hence opening tags are guaranteed to start with appropriate line breaks. // Hence opening tags are guaranteed to start with appropriate line breaks.
bool mLineBreakDue; bool mLineBreakDue;
bool mPreformattedBlockBoundary;
nsString mURL; nsString mURL;
int32_t mHeaderStrategy; /* Header strategy (pref) int32_t mHeaderStrategy; /* Header strategy (pref)

Просмотреть файл

@ -137,31 +137,6 @@ TestPreElement()
return NS_OK; return NS_OK;
} }
nsresult
TestBlockElement()
{
nsString test;
test.AppendLiteral(
"<html>" NS_LINEBREAK
"<body>" NS_LINEBREAK
"<div>" NS_LINEBREAK
" first" NS_LINEBREAK
"</div>" NS_LINEBREAK
"<div>" NS_LINEBREAK
" second" NS_LINEBREAK
"</div>" NS_LINEBREAK
"</body>" NS_LINEBREAK "</html>");
ConvertBufToPlainText(test, 0);
if (!test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK)) {
fail("Wrong prettyprinted html to text serialization");
return NS_ERROR_FAILURE;
}
passed("prettyprinted HTML to text serialization test");
return NS_OK;
}
nsresult nsresult
TestPlainTextSerializer() TestPlainTextSerializer()
{ {
@ -188,9 +163,6 @@ TestPlainTextSerializer()
rv = TestPreElement(); rv = TestPreElement();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = TestBlockElement();
NS_ENSURE_SUCCESS(rv, rv);
// Add new tests here... // Add new tests here...
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -20,14 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=116083
<div data-result="bar baz"><span style="white-space: pre-wrap">bar </span>baz</div> <div data-result="bar baz"><span style="white-space: pre-wrap">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: pre-line">bar </span>baz</div> <div data-result="bar baz"><span style="white-space: pre-line">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: -moz-pre-space">bar </span>baz</div> <div data-result="bar baz"><span style="white-space: -moz-pre-space">bar </span>baz</div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="&#10;foo bar&#10;">foo bar</div> <div data-result="&#10;foo bar&#10;">foo bar</div>
</div> </div>
<script type="application/javascript"> <script type="application/javascript">

Просмотреть файл

@ -1600,7 +1600,7 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut)
return NS_ERROR_ILLEGAL_VALUE; // end of PDU return NS_ERROR_ILLEGAL_VALUE; // end of PDU
} }
const char* end = static_cast<char*>(memchr(str, '\0', aPDU.GetSize())); const char* end = static_cast<char*>(memchr(str, '\0', aPDU.GetSize() + 1));
if (NS_WARN_IF(!end)) { if (NS_WARN_IF(!end)) {
return NS_ERROR_ILLEGAL_VALUE; // no string terminator return NS_ERROR_ILLEGAL_VALUE; // no string terminator
} }

Просмотреть файл

@ -116,7 +116,7 @@ BroadcastSystemMessage(const nsAString& aType,
aData.get_nsString().Length()); aData.get_nsString().Length());
value = STRING_TO_JSVAL(jsData); value = STRING_TO_JSVAL(jsData);
} else if (aData.type() == BluetoothValue::TArrayOfBluetoothNamedValue) { } else if (aData.type() == BluetoothValue::TArrayOfBluetoothNamedValue) {
JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx))); JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx));
if (!obj) { if (!obj) {
BT_WARNING("Failed to new JSObject for system message!"); BT_WARNING("Failed to new JSObject for system message!");
return false; return false;

Просмотреть файл

@ -106,6 +106,7 @@ namespace system {
#define USB_FUNC_NONE "none" #define USB_FUNC_NONE "none"
#define USB_FUNC_RNDIS "rndis" #define USB_FUNC_RNDIS "rndis"
#define USB_FUNC_UMS "mass_storage" #define USB_FUNC_UMS "mass_storage"
#define USB_FUNC_DEFAULT "default"
class AutoMounter; class AutoMounter;
@ -552,6 +553,9 @@ SetUsbFunction(const char* aUsbFunc)
// We're enabling UMS. For this we make the assumption that the persisted // We're enabling UMS. For this we make the assumption that the persisted
// property has mass_storage enabled. // property has mass_storage enabled.
property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, ""); property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
} else if (strcmp(aUsbFunc, USB_FUNC_DEFAULT) == 0) {
// Set the property as PERSIST_SYS_USB_CONFIG
property_get(PERSIST_SYS_USB_CONFIG, newSysUsbConfig, "");
} else { } else {
printf_stderr("AutoMounter::SetUsbFunction Unrecognized aUsbFunc '%s'\n", aUsbFunc); printf_stderr("AutoMounter::SetUsbFunction Unrecognized aUsbFunc '%s'\n", aUsbFunc);
MOZ_ASSERT(0); MOZ_ASSERT(0);
@ -626,6 +630,7 @@ AutoMounter::StartMtpServer()
sMozMtpServer = new MozMtpServer(); sMozMtpServer = new MozMtpServer();
if (!sMozMtpServer->Init()) { if (!sMozMtpServer->Init()) {
sMozMtpServer = nullptr;
return false; return false;
} }
@ -786,9 +791,15 @@ AutoMounter::UpdateState()
if (StartMtpServer()) { if (StartMtpServer()) {
SetState(STATE_MTP_STARTED); SetState(STATE_MTP_STARTED);
} else { } else {
// Unable to start MTP. Go back to UMS. if (umsAvail) {
SetUsbFunction(USB_FUNC_UMS); // Unable to start MTP. Go back to UMS.
SetState(STATE_UMS_CONFIGURING); LOG("UpdateState: StartMtpServer failed, switch to UMS");
SetUsbFunction(USB_FUNC_UMS);
SetState(STATE_UMS_CONFIGURING);
} else {
LOG("UpdateState: StartMtpServer failed, keep idle state");
SetUsbFunction(USB_FUNC_DEFAULT);
}
} }
} else { } else {
// We need to configure USB to use mtp. Wait for it to be configured // We need to configure USB to use mtp. Wait for it to be configured
@ -849,6 +860,10 @@ AutoMounter::UpdateState()
SetState(STATE_UMS_CONFIGURING); SetState(STATE_UMS_CONFIGURING);
break; break;
} }
// if ums/rndis is not available and mtp is disable,
// restore the usb function as PERSIST_SYS_USB_CONFIG.
SetUsbFunction(USB_FUNC_DEFAULT);
SetState(STATE_IDLE); SetState(STATE_IDLE);
break; break;

Просмотреть файл

@ -232,7 +232,7 @@ MozMtpServer::Init()
const char *mtpUsbFilename = "/dev/mtp_usb"; const char *mtpUsbFilename = "/dev/mtp_usb";
mMtpUsbFd = open(mtpUsbFilename, O_RDWR); mMtpUsbFd = open(mtpUsbFilename, O_RDWR);
if (mMtpUsbFd.get() < 0) { if (mMtpUsbFd.get() < 0) {
MTP_ERR("open of '%s' failed", mtpUsbFilename); MTP_ERR("open of '%s' failed((%s))", mtpUsbFilename, strerror(errno));
return false; return false;
} }
MTP_LOG("Opened '%s' fd %d", mtpUsbFilename, mMtpUsbFd.get()); MTP_LOG("Opened '%s' fd %d", mtpUsbFilename, mMtpUsbFd.get());

Просмотреть файл

@ -19,7 +19,8 @@ enum NFCTechType {
"ISO-DEP", // NFCForum-TS-DigitalProtocol-1.1 ISO-DEP. "ISO-DEP", // NFCForum-TS-DigitalProtocol-1.1 ISO-DEP.
"MIFARE-Classic", // MIFARE Classic from NXP. "MIFARE-Classic", // MIFARE Classic from NXP.
"MIFARE-Ultralight", // MIFARE Ultralight from NXP. "MIFARE-Ultralight", // MIFARE Ultralight from NXP.
"NFC-Barcode" // NFC Barcode from Kovio. "NFC-Barcode", // NFC Barcode from Kovio.
"Unknown"
}; };
/** /**

Просмотреть файл

@ -24,7 +24,6 @@
#include <sched.h> #include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <sys/klog.h> #include <sys/klog.h>
#include <sys/stat.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <time.h> #include <time.h>
@ -48,7 +47,6 @@
#include "HalImpl.h" #include "HalImpl.h"
#include "HalLog.h" #include "HalLog.h"
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/battery/Constants.h" #include "mozilla/dom/battery/Constants.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/FileUtils.h" #include "mozilla/FileUtils.h"
@ -630,6 +628,28 @@ namespace {
/** /**
* RAII class to help us remember to close file descriptors. * RAII class to help us remember to close file descriptors.
*/ */
const char *wakeLockFilename = "/sys/power/wake_lock";
const char *wakeUnlockFilename = "/sys/power/wake_unlock";
template<ssize_t n>
bool ReadFromFile(const char *filename, char (&buf)[n])
{
int fd = open(filename, O_RDONLY);
ScopedClose autoClose(fd);
if (fd < 0) {
HAL_LOG("Unable to open file %s.", filename);
return false;
}
ssize_t numRead = read(fd, buf, n);
if (numRead < 0) {
HAL_LOG("Error reading from file %s.", filename);
return false;
}
buf[std::min(numRead, n - 1)] = '\0';
return true;
}
bool WriteToFile(const char *filename, const char *toWrite) bool WriteToFile(const char *filename, const char *toWrite)
{ {
@ -755,9 +775,6 @@ static Monitor* sInternalLockCpuMonitor = nullptr;
static void static void
UpdateCpuSleepState() UpdateCpuSleepState()
{ {
const char *wakeLockFilename = "/sys/power/wake_lock";
const char *wakeUnlockFilename = "/sys/power/wake_unlock";
sInternalLockCpuMonitor->AssertCurrentThreadOwns(); sInternalLockCpuMonitor->AssertCurrentThreadOwns();
bool allowed = sCpuSleepAllowed && !sInternalLockCpuCount; bool allowed = sCpuSleepAllowed && !sInternalLockCpuCount;
WriteToFile(allowed ? wakeUnlockFilename : wakeLockFilename, "gecko"); WriteToFile(allowed ? wakeUnlockFilename : wakeLockFilename, "gecko");
@ -1269,6 +1286,7 @@ OomVictimLogger::Observe(
lineTimestampFound = true; lineTimestampFound = true;
mLastLineChecked = lineTimestamp; mLastLineChecked = lineTimestamp;
} }
// Log interesting lines // Log interesting lines
for (size_t i = 0; i < regex_count; i++) { for (size_t i = 0; i < regex_count; i++) {
@ -1294,347 +1312,6 @@ OomVictimLogger::Observe(
return NS_OK; return NS_OK;
} }
/**
* Wraps a particular ProcessPriority, giving us easy access to the prefs that
* are relevant to it.
*
* Creating a PriorityClass also ensures that the control group is created.
*/
class PriorityClass
{
public:
/**
* Create a PriorityClass for the given ProcessPriority. This implicitly
* reads the relevant prefs and opens the cgroup.procs file of the relevant
* control group caching its file descriptor for later use.
*/
PriorityClass(ProcessPriority aPriority);
/**
* Closes the file descriptor for the cgroup.procs file of the associated
* control group.
*/
~PriorityClass();
PriorityClass(const PriorityClass& aOther);
PriorityClass& operator=(const PriorityClass& aOther);
ProcessPriority Priority()
{
return mPriority;
}
int32_t OomScoreAdj()
{
return clamped<int32_t>(mOomScoreAdj, OOM_SCORE_ADJ_MIN, OOM_SCORE_ADJ_MAX);
}
int32_t KillUnderKB()
{
return mKillUnderKB;
}
nsCString CGroup()
{
return mGroup;
}
/**
* Adds a process to this priority class, this moves the process' PID into
* the associated control group.
*
* @param aPid The PID of the process to be added.
*/
void AddProcess(int aPid);
private:
ProcessPriority mPriority;
int32_t mOomScoreAdj;
int32_t mKillUnderKB;
int mCpuCGroupProcsFd;
int mMemCGroupProcsFd;
nsCString mGroup;
/**
* Return a string that identifies where we can find the value of aPref
* that's specific to mPriority. For example, we might return
* "hal.processPriorityManager.gonk.FOREGROUND_HIGH.oomScoreAdjust".
*/
nsCString PriorityPrefName(const char* aPref)
{
return nsPrintfCString("hal.processPriorityManager.gonk.%s.%s",
ProcessPriorityToString(mPriority), aPref);
}
/**
* Get the full path of the cgroup.procs file associated with the group.
*/
nsCString CpuCGroupProcsFilename()
{
nsCString cgroupName = mGroup;
/* If mGroup is empty, our cgroup.procs file is the root procs file,
* located at /dev/cpuctl/cgroup.procs. Otherwise our procs file is
* /dev/cpuctl/NAME/cgroup.procs. */
if (!mGroup.IsEmpty()) {
cgroupName.AppendLiteral("/");
}
return NS_LITERAL_CSTRING("/dev/cpuctl/") + cgroupName +
NS_LITERAL_CSTRING("cgroup.procs");
}
nsCString MemCGroupProcsFilename()
{
nsCString cgroupName = mGroup;
/* If mGroup is empty, our cgroup.procs file is the root procs file,
* located at /sys/fs/cgroup/memory/cgroup.procs. Otherwise our procs
* file is /sys/fs/cgroup/memory/NAME/cgroup.procs. */
if (!mGroup.IsEmpty()) {
cgroupName.AppendLiteral("/");
}
return NS_LITERAL_CSTRING("/sys/fs/cgroup/memory/") + cgroupName +
NS_LITERAL_CSTRING("cgroup.procs");
}
int OpenCpuCGroupProcs()
{
return open(CpuCGroupProcsFilename().get(), O_WRONLY);
}
int OpenMemCGroupProcs()
{
return open(MemCGroupProcsFilename().get(), O_WRONLY);
}
};
/**
* Creates a directory and parents (essentially mkdir -p, but
* this only create the directories within the cgroup name).
*/
static bool MakeCGroupDir(const nsACString& aRootDir,
const nsACString& aGroupName)
{
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
// Create directories contained within aGroupName
nsCString cgroupIter = aGroupName + kSlash;
int32_t offset = 0;
while ((offset = cgroupIter.FindChar('/', offset)) != -1) {
nsAutoCString path = aRootDir + Substring(cgroupIter, 0, offset);
int rv = mkdir(path.get(), 0744);
if (rv == -1 && errno != EEXIST) {
HAL_LOG("Could not create the %s control group.", path.get());
return false;
}
offset++;
}
return true;
}
/**
* Try to create the cgroup for the given PriorityClass, if it doesn't already
* exist. This essentially implements mkdir -p; that is, we create parent
* cgroups as necessary. The group parameters are also set according to
* the corresponding preferences.
*
* @param aGroup The name of the group.
* @return true if we successfully created the cgroup, or if it already
* exists. Otherwise, return false.
*/
static bool
EnsureCpuCGroupExists(const nsACString& aGroup)
{
NS_NAMED_LITERAL_CSTRING(kDevCpuCtl, "/dev/cpuctl/");
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups.");
/* If cgroup is not empty, append the cgroup name and a dot to obtain the
* group specific preferences. */
if (!aGroup.IsEmpty()) {
prefPrefix += aGroup + NS_LITERAL_CSTRING(".");
}
nsAutoCString cpuSharesPref(prefPrefix + NS_LITERAL_CSTRING("cpu_shares"));
int cpuShares = Preferences::GetInt(cpuSharesPref.get());
nsAutoCString cpuNotifyOnMigratePref(prefPrefix
+ NS_LITERAL_CSTRING("cpu_notify_on_migrate"));
int cpuNotifyOnMigrate = Preferences::GetInt(cpuNotifyOnMigratePref.get());
if (!MakeCGroupDir(kDevCpuCtl, aGroup)) {
return false;
}
nsAutoCString pathPrefix(kDevCpuCtl + aGroup + kSlash);
nsAutoCString cpuSharesPath(pathPrefix + NS_LITERAL_CSTRING("cpu.shares"));
if (cpuShares && !WriteToFile(cpuSharesPath.get(),
nsPrintfCString("%d", cpuShares).get())) {
HAL_LOG("Could not set the cpu share for group %s", cpuSharesPath.get());
return false;
}
nsAutoCString notifyOnMigratePath(pathPrefix
+ NS_LITERAL_CSTRING("cpu.notify_on_migrate"));
if (!WriteToFile(notifyOnMigratePath.get(),
nsPrintfCString("%d", cpuNotifyOnMigrate).get())) {
HAL_LOG("Could not set the cpu migration notification flag for group %s",
notifyOnMigratePath.get());
return false;
}
return true;
}
static bool
EnsureMemCGroupExists(const nsACString& aGroup)
{
NS_NAMED_LITERAL_CSTRING(kMemCtl, "/sys/fs/cgroup/memory/");
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups.");
/* If cgroup is not empty, append the cgroup name and a dot to obtain the
* group specific preferences. */
if (!aGroup.IsEmpty()) {
prefPrefix += aGroup + NS_LITERAL_CSTRING(".");
}
nsAutoCString memSwappinessPref(prefPrefix +
NS_LITERAL_CSTRING("memory_swappiness"));
int memSwappiness = Preferences::GetInt(memSwappinessPref.get());
if (!MakeCGroupDir(kMemCtl, aGroup)) {
return false;
}
nsAutoCString pathPrefix(kMemCtl + aGroup + kSlash);
nsAutoCString memSwappinessPath(pathPrefix +
NS_LITERAL_CSTRING("memory.swappiness"));
if (!WriteToFile(memSwappinessPath.get(),
nsPrintfCString("%d", memSwappiness).get())) {
HAL_LOG("Could not set the memory.swappiness for group %s",
memSwappinessPath.get());
return false;
}
return true;
}
PriorityClass::PriorityClass(ProcessPriority aPriority)
: mPriority(aPriority)
, mOomScoreAdj(0)
, mKillUnderKB(0)
, mCpuCGroupProcsFd(-1)
, mMemCGroupProcsFd(-1)
{
DebugOnly<nsresult> rv;
rv = Preferences::GetInt(PriorityPrefName("OomScoreAdjust").get(),
&mOomScoreAdj);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing oom_score_adj preference");
rv = Preferences::GetInt(PriorityPrefName("KillUnderKB").get(),
&mKillUnderKB);
rv = Preferences::GetCString(PriorityPrefName("cgroup").get(), &mGroup);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing control group preference");
if (EnsureCpuCGroupExists(mGroup)) {
mCpuCGroupProcsFd = OpenCpuCGroupProcs();
}
if (EnsureMemCGroupExists(mGroup)) {
mMemCGroupProcsFd = OpenMemCGroupProcs();
}
}
PriorityClass::~PriorityClass()
{
MOZ_TEMP_FAILURE_RETRY(close(mCpuCGroupProcsFd));
MOZ_TEMP_FAILURE_RETRY(close(mMemCGroupProcsFd));
}
PriorityClass::PriorityClass(const PriorityClass& aOther)
: mPriority(aOther.mPriority)
, mOomScoreAdj(aOther.mOomScoreAdj)
, mKillUnderKB(aOther.mKillUnderKB)
, mGroup(aOther.mGroup)
{
mCpuCGroupProcsFd = OpenCpuCGroupProcs();
mMemCGroupProcsFd = OpenMemCGroupProcs();
}
PriorityClass& PriorityClass::operator=(const PriorityClass& aOther)
{
mPriority = aOther.mPriority;
mOomScoreAdj = aOther.mOomScoreAdj;
mKillUnderKB = aOther.mKillUnderKB;
mGroup = aOther.mGroup;
mCpuCGroupProcsFd = OpenCpuCGroupProcs();
mMemCGroupProcsFd = OpenMemCGroupProcs();
return *this;
}
void PriorityClass::AddProcess(int aPid)
{
if (mCpuCGroupProcsFd >= 0) {
nsPrintfCString str("%d", aPid);
if (write(mCpuCGroupProcsFd, str.get(), str.Length()) < 0) {
HAL_ERR("Couldn't add PID %d to the %s cpu control group",
aPid, mGroup.get());
}
}
if (mMemCGroupProcsFd >= 0) {
nsPrintfCString str("%d", aPid);
if (write(mMemCGroupProcsFd, str.get(), str.Length()) < 0) {
HAL_ERR("Couldn't add PID %d to the %s memory control group",
aPid, mGroup.get());
}
}
}
/**
* Get the PriorityClass associated with the given ProcessPriority.
*
* If you pass an invalid ProcessPriority value, we return null.
*
* The pointers returned here are owned by GetPriorityClass (don't free them
* yourself). They are guaranteed to stick around until shutdown.
*/
PriorityClass*
GetPriorityClass(ProcessPriority aPriority)
{
static StaticAutoPtr<nsTArray<PriorityClass>> priorityClasses;
// Initialize priorityClasses if this is the first time we're running this
// method.
if (!priorityClasses) {
priorityClasses = new nsTArray<PriorityClass>();
ClearOnShutdown(&priorityClasses);
for (int32_t i = 0; i < NUM_PROCESS_PRIORITY; i++) {
priorityClasses->AppendElement(PriorityClass(ProcessPriority(i)));
}
}
if (aPriority < 0 ||
static_cast<uint32_t>(aPriority) >= priorityClasses->Length()) {
return nullptr;
}
return &(*priorityClasses)[aPriority];
}
static void static void
EnsureKernelLowMemKillerParamsSet() EnsureKernelLowMemKillerParamsSet()
{ {
@ -1675,12 +1352,21 @@ EnsureKernelLowMemKillerParamsSet()
// The system doesn't function correctly if we're missing these prefs, so // The system doesn't function correctly if we're missing these prefs, so
// crash loudly. // crash loudly.
PriorityClass* pc = GetPriorityClass(static_cast<ProcessPriority>(i)); ProcessPriority priority = static_cast<ProcessPriority>(i);
int32_t oomScoreAdj = pc->OomScoreAdj(); int32_t oomScoreAdj;
int32_t killUnderKB = pc->KillUnderKB(); if (!NS_SUCCEEDED(Preferences::GetInt(
nsPrintfCString("hal.processPriorityManager.gonk.%s.OomScoreAdjust",
ProcessPriorityToString(priority)).get(),
&oomScoreAdj))) {
MOZ_CRASH();
}
if (killUnderKB == 0) { int32_t killUnderKB;
if (!NS_SUCCEEDED(Preferences::GetInt(
nsPrintfCString("hal.processPriorityManager.gonk.%s.KillUnderKB",
ProcessPriorityToString(priority)).get(),
&killUnderKB))) {
// ProcessPriority values like PROCESS_PRIORITY_FOREGROUND_KEYBOARD, // ProcessPriority values like PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
// which has only OomScoreAdjust but lacks KillUnderMB value, will not // which has only OomScoreAdjust but lacks KillUnderMB value, will not
// create new LMK parameters. // create new LMK parameters.
@ -1711,8 +1397,7 @@ EnsureKernelLowMemKillerParamsSet()
minfreeParams.Cut(minfreeParams.Length() - 1, 1); minfreeParams.Cut(minfreeParams.Length() - 1, 1);
if (!adjParams.IsEmpty() && !minfreeParams.IsEmpty()) { if (!adjParams.IsEmpty() && !minfreeParams.IsEmpty()) {
WriteToFile("/sys/module/lowmemorykiller/parameters/adj", adjParams.get()); WriteToFile("/sys/module/lowmemorykiller/parameters/adj", adjParams.get());
WriteToFile("/sys/module/lowmemorykiller/parameters/minfree", WriteToFile("/sys/module/lowmemorykiller/parameters/minfree", minfreeParams.get());
minfreeParams.get());
} }
// Set the low-memory-notification threshold. // Set the low-memory-notification threshold.
@ -1734,6 +1419,148 @@ EnsureKernelLowMemKillerParamsSet()
} }
} }
static void
SetNiceForPid(int aPid, int aNice)
{
errno = 0;
int origProcPriority = getpriority(PRIO_PROCESS, aPid);
if (errno) {
HAL_LOG("Unable to get nice for pid=%d; error %d. SetNiceForPid bailing.",
aPid, errno);
return;
}
int rv = setpriority(PRIO_PROCESS, aPid, aNice);
if (rv) {
HAL_LOG("Unable to set nice for pid=%d; error %d. SetNiceForPid bailing.",
aPid, errno);
return;
}
// On Linux, setpriority(aPid) modifies the priority only of the main
// thread of that process. We have to modify the priorities of all of the
// process's threads as well, so iterate over all the threads and increase
// each of their priorites by aNice - origProcPriority (and also ensure that
// none of the tasks has a lower priority than the main thread).
//
// This is horribly racy.
DIR* tasksDir = opendir(nsPrintfCString("/proc/%d/task/", aPid).get());
if (!tasksDir) {
HAL_LOG("Unable to open /proc/%d/task. SetNiceForPid bailing.", aPid);
return;
}
// Be careful not to leak tasksDir; after this point, we must call closedir().
while (struct dirent* de = readdir(tasksDir)) {
char* endptr = nullptr;
long tidlong = strtol(de->d_name, &endptr, /* base */ 10);
if (*endptr || tidlong < 0 || tidlong > INT32_MAX || tidlong == aPid) {
// if dp->d_name was not an integer, was negative (?!) or too large, or
// was the same as aPid, we're not interested.
//
// (The |tidlong == aPid| check is very important; without it, we'll
// renice aPid twice, and the second renice will be relative to the
// priority set by the first renice.)
continue;
}
int tid = static_cast<int>(tidlong);
// Do not set the priority of threads running with a real-time policy
// as part of the bulk process adjustment. These threads need to run
// at their specified priority in order to meet timing guarantees.
int schedPolicy = sched_getscheduler(tid);
if (schedPolicy == SCHED_FIFO || schedPolicy == SCHED_RR) {
continue;
}
errno = 0;
// Get and set the task's new priority.
int origtaskpriority = getpriority(PRIO_PROCESS, tid);
if (errno) {
HAL_LOG("Unable to get nice for tid=%d (pid=%d); error %d. This isn't "
"necessarily a problem; it could be a benign race condition.",
tid, aPid, errno);
continue;
}
int newtaskpriority =
std::max(origtaskpriority - origProcPriority + aNice, aNice);
// Do not reduce priority of threads already running at priorities greater
// than normal. These threads are likely special service threads that need
// elevated priorities to process audio, display composition, etc.
if (newtaskpriority > origtaskpriority &&
origtaskpriority < ANDROID_PRIORITY_NORMAL) {
continue;
}
rv = setpriority(PRIO_PROCESS, tid, newtaskpriority);
if (rv) {
HAL_LOG("Unable to set nice for tid=%d (pid=%d); error %d. This isn't "
"necessarily a problem; it could be a benign race condition.",
tid, aPid, errno);
continue;
}
}
HAL_LOG("Changed nice for pid %d from %d to %d.",
aPid, origProcPriority, aNice);
closedir(tasksDir);
}
/*
* Used to store the nice value adjustments and oom_adj values for the various
* process priority levels.
*/
struct ProcessPriorityPrefs {
bool initialized;
int lowPriorityNice;
struct {
int nice;
int oomScoreAdj;
} priorities[NUM_PROCESS_PRIORITY];
};
/*
* Reads the preferences for the various process priority levels and sets up
* watchers so that if they're dynamically changed the change is reflected on
* the appropriate variables.
*/
void
EnsureProcessPriorityPrefs(ProcessPriorityPrefs* prefs)
{
if (prefs->initialized) {
return;
}
// Read the preferences for process priority levels
for (int i = PROCESS_PRIORITY_BACKGROUND; i < NUM_PROCESS_PRIORITY; i++) {
ProcessPriority priority = static_cast<ProcessPriority>(i);
// Read the nice values
const char* processPriorityStr = ProcessPriorityToString(priority);
nsPrintfCString niceStr("hal.processPriorityManager.gonk.%s.Nice",
processPriorityStr);
Preferences::AddIntVarCache(&prefs->priorities[i].nice, niceStr.get());
// Read the oom_adj scores
nsPrintfCString oomStr("hal.processPriorityManager.gonk.%s.OomScoreAdjust",
processPriorityStr);
Preferences::AddIntVarCache(&prefs->priorities[i].oomScoreAdj,
oomStr.get());
}
Preferences::AddIntVarCache(&prefs->lowPriorityNice,
"hal.processPriorityManager.gonk.LowCPUNice");
prefs->initialized = true;
}
void void
SetProcessPriority(int aPid, SetProcessPriority(int aPid,
ProcessPriority aPriority, ProcessPriority aPriority,
@ -1752,23 +1579,49 @@ SetProcessPriority(int aPid,
// SetProcessPriority being called early in startup. // SetProcessPriority being called early in startup.
EnsureKernelLowMemKillerParamsSet(); EnsureKernelLowMemKillerParamsSet();
PriorityClass* pc = GetPriorityClass(aPriority); static ProcessPriorityPrefs prefs = { 0 };
EnsureProcessPriorityPrefs(&prefs);
int oomScoreAdj = pc->OomScoreAdj(); int oomScoreAdj = prefs.priorities[aPriority].oomScoreAdj;
RoundOomScoreAdjUpWithBackroundLRU(oomScoreAdj, aBackgroundLRU); RoundOomScoreAdjUpWithBackroundLRU(oomScoreAdj, aBackgroundLRU);
// We try the newer interface first, and fall back to the older interface int clampedOomScoreAdj = clamped<int>(oomScoreAdj, OOM_SCORE_ADJ_MIN,
// on failure. OOM_SCORE_ADJ_MAX);
if (!WriteToFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(), if (clampedOomScoreAdj != oomScoreAdj) {
nsPrintfCString("%d", oomScoreAdj).get())) HAL_LOG("Clamping OOM adjustment for pid %d to %d", aPid,
{ clampedOomScoreAdj);
WriteToFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(), } else {
nsPrintfCString("%d", OomAdjOfOomScoreAdj(oomScoreAdj)).get()); HAL_LOG("Setting OOM adjustment for pid %d to %d", aPid,
clampedOomScoreAdj);
} }
HAL_LOG("Assigning pid %d to cgroup %s", aPid, pc->CGroup().get()); // We try the newer interface first, and fall back to the older interface
pc->AddProcess(aPid); // on failure.
if (!WriteToFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(),
nsPrintfCString("%d", clampedOomScoreAdj).get()))
{
int oomAdj = OomAdjOfOomScoreAdj(clampedOomScoreAdj);
WriteToFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(),
nsPrintfCString("%d", oomAdj).get());
}
int nice = 0;
if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
nice = prefs.priorities[aPriority].nice;
} else if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
nice = prefs.lowPriorityNice;
} else {
HAL_ERR("Unknown aCPUPriority value %d", aCPUPriority);
MOZ_ASSERT(false);
return;
}
HAL_LOG("Setting nice for pid %d to %d", aPid, nice);
SetNiceForPid(aPid, nice);
} }
static bool static bool

Просмотреть файл

@ -3,6 +3,7 @@
Cu.import("resource://services-common/async.js"); Cu.import("resource://services-common/async.js");
Cu.import("resource://testing-common/services/common/utils.js"); Cu.import("resource://testing-common/services/common/utils.js");
Cu.import("resource://testing-common/PlacesTestUtils.jsm");
let provider = { let provider = {
getFile: function(prop, persistent) { getFile: function(prop, persistent) {

Просмотреть файл

@ -1,7 +1,6 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */ * http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/PlacesUtils.jsm");
Cu.import("resource://services-sync/constants.js"); Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/engines/history.js"); Cu.import("resource://services-sync/engines/history.js");
Cu.import("resource://services-sync/engines.js"); Cu.import("resource://services-sync/engines.js");
@ -13,13 +12,16 @@ Cu.import("resource://testing-common/services/sync/utils.js");
Service.engineManager.clear(); Service.engineManager.clear();
add_test(function test_setup() {
PlacesTestUtils.clearHistory().then(run_next_test);
});
add_test(function test_processIncoming_mobile_history_batched() { add_test(function test_processIncoming_mobile_history_batched() {
_("SyncEngine._processIncoming works on history engine."); _("SyncEngine._processIncoming works on history engine.");
let FAKE_DOWNLOAD_LIMIT = 100; let FAKE_DOWNLOAD_LIMIT = 100;
Svc.Prefs.set("client.type", "mobile"); Svc.Prefs.set("client.type", "mobile");
PlacesUtils.history.removeAllPages();
Service.engineManager.register(HistoryEngine); Service.engineManager.register(HistoryEngine);
// A collection that logs each GET // A collection that logs each GET
@ -130,10 +132,11 @@ add_test(function test_processIncoming_mobile_history_batched() {
} }
} finally { } finally {
PlacesUtils.history.removeAllPages(); PlacesTestUtils.clearHistory().then(() => {
server.stop(do_test_finished); server.stop(do_test_finished);
Svc.Prefs.resetBranch(""); Svc.Prefs.resetBranch("");
Service.recordManager.clearCache(); Service.recordManager.clearCache();
});
} }
}); });

Просмотреть файл

@ -62,7 +62,7 @@ function ensureThrows(func) {
try { try {
func.apply(this, arguments); func.apply(this, arguments);
} catch (ex) { } catch (ex) {
PlacesUtils.history.removeAllPages(); PlacesTestUtils.clearHistory();
do_throw(ex); do_throw(ex);
} }
}; };
@ -300,6 +300,5 @@ add_test(function test_remove() {
add_test(function cleanup() { add_test(function cleanup() {
_("Clean up."); _("Clean up.");
PlacesUtils.history.removeAllPages(); PlacesTestUtils.clearHistory().then(run_next_test);
run_next_test();
}); });

Просмотреть файл

@ -199,6 +199,5 @@ add_test(function test_stop_tracking_twice() {
add_test(function cleanup() { add_test(function cleanup() {
_("Clean up."); _("Clean up.");
PlacesUtils.history.removeAllPages(); PlacesTestUtils.clearHistory().then(run_next_test);
run_next_test();
}); });

Просмотреть файл

@ -369,7 +369,7 @@ Other Measurements\n\
\n\ \n\
100.00 MB ── heap-allocated\n\ 100.00 MB ── heap-allocated\n\
\n\ \n\
End of 5th \ End of 5th\n\
"; ";
let amvExpectedText = let amvExpectedText =
@ -538,7 +538,7 @@ Other Measurements\n\
\n\ \n\
104,857,600 B ── heap-allocated\n\ 104,857,600 B ── heap-allocated\n\
\n\ \n\
End of 5th \ End of 5th\n\
"; ";
function finish() function finish()

Просмотреть файл

@ -912,14 +912,19 @@ public:
mozStorageTransaction transaction(mDBConn, false, mozStorageTransaction transaction(mDBConn, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE); mozIStorageConnection::TRANSACTION_IMMEDIATE);
VisitData* lastPlace = nullptr; VisitData* lastFetchedPlace = nullptr;
for (nsTArray<VisitData>::size_type i = 0; i < mPlaces.Length(); i++) { for (nsTArray<VisitData>::size_type i = 0; i < mPlaces.Length(); i++) {
VisitData& place = mPlaces.ElementAt(i); VisitData& place = mPlaces.ElementAt(i);
VisitData& referrer = mReferrers.ElementAt(i); VisitData& referrer = mReferrers.ElementAt(i);
// Fetching from the database can overwrite this information, so save it
// apart.
bool typed = place.typed;
bool hidden = place.hidden;
// We can avoid a database lookup if it's the same place as the last // We can avoid a database lookup if it's the same place as the last
// visit we added. // visit we added.
bool known = lastPlace && lastPlace->IsSamePlaceAs(place); bool known = lastFetchedPlace && lastFetchedPlace->IsSamePlaceAs(place);
if (!known) { if (!known) {
nsresult rv = mHistory->FetchPageInfo(place, &known); nsresult rv = mHistory->FetchPageInfo(place, &known);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@ -930,6 +935,17 @@ public:
} }
return NS_OK; return NS_OK;
} }
lastFetchedPlace = &mPlaces.ElementAt(i);
}
// If any transition is typed, ensure the page is marked as typed.
if (typed != lastFetchedPlace->typed) {
place.typed = true;
}
// If any transition is visible, ensure the page is marked as visible.
if (hidden != lastFetchedPlace->hidden) {
place.hidden = false;
} }
FetchReferrerInfo(referrer, place); FetchReferrerInfo(referrer, place);
@ -953,8 +969,6 @@ public:
rv = NS_DispatchToMainThread(event); rv = NS_DispatchToMainThread(event);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
lastPlace = &mPlaces.ElementAt(i);
} }
nsresult rv = transaction.Commit(); nsresult rv = transaction.Commit();
@ -2291,24 +2305,15 @@ History::FetchPageInfo(VisitData& _place, bool* _exists)
(_place.title.IsEmpty() && title.IsVoid())); (_place.title.IsEmpty() && title.IsVoid()));
} }
if (_place.hidden) { int32_t hidden;
// If this transition was hidden, it is possible that others were not. rv = stmt->GetInt32(3, &hidden);
// Any one visible transition makes this location visible. If database NS_ENSURE_SUCCESS(rv, rv);
// has location as visible, reflect that in our data structure. _place.hidden = !!hidden;
int32_t hidden;
rv = stmt->GetInt32(3, &hidden);
NS_ENSURE_SUCCESS(rv, rv);
_place.hidden = !!hidden;
}
if (!_place.typed) { int32_t typed;
// If this transition wasn't typed, others might have been. If database rv = stmt->GetInt32(4, &typed);
// has location as typed, reflect that in our data structure. NS_ENSURE_SUCCESS(rv, rv);
int32_t typed; _place.typed = !!typed;
rv = stmt->GetInt32(4, &typed);
NS_ENSURE_SUCCESS(rv, rv);
_place.typed = !!typed;
}
rv = stmt->GetInt32(5, &_place.frecency); rv = stmt->GetInt32(5, &_place.frecency);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -24,30 +24,28 @@ const RECENT_EVENT_THRESHOLD = 15 * 60 * 1000000;
* The time of the visit. Defaults to now if not provided. * The time of the visit. Defaults to now if not provided.
*/ */
function VisitInfo(aTransitionType, function VisitInfo(aTransitionType,
aVisitTime) aVisitTime) {
{
this.transitionType = this.transitionType =
aTransitionType === undefined ? TRANSITION_LINK : aTransitionType; aTransitionType === undefined ? TRANSITION_LINK : aTransitionType;
this.visitDate = aVisitTime || Date.now() * 1000; this.visitDate = aVisitTime || Date.now() * 1000;
} }
function promiseUpdatePlaces(aPlaces) { function promiseUpdatePlaces(aPlaces) {
let deferred = Promise.defer(); return new Promise((resolve, reject) => {
PlacesUtils.asyncHistory.updatePlaces(aPlaces, { PlacesUtils.asyncHistory.updatePlaces(aPlaces, {
_errors: [], _errors: [],
_results: [], _results: [],
handleError: function handleError(aResultCode, aPlace) { handleError(aResultCode, aPlace) {
this._errors.push({ resultCode: aResultCode, info: aPlace}); this._errors.push({ resultCode: aResultCode, info: aPlace});
}, },
handleResult: function handleResult(aPlace) { handleResult(aPlace) {
this._results.push(aPlace); this._results.push(aPlace);
}, },
handleCompletion: function handleCompletion() { handleCompletion() {
deferred.resolve({ errors: this._errors, results: this._results }); resolve({ errors: this._errors, results: this._results });
} }
});
}); });
return deferred.promise;
} }
/** /**
@ -63,18 +61,14 @@ function promiseUpdatePlaces(aPlaces) {
*/ */
function TitleChangedObserver(aURI, function TitleChangedObserver(aURI,
aExpectedTitle, aExpectedTitle,
aCallback) aCallback) {
{
this.uri = aURI; this.uri = aURI;
this.expectedTitle = aExpectedTitle; this.expectedTitle = aExpectedTitle;
this.callback = aCallback; this.callback = aCallback;
} }
TitleChangedObserver.prototype = { TitleChangedObserver.prototype = {
__proto__: NavHistoryObserver.prototype, __proto__: NavHistoryObserver.prototype,
onTitleChanged: function(aURI, onTitleChanged(aURI, aTitle, aGUID) {
aTitle,
aGUID)
{
do_log_info("onTitleChanged(" + aURI.spec + ", " + aTitle + ", " + aGUID + ")"); do_log_info("onTitleChanged(" + aURI.spec + ", " + aTitle + ", " + aGUID + ")");
if (!this.uri.equals(aURI)) { if (!this.uri.equals(aURI)) {
return; return;
@ -148,14 +142,12 @@ function do_check_title_for_uri(aURI,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//// Test Functions //// Test Functions
function test_interface_exists() add_task(function* test_interface_exists() {
{
let history = Cc["@mozilla.org/browser/history;1"].getService(Ci.nsISupports); let history = Cc["@mozilla.org/browser/history;1"].getService(Ci.nsISupports);
do_check_true(history instanceof Ci.mozIAsyncHistory); do_check_true(history instanceof Ci.mozIAsyncHistory);
} });
function test_invalid_uri_throws() add_task(function* test_invalid_uri_throws() {
{
// First, test passing in nothing. // First, test passing in nothing.
let place = { let place = {
visits: [ visits: [
@ -188,10 +180,9 @@ function test_invalid_uri_throws()
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG); do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
} }
} }
} });
function test_invalid_places_throws() add_task(function* test_invalid_places_throws() {
{
// First, test passing in nothing. // First, test passing in nothing.
try { try {
PlacesUtils.asyncHistory.updatePlaces(); PlacesUtils.asyncHistory.updatePlaces();
@ -219,10 +210,9 @@ function test_invalid_places_throws()
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG); do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
} }
} }
} });
function test_invalid_guid_throws() add_task(function* test_invalid_guid_throws() {
{
// First check invalid length guid. // First check invalid length guid.
let place = { let place = {
guid: "BAD_GUID", guid: "BAD_GUID",
@ -249,10 +239,9 @@ function test_invalid_guid_throws()
catch (e) { catch (e) {
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG); do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
} }
} });
function test_no_visits_throws() add_task(function* test_no_visits_throws() {
{
const TEST_URI = const TEST_URI =
NetUtil.newURI(TEST_DOMAIN + "test_no_id_or_guid_no_visits_throws"); NetUtil.newURI(TEST_DOMAIN + "test_no_id_or_guid_no_visits_throws");
const TEST_GUID = "_RANDOMGUID_"; const TEST_GUID = "_RANDOMGUID_";
@ -290,10 +279,9 @@ function test_no_visits_throws()
} }
} }
} }
} });
function test_add_visit_no_date_throws() add_task(function* test_add_visit_no_date_throws() {
{
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_date_throws"), uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_date_throws"),
visits: [ visits: [
@ -308,10 +296,9 @@ function test_add_visit_no_date_throws()
catch (e) { catch (e) {
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG); do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
} }
} });
function test_add_visit_no_transitionType_throws() add_task(function* test_add_visit_no_transitionType_throws() {
{
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_transitionType_throws"), uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_transitionType_throws"),
visits: [ visits: [
@ -326,10 +313,9 @@ function test_add_visit_no_transitionType_throws()
catch (e) { catch (e) {
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG); do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
} }
} });
function test_add_visit_invalid_transitionType_throws() add_task(function* test_add_visit_invalid_transitionType_throws() {
{
// First, test something that has a transition type lower than the first one. // First, test something that has a transition type lower than the first one.
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + uri: NetUtil.newURI(TEST_DOMAIN +
@ -355,10 +341,9 @@ function test_add_visit_invalid_transitionType_throws()
catch (e) { catch (e) {
do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG); do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
} }
} });
function test_non_addable_uri_errors() add_task(function* test_non_addable_uri_errors() {
{
// Array of protocols that nsINavHistoryService::canAddURI returns false for. // Array of protocols that nsINavHistoryService::canAddURI returns false for.
const URLS = [ const URLS = [
"about:config", "about:config",
@ -404,10 +389,9 @@ function test_non_addable_uri_errors()
do_check_false(yield promiseIsURIVisited(place.info.uri)); do_check_false(yield promiseIsURIVisited(place.info.uri));
} }
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_duplicate_guid_errors() add_task(function* test_duplicate_guid_errors() {
{
// This test ensures that trying to add a visit, with a guid already found in // This test ensures that trying to add a visit, with a guid already found in
// another visit, fails. // another visit, fails.
let place = { let place = {
@ -443,10 +427,9 @@ function test_duplicate_guid_errors()
do_check_false(yield promiseIsURIVisited(badPlaceInfo.info.uri)); do_check_false(yield promiseIsURIVisited(badPlaceInfo.info.uri));
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_invalid_referrerURI_ignored() add_task(function* test_invalid_referrerURI_ignored() {
{
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + uri: NetUtil.newURI(TEST_DOMAIN +
"test_invalid_referrerURI_ignored"), "test_invalid_referrerURI_ignored"),
@ -480,10 +463,9 @@ function test_invalid_referrerURI_ignored()
stmt.finalize(); stmt.finalize();
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_nonnsIURI_referrerURI_ignored() add_task(function* test_nonnsIURI_referrerURI_ignored() {
{
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + uri: NetUtil.newURI(TEST_DOMAIN +
"test_nonnsIURI_referrerURI_ignored"), "test_nonnsIURI_referrerURI_ignored"),
@ -513,10 +495,9 @@ function test_nonnsIURI_referrerURI_ignored()
stmt.finalize(); stmt.finalize();
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_old_referrer_ignored() add_task(function* test_old_referrer_ignored() {
{
// This tests that a referrer for a visit which is not recent (specifically, // This tests that a referrer for a visit which is not recent (specifically,
// older than 15 minutes as per RECENT_EVENT_THRESHOLD) is not saved by // older than 15 minutes as per RECENT_EVENT_THRESHOLD) is not saved by
// updatePlaces. // updatePlaces.
@ -573,10 +554,9 @@ function test_old_referrer_ignored()
stmt.finalize(); stmt.finalize();
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_place_id_ignored() add_task(function* test_place_id_ignored() {
{
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_place_id_ignored_first"), uri: NetUtil.newURI(TEST_DOMAIN + "test_place_id_ignored_first"),
visits: [ visits: [
@ -614,10 +594,9 @@ function test_place_id_ignored()
do_check_true(yield promiseIsURIVisited(badPlace.uri)); do_check_true(yield promiseIsURIVisited(badPlace.uri));
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_handleCompletion_called_when_complete() add_task(function* test_handleCompletion_called_when_complete() {
{
// We test a normal visit, and embeded visit, and a uri that would fail // We test a normal visit, and embeded visit, and a uri that would fail
// the canAddURI test to make sure that the notification happens after *all* // the canAddURI test to make sure that the notification happens after *all*
// of them have had a callback. // of them have had a callback.
@ -656,10 +635,9 @@ function test_handleCompletion_called_when_complete()
do_check_eq(callbackCountSuccess, EXPECTED_COUNT_SUCCESS); do_check_eq(callbackCountSuccess, EXPECTED_COUNT_SUCCESS);
do_check_eq(callbackCountFailure, EXPECTED_COUNT_FAILURE); do_check_eq(callbackCountFailure, EXPECTED_COUNT_FAILURE);
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_add_visit() add_task(function* test_add_visit() {
{
const VISIT_TIME = Date.now() * 1000; const VISIT_TIME = Date.now() * 1000;
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit"), uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit"),
@ -720,10 +698,9 @@ function test_add_visit()
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} }
} }
} });
function test_properties_saved() add_task(function* test_properties_saved() {
{
// Check each transition type to make sure it is saved properly. // Check each transition type to make sure it is saved properly.
let places = []; let places = [];
for (let transitionType = TRANSITION_LINK; for (let transitionType = TRANSITION_LINK;
@ -804,10 +781,9 @@ function test_properties_saved()
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} }
} }
} });
function test_guid_saved() add_task(function* test_guid_saved() {
{
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_guid_saved"), uri: NetUtil.newURI(TEST_DOMAIN + "test_guid_saved"),
guid: "__TESTGUID__", guid: "__TESTGUID__",
@ -828,10 +804,9 @@ function test_guid_saved()
do_check_eq(placeInfo.guid, place.guid); do_check_eq(placeInfo.guid, place.guid);
do_check_guid_for_uri(uri, place.guid); do_check_guid_for_uri(uri, place.guid);
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_referrer_saved() add_task(function* test_referrer_saved() {
{
let places = [ let places = [
{ uri: NetUtil.newURI(TEST_DOMAIN + "test_referrer_saved/referrer"), { uri: NetUtil.newURI(TEST_DOMAIN + "test_referrer_saved/referrer"),
visits: [ visits: [
@ -881,10 +856,9 @@ function test_referrer_saved()
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} }
} }
} });
function test_guid_change_saved() add_task(function* test_guid_change_saved() {
{
// First, add a visit for it. // First, add a visit for it.
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_guid_change_saved"), uri: NetUtil.newURI(TEST_DOMAIN + "test_guid_change_saved"),
@ -908,10 +882,9 @@ function test_guid_change_saved()
do_check_guid_for_uri(place.uri, place.guid); do_check_guid_for_uri(place.uri, place.guid);
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_title_change_saved() add_task(function* test_title_change_saved() {
{
// First, add a visit for it. // First, add a visit for it.
let place = { let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_title_change_saved"), uri: NetUtil.newURI(TEST_DOMAIN + "test_title_change_saved"),
@ -955,10 +928,9 @@ function test_title_change_saved()
do_check_title_for_uri(place.uri, place.title); do_check_title_for_uri(place.uri, place.title);
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_no_title_does_not_clear_title() add_task(function* test_no_title_does_not_clear_title() {
{
const TITLE = "test title"; const TITLE = "test title";
// First, add a visit for it. // First, add a visit for it.
let place = { let place = {
@ -984,10 +956,9 @@ function test_no_title_does_not_clear_title()
do_check_title_for_uri(place.uri, TITLE); do_check_title_for_uri(place.uri, TITLE);
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_title_change_notifies() add_task(function* test_title_change_notifies() {
{
// There are three cases to test. The first case is to make sure we do not // There are three cases to test. The first case is to make sure we do not
// get notified if we do not specify a title. // get notified if we do not specify a title.
let place = { let place = {
@ -1015,36 +986,35 @@ function test_title_change_notifies()
place.uri = NetUtil.newURI(place.uri.spec + "/new-visit-with-title"); place.uri = NetUtil.newURI(place.uri.spec + "/new-visit-with-title");
place.title = "title 1"; place.title = "title 1";
function promiseTitleChangedObserver(aPlace) { function promiseTitleChangedObserver(aPlace) {
let deferred = Promise.defer(); return new Promise((resolve, reject) => {
let callbackCount = 0; let callbackCount = 0;
let observer = new TitleChangedObserver(aPlace.uri, aPlace.title, function() { let observer = new TitleChangedObserver(aPlace.uri, aPlace.title, function() {
switch (++callbackCount) { switch (++callbackCount) {
case 1: case 1:
// The third case to test is to make sure we get a notification when // The third case to test is to make sure we get a notification when
// we change an existing place. // we change an existing place.
observer.expectedTitle = place.title = "title 2"; observer.expectedTitle = place.title = "title 2";
place.visits = [new VisitInfo()]; place.visits = [new VisitInfo()];
PlacesUtils.asyncHistory.updatePlaces(place); PlacesUtils.asyncHistory.updatePlaces(place);
break; break;
case 2: case 2:
PlacesUtils.history.removeObserver(silentObserver); PlacesUtils.history.removeObserver(silentObserver);
PlacesUtils.history.removeObserver(observer); PlacesUtils.history.removeObserver(observer);
deferred.resolve(); resolve();
break; break;
}; };
}); });
PlacesUtils.history.addObserver(observer, false); PlacesUtils.history.addObserver(observer, false);
PlacesUtils.asyncHistory.updatePlaces(aPlace); PlacesUtils.asyncHistory.updatePlaces(aPlace);
return deferred.promise; });
} }
yield promiseTitleChangedObserver(place); yield promiseTitleChangedObserver(place);
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
function test_visit_notifies() add_task(function* test_visit_notifies() {
{
// There are two observers we need to see for each visit. One is an // There are two observers we need to see for each visit. One is an
// nsINavHistoryObserver and the other is the uri-visit-saved observer topic. // nsINavHistoryObserver and the other is the uri-visit-saved observer topic.
let place = { let place = {
@ -1057,44 +1027,43 @@ function test_visit_notifies()
do_check_false(yield promiseIsURIVisited(place.uri)); do_check_false(yield promiseIsURIVisited(place.uri));
function promiseVisitObserver(aPlace) { function promiseVisitObserver(aPlace) {
let deferred = Promise.defer(); return new Promise((resolve, reject) => {
let callbackCount = 0; let callbackCount = 0;
let finisher = function() { let finisher = function() {
if (++callbackCount == 2) { if (++callbackCount == 2) {
deferred.resolve(); resolve();
}
} }
} let visitObserver = new VisitObserver(place.uri, place.guid,
let visitObserver = new VisitObserver(place.uri, place.guid, function(aVisitDate,
function(aVisitDate, aTransitionType) {
aTransitionType) { let visit = place.visits[0];
let visit = place.visits[0]; do_check_eq(visit.visitDate, aVisitDate);
do_check_eq(visit.visitDate, aVisitDate); do_check_eq(visit.transitionType, aTransitionType);
do_check_eq(visit.transitionType, aTransitionType);
PlacesUtils.history.removeObserver(visitObserver); PlacesUtils.history.removeObserver(visitObserver);
finisher(); finisher();
});
PlacesUtils.history.addObserver(visitObserver, false);
let observer = function(aSubject, aTopic, aData) {
do_log_info("observe(" + aSubject + ", " + aTopic + ", " + aData + ")");
do_check_true(aSubject instanceof Ci.nsIURI);
do_check_true(aSubject.equals(place.uri));
Services.obs.removeObserver(observer, URI_VISIT_SAVED);
finisher();
};
Services.obs.addObserver(observer, URI_VISIT_SAVED, false);
PlacesUtils.asyncHistory.updatePlaces(place);
}); });
PlacesUtils.history.addObserver(visitObserver, false);
let observer = function(aSubject, aTopic, aData) {
do_log_info("observe(" + aSubject + ", " + aTopic + ", " + aData + ")");
do_check_true(aSubject instanceof Ci.nsIURI);
do_check_true(aSubject.equals(place.uri));
Services.obs.removeObserver(observer, URI_VISIT_SAVED);
finisher();
};
Services.obs.addObserver(observer, URI_VISIT_SAVED, false);
PlacesUtils.asyncHistory.updatePlaces(place);
return deferred.promise;
} }
yield promiseVisitObserver(place); yield promiseVisitObserver(place);
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
// test with empty mozIVisitInfoCallback object // test with empty mozIVisitInfoCallback object
function test_callbacks_not_supplied() add_task(function* test_callbacks_not_supplied() {
{
const URLS = [ const URLS = [
"imap://cyrus.andrew.cmu.edu/archive.imap", // bad URI "imap://cyrus.andrew.cmu.edu/archive.imap", // bad URI
"http://mozilla.org/" // valid URI "http://mozilla.org/" // valid URI
@ -1121,40 +1090,36 @@ function test_callbacks_not_supplied()
PlacesUtils.asyncHistory.updatePlaces(places, {}); PlacesUtils.asyncHistory.updatePlaces(places, {});
yield promiseAsyncUpdates(); yield promiseAsyncUpdates();
} });
//////////////////////////////////////////////////////////////////////////////// // Test that we don't wrongly overwrite typed and hidden when adding new visits.
//// Test Runner add_task(function* test_typed_hidden_not_overwritten() {
yield PlacesTestUtils.clearHistory();
let places = [
{ uri: NetUtil.newURI("http://mozilla.org/"),
title: "test",
visits: [
new VisitInfo(TRANSITION_TYPED),
new VisitInfo(TRANSITION_LINK)
]
},
{ uri: NetUtil.newURI("http://mozilla.org/"),
title: "test",
visits: [
new VisitInfo(TRANSITION_FRAMED_LINK)
]
},
];
yield promiseUpdatePlaces(places);
[ let db = yield PlacesUtils.promiseDBConnection();
test_interface_exists, let rows = yield db.execute("SELECT hidden, typed FROM moz_places WHERE url = :url",
test_invalid_uri_throws, { url: "http://mozilla.org/" });
test_invalid_places_throws, Assert.equal(rows[0].getResultByName("typed"), 1,
test_invalid_guid_throws, "The page should be marked as typed");
test_no_visits_throws, Assert.equal(rows[0].getResultByName("hidden"), 0,
test_add_visit_no_date_throws, "The page should be marked as not hidden");
test_add_visit_no_transitionType_throws, });
test_add_visit_invalid_transitionType_throws,
// Note: all asynchronous tests (every test below this point) should wait for
// async updates before calling run_next_test.
test_non_addable_uri_errors,
test_duplicate_guid_errors,
test_invalid_referrerURI_ignored,
test_nonnsIURI_referrerURI_ignored,
test_old_referrer_ignored,
test_place_id_ignored,
test_handleCompletion_called_when_complete,
test_add_visit,
test_properties_saved,
test_guid_saved,
test_referrer_saved,
test_guid_change_saved,
test_title_change_saved,
test_no_title_does_not_clear_title,
test_title_change_notifies,
test_visit_notifies,
test_callbacks_not_supplied,
].forEach(add_task);
function run_test() function run_test()
{ {

Просмотреть файл

@ -605,4 +605,11 @@
<children includes="menupopup"/> <children includes="menupopup"/>
</content> </content>
</binding> </binding>
<binding id="menulist-popuponly" display="xul:menu"
extends="chrome://global/content/bindings/menulist.xml#menulist">
<content>
<children includes="menupopup"/>
</content>
</binding>
</bindings> </bindings>

Просмотреть файл

@ -248,7 +248,7 @@
this.messageManager.addMessageListener("DOMFullscreen:RequestRollback", this); this.messageManager.addMessageListener("DOMFullscreen:RequestRollback", this);
this.messageManager.loadFrameScript("chrome://global/content/browser-child.js", true); this.messageManager.loadFrameScript("chrome://global/content/browser-child.js", true);
if (this.hasAttribute("selectpopup")) { if (this.hasAttribute("selectmenulist")) {
this.messageManager.addMessageListener("Forms:ShowDropDown", this); this.messageManager.addMessageListener("Forms:ShowDropDown", this);
this.messageManager.addMessageListener("Forms:HideDropDown", this); this.messageManager.addMessageListener("Forms:HideDropDown", this);
this.messageManager.loadFrameScript("chrome://global/content/select-child.js", true); this.messageManager.loadFrameScript("chrome://global/content/select-child.js", true);
@ -310,9 +310,9 @@
case "Forms:ShowDropDown": { case "Forms:ShowDropDown": {
Cu.import("resource://gre/modules/SelectParentHelper.jsm"); Cu.import("resource://gre/modules/SelectParentHelper.jsm");
let dropdown = document.getElementById(this.getAttribute("selectpopup")); let menulist = document.getElementById(this.getAttribute("selectmenulist"));
SelectParentHelper.populate(dropdown, data.options, data.selectedIndex); SelectParentHelper.populate(menulist, data.options, data.selectedIndex);
SelectParentHelper.open(this, dropdown, data.rect); SelectParentHelper.open(this, menulist, data.rect);
break; break;
} }
@ -345,8 +345,8 @@
case "Forms:HideDropDown": { case "Forms:HideDropDown": {
Cu.import("resource://gre/modules/SelectParentHelper.jsm"); Cu.import("resource://gre/modules/SelectParentHelper.jsm");
let dropdown = document.getElementById(this.getAttribute("selectpopup")); let menulist = document.getElementById(this.getAttribute("selectmenulist"));
SelectParentHelper.hide(dropdown); SelectParentHelper.hide(menulist);
break; break;
} }

Просмотреть файл

@ -930,6 +930,14 @@ menulist {
-moz-binding: url("chrome://global/content/bindings/menulist.xml#menulist"); -moz-binding: url("chrome://global/content/bindings/menulist.xml#menulist");
} }
menulist[popuponly="true"] {
-moz-binding: url("chrome://global/content/bindings/menulist.xml#menulist-popuponly");
-moz-appearance: none !important;
margin: 0 !important;
height: 0 !important;
border: 0 !important;
}
menulist[editable="true"] { menulist[editable="true"] {
-moz-binding: url("chrome://global/content/bindings/menulist.xml#menulist-editable"); -moz-binding: url("chrome://global/content/bindings/menulist.xml#menulist-editable");
} }

Просмотреть файл

@ -1263,7 +1263,7 @@ BoxModelHighlighter.prototype = Heritage.extend(AutoRefreshHighlighter.prototype
} }
let rect = this.currentQuads.border.bounds; let rect = this.currentQuads.border.bounds;
let dim = Math.ceil(rect.width) + " x " + Math.ceil(rect.height); let dim = Math.ceil(rect.width) + " \u00D7 " + Math.ceil(rect.height);
let elementId = this.ID_CLASS_PREFIX + "nodeinfobar-"; let elementId = this.ID_CLASS_PREFIX + "nodeinfobar-";
this.markup.setTextContentForElement(elementId + "tagname", tagName); this.markup.setTextContentForElement(elementId + "tagname", tagName);

Просмотреть файл

@ -136,7 +136,7 @@ let MemoryActor = protocol.ActorClass({
if (this.state == "attached") { if (this.state == "attached") {
if (isTopLevel && this.dbg.memory.trackingAllocationSites) { if (isTopLevel && this.dbg.memory.trackingAllocationSites) {
this._clearDebuggees(); this._clearDebuggees();
nthis._frameCache.initFrames(); this._frameCache.initFrames();
} }
this.dbg.addDebuggees(); this.dbg.addDebuggees();
} }

Просмотреть файл

@ -500,6 +500,7 @@ let NetworkHelper = {
* - state: The security of the connection used to fetch this * - state: The security of the connection used to fetch this
* request. Has one of following string values: * request. Has one of following string values:
* * "insecure": the connection was not secure (only http) * * "insecure": the connection was not secure (only http)
* * "weak": the connection has minor security issues
* * "broken": secure connection failed (e.g. expired cert) * * "broken": secure connection failed (e.g. expired cert)
* * "secure": the connection was properly secured. * * "secure": the connection was properly secured.
* If state == broken: * If state == broken:
@ -511,6 +512,9 @@ let NetworkHelper = {
* See parseCertificateInfo for the contents. * See parseCertificateInfo for the contents.
* - hsts: true if host uses Strict Transport Security, false otherwise * - hsts: true if host uses Strict Transport Security, false otherwise
* - hpkp: true if host uses Public Key Pinning, false otherwise * - hpkp: true if host uses Public Key Pinning, false otherwise
* If state == weak: Same as state == secure and
* - weaknessReasons: list of reasons that cause the request to be
* considered weak. See getReasonsForWeakness.
*/ */
parseSecurityInfo: function NH_parseSecurityInfo(securityInfo, httpActivity) { parseSecurityInfo: function NH_parseSecurityInfo(securityInfo, httpActivity) {
const info = { const info = {
@ -551,7 +555,7 @@ let NetworkHelper = {
* => .securityState has STATE_IS_BROKEN flag * => .securityState has STATE_IS_BROKEN flag
* => .errorCode is NOT an NSS error code * => .errorCode is NOT an NSS error code
* => .errorMessage is not available * => .errorMessage is not available
* => state === "insecure" * => state === "weak"
*/ */
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo); securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
@ -561,10 +565,26 @@ let NetworkHelper = {
const NSSErrorsService = Cc['@mozilla.org/nss_errors_service;1'] const NSSErrorsService = Cc['@mozilla.org/nss_errors_service;1']
.getService(Ci.nsINSSErrorsService); .getService(Ci.nsINSSErrorsService);
const SSLStatus = securityInfo.SSLStatus; const SSLStatus = securityInfo.SSLStatus;
if (!NSSErrorsService.isNSSErrorCode(securityInfo.errorCode)) {
const state = securityInfo.securityState;
if (securityInfo.securityState & wpl.STATE_IS_SECURE) { if (state & wpl.STATE_IS_SECURE) {
// The connection is secure. // The connection is secure.
info.state = "secure"; info.state = "secure";
} else if (state & wpl.STATE_IS_BROKEN) {
// The connection is not secure, there was no error but there's some
// minor security issues.
info.state = "weak";
info.weaknessReasons = this.getReasonsForWeakness(state);
} else if (state & wpl.STATE_IS_INSECURE) {
// This was most likely an https request that was aborted before
// validation. Return info as info.state = insecure.
return info;
} else {
DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
"Security state " + state + " has no known STATE_IS_* flags.");
return info;
}
// Cipher suite. // Cipher suite.
info.cipherSuite = SSLStatus.cipherName; info.cipherSuite = SSLStatus.cipherName;
@ -598,14 +618,10 @@ let NetworkHelper = {
info.hpkp = false; info.hpkp = false;
} }
} else if (NSSErrorsService.isNSSErrorCode(securityInfo.errorCode)) { } else {
// The connection failed. // The connection failed.
info.state = "broken"; info.state = "broken";
info.errorMessage = securityInfo.errorMessage; info.errorMessage = securityInfo.errorMessage;
} else {
// Connection has securityInfo, it is not secure and there's no problems
// to report. Mark the request as insecure.
return info;
} }
return info; return info;
@ -683,6 +699,46 @@ let NetworkHelper = {
return "Unknown"; return "Unknown";
} }
}, },
/**
* Takes the securityState bitfield and returns reasons for weak connection
* as an array of strings.
*
* @param Number state
* nsITransportSecurityInfo.securityState.
*
* @return Array[String]
* List of weakness reasons. A subset of { cipher, sslv3 } where
* * cipher: The cipher suite is consireded to be weak (RC4).
* * sslv3: The protocol, SSLv3, is weak.
*/
getReasonsForWeakness: function NH_getReasonsForWeakness(state) {
const wpl = Ci.nsIWebProgressListener;
// If there's non-fatal security issues the request has STATE_IS_BROKEN
// flag set. See http://hg.mozilla.org/mozilla-central/file/44344099d119
// /security/manager/ssl/src/nsNSSCallbacks.cpp#l1233
let reasons = [];
if (state & wpl.STATE_IS_BROKEN) {
let isSSLV3 = state & wpl.STATE_USES_SSL_3;
let isCipher = state & wpl.STATE_USES_WEAK_CRYPTO;
if (isSSLV3) {
reasons.push("sslv3");
}
if (isCipher) {
reasons.push("cipher");
}
if (!isCipher && !isSSLV3) {
DevToolsUtils.reportException("NetworkHelper.getReasonsForWeakness",
"STATE_IS_BROKEN without a known reason. Full state was: " + state);
}
}
return reasons;
},
}; };
for (let prop of Object.getOwnPropertyNames(NetworkHelper)) { for (let prop of Object.getOwnPropertyNames(NetworkHelper)) {

Просмотреть файл

@ -89,12 +89,12 @@ function test_secureSecurityInfo() {
} }
/** /**
* Test that STATE_IS_BROKEN returns "insecure" * Test that STATE_IS_BROKEN returns "weak"
*/ */
function test_brokenSecurityInfo() { function test_brokenSecurityInfo() {
MockSecurityInfo.securityState = wpl.STATE_IS_BROKEN; MockSecurityInfo.securityState = wpl.STATE_IS_BROKEN;
let result = NetworkHelper.parseSecurityInfo(MockSecurityInfo, {}); let result = NetworkHelper.parseSecurityInfo(MockSecurityInfo, {});
equal(result.state, "insecure", equal(result.state, "weak",
"state == 'insecure' if securityState contains STATE_IS_BROKEN flag"); "state == 'weak' if securityState contains STATE_IS_BROKEN flag");
} }

Просмотреть файл

@ -0,0 +1,55 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Tests that NetworkHelper.getReasonsForWeakness returns correct reasons for
// weak requests.
const { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
Object.defineProperty(this, "NetworkHelper", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/network-helper");
},
configurable: true,
writeable: false,
enumerable: true
});
const Ci = Components.interfaces;
const wpl = Ci.nsIWebProgressListener;
const TEST_CASES = [
{
description: "weak cipher",
input: wpl.STATE_IS_BROKEN | wpl.STATE_USES_WEAK_CRYPTO,
expected: ["cipher"]
}, {
description: "weak sslv3 protocol",
input: wpl.STATE_IS_BROKEN | wpl.STATE_USES_SSL_3,
expected: ["sslv3"]
}, {
description: "weak cipher + sslv3",
input: wpl.STATE_IS_BROKEN | wpl.STATE_USES_WEAK_CRYPTO | wpl.STATE_USES_SSL_3,
expected: ["sslv3", "cipher"] // order matters for deepEqual
}, {
description: "only STATE_IS_BROKEN flag",
input: wpl.STATE_IS_BROKEN,
expected: []
}, {
description: "only STATE_IS_SECURE flag",
input: wpl.STATE_IS_SECURE,
expected: []
},
];
function run_test() {
do_print("Testing NetworkHelper.getReasonsForWeakness.");
for (let {description, input, expected} of TEST_CASES) {
do_print("Testing " + description);
deepEqual(NetworkHelper.getReasonsForWeakness(input), expected,
"Got the expected reasons for weakness.");
}
}

Просмотреть файл

@ -11,3 +11,4 @@ support-files =
[test_security-info-protocol-version.js] [test_security-info-protocol-version.js]
[test_security-info-state.js] [test_security-info-state.js]
[test_security-info-static-hpkp.js] [test_security-info-static-hpkp.js]
[test_security-info-weakness-reasons.js]

Просмотреть файл

@ -11,27 +11,35 @@ this.EXPORTED_SYMBOLS = [
let currentBrowser = null; let currentBrowser = null;
this.SelectParentHelper = { this.SelectParentHelper = {
populate: function(popup, items, selectedIndex) { populate: function(menulist, items, selectedIndex) {
// Clear the current contents of the popup // Clear the current contents of the popup
popup.textContent = ""; menulist.menupopup.textContent = "";
populateChildren(popup, items, selectedIndex); populateChildren(menulist.menupopup, items, selectedIndex);
// We expect the parent element of the popup to be a <xul:menulist> that
// has the popuponly attribute set to "true". This is necessary in order
// for a <xul:menupopup> to act like a proper <html:select> dropdown, as
// the <xul:menulist> does things like remember state and set the
// _moz-menuactive attribute on the selected <xul:menuitem>.
menulist.selectedIndex = selectedIndex;
}, },
open: function(browser, popup, rect) { open: function(browser, menulist, rect) {
menulist.hidden = false;
currentBrowser = browser; currentBrowser = browser;
this._registerListeners(popup); this._registerListeners(menulist.menupopup);
popup.hidden = false;
let {x, y} = browser.mapScreenCoordinatesFromContent(rect.left, rect.top + rect.height); let {x, y} = browser.mapScreenCoordinatesFromContent(rect.left, rect.top + rect.height);
popup.openPopupAtScreen(x, y); menulist.menupopup.openPopupAtScreen(x, y);
menulist.selectedItem.scrollIntoView();
}, },
hide: function(popup) { hide: function(menulist) {
popup.hidePopup(); menulist.menupopup.hidePopup();
}, },
handleEvent: function(event) { handleEvent: function(event) {
let popup = event.currentTarget; let popup = event.currentTarget;
let menulist = popup.parentNode;
switch (event.type) { switch (event.type) {
case "command": case "command":
@ -47,6 +55,7 @@ this.SelectParentHelper = {
currentBrowser.messageManager.sendAsyncMessage("Forms:DismissedDropDown", {}); currentBrowser.messageManager.sendAsyncMessage("Forms:DismissedDropDown", {});
currentBrowser = null; currentBrowser = null;
this._unregisterListeners(popup); this._unregisterListeners(popup);
menulist.hidden = true;
break; break;
} }
}, },
@ -69,11 +78,6 @@ function populateChildren(element, options, selectedIndex, startIndex = 0, isGro
for (let option of options) { for (let option of options) {
let item = element.ownerDocument.createElement("menuitem"); let item = element.ownerDocument.createElement("menuitem");
item.setAttribute("label", option.textContent); item.setAttribute("label", option.textContent);
item.setAttribute("type", "radio");
if (index == selectedIndex) {
item.setAttribute("checked", "true");
}
element.appendChild(item); element.appendChild(item);

Просмотреть файл

@ -8,11 +8,14 @@
menulist { menulist {
-moz-appearance: menulist; -moz-appearance: menulist;
margin: 5px 2px 3px; margin: 5px 2px 3px;
min-height: 20px !important;
color: -moz-DialogText; color: -moz-DialogText;
text-shadow: none; text-shadow: none;
} }
menulist:not([popuponly="true"]) {
min-height: 20px !important;
}
.menulist-label-box { .menulist-label-box {
-moz-appearance: menulist-text; -moz-appearance: menulist-text;
-moz-box-align: center; -moz-box-align: center;