This commit is contained in:
Wes Kocher 2015-01-27 15:47:50 -08:00
Родитель 915c7c01d6 9148720ef2
Коммит a7ffe505ae
45 изменённых файлов: 1478 добавлений и 1627 удалений

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

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

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

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

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

@ -146,8 +146,13 @@
<!-- for url bar autocomplete -->
<panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
<!-- for select dropdowns -->
<menupopup id="ContentSelectDropdown" rolluponmousewheel="true" hidden="true"/>
<!-- for select dropdowns. The menupopup is what shows the list of options,
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 -->
<panel id="invalid-form-popup" type="arrow" orient="vertical" noautofocus="true" hidden="true" level="parent">
@ -1169,7 +1174,7 @@
tabcontainer="tabbrowser-tabs"
contentcontextmenu="contentAreaContextMenu"
autocompletepopup="PopupAutoComplete"
selectpopup="ContentSelectDropdown"/>
selectmenulist="ContentSelectDropdown"/>
<chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
</vbox>
<splitter id="social-sidebar-splitter"

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

@ -30,7 +30,7 @@
<xul:vbox flex="1" class="browserContainer">
<xul:stack flex="1" class="browserStack" anonid="browserStack">
<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:vbox>
</xul:hbox>
@ -1600,8 +1600,8 @@
if (!isPreloadBrowser && this.hasAttribute("autocompletepopup"))
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
if (this.hasAttribute("selectpopup"))
b.setAttribute("selectpopup", this.getAttribute("selectpopup"));
if (this.hasAttribute("selectmenulist"))
b.setAttribute("selectmenulist", this.getAttribute("selectmenulist"));
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);

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

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

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

@ -118,216 +118,88 @@
/* Modal dialog styles */
.OT_dialog-centering {
display: table;
width: 100%;
height: 100%;
}
.OT_dialog-centering-child {
display: table-cell;
vertical-align: middle;
}
.OT_dialog {
border: none;
border-radius: 0;
top: 50%;
left: 50%;
position: absolute;
position: fixed;
padding: 0;
position: relative;
box-sizing: border-box;
max-width: 576px;
margin-right: auto;
margin-left: auto;
padding: 36px;
text-align: center; /* centers all the inline content */
background-color: #363636;
color: #fff;
z-index: 9999;
box-shadow: 2px 4px 6px #999;
font-family: 'Didact Gothic', sans-serif;
}
.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;
font-size: 13px;
line-height: 1.4;
}
.OT_dialog * {
font-family: 'Didact Gothic', sans-serif;
}
.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);
font-family: inherit;
box-sizing: inherit;
}
.OT_closeButton {
color: #999999;
cursor: pointer;
font-size: 32px;
line-height: 30px;
line-height: 36px;
position: absolute;
right: 15px;
right: 18px;
top: 0;
}
.OT_dialog-messages {
position: absolute;
top: 32px;
left: 32px;
right: 32px;
text-align: center;
}
.OT_dialog-allow-deny-firefox-maybe-denied .OT_dialog-messages {
top: 45px;
}
.OT_dialog-messages-main {
margin-bottom: 36px;
line-height: 36px;
font-weight: 300;
font-size: 18pt;
line-height: 24px;
font-size: 24px;
}
.OT_dialog-messages-minor {
font-weight: 300;
margin-top: 12px;
margin-bottom: 18px;
font-size: 13px;
line-height: 18px;
color: #A4A4A4;
}
.OT_dialog-allow-deny-firefox-maybe-denied .OT_dialog-messages-minor {
margin-top: 4px;
}
.OT_dialog-messages-minor strong {
font-weight: 300;
color: #ffffff;
}
.OT_dialog-hidden {
display: none;
}
.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-actions-card {
display: inline-block;
}
.OT_dialog-button-title {
margin-bottom: 18px;
line-height: 18px;
font-weight: 300;
text-align: center;
margin-bottom: 15px;
font-size: 14px;
line-height: 150%;
color: #999999;
}
.OT_dialog-button-title label {
color: #999999;
}
@ -345,13 +217,13 @@
}
.OT_dialog-button {
font-weight: 100;
display: block;
line-height: 50px;
height: 47px;
display: inline-block;
margin-bottom: 18px;
padding: 0 1em;
background-color: #1CA3DC;
text-align: center;
font-size: 16pt;
cursor: pointer;
}
@ -364,138 +236,67 @@
opacity: 0.5;
}
.OT_dialog-button.OT_dialog-button-large {
line-height: 60px;
height: 58px;
.OT_dialog-button-large {
line-height: 36px;
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;
color: #999999;
font-size: 12pt;
height: 40px;
line-height: 40px;
margin: 20px auto 0 auto;
width: 86px;
font-size: 16px;
}
.OT_dialog-progress-bar {
display: inline-block; /* prevents margin collapse */
width: 100%;
margin-top: 5px;
margin-bottom: 41px;
border: 1px solid #4E4E4E;
height: 8px;
}
.OT_dialog-progress-bar-fill {
height: 100%;
background-color: #29A4DA;
height: 10px;
margin-top: -1px;
margin-left: -1px;
margin-right: -1px;
}
.OT_dialog-plugin-upgrading .OT_dialog-plugin-upgrade-percentage {
font-size: 36pt;
line-height: 54px;
font-size: 48px;
font-weight: 100;
}
.OT_dialog-plugin-upgrading .OT_dialog-progress-bar {
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;
}
/* Helpers */
.OT_centered {
position: fixed;
left: 50%;
top: 50%;
margin: 0;
position: fixed;
left: 50%;
top: 50%;
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 */
@ -803,21 +604,14 @@
.OT_publisher .OT_name,
.OT_subscriber .OT_name {
left: 24px;
left: 10px;
right: 37px;
height: 34px;
}
.OT_publisher .OT_name-no-bug,
.OT_subscriber .OT_name-no-bug {
left: 10px;
padding-left: 0;
}
.OT_publisher .OT_mute,
.OT_subscriber .OT_mute,
.OT_publisher .OT_opentok,
.OT_subscriber .OT_opentok {
.OT_subscriber .OT_mute {
border: none;
cursor: pointer;
display: block;
@ -828,21 +622,6 @@
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_subscriber .OT_mute {
right: 0;
@ -883,21 +662,6 @@
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
*
@ -975,23 +739,6 @@
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 */
.OT_video-container {
position: absolute;
@ -1095,7 +842,7 @@
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;
}

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

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

@ -701,7 +701,7 @@ let CallsListView = Heritage.extend(WidgetMethods, {
let dimensionsNode = $("#screenshot-dimensions");
let actualWidth = (width / 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);
},

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

@ -20,7 +20,7 @@ function ifTestingSupported() {
is($("#screenshot-container").hidden, false,
"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.");
is($("#screenshot-image").getAttribute("flipped"), "false",

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

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

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

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

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

@ -45,7 +45,7 @@ function*(inspector, view) {
info("Checking that the layout-view shows the right value");
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");
let onUpdated = waitForUpdate(inspector);
@ -54,7 +54,7 @@ function*(inspector, view) {
ok(true, "Layout-view got updated");
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",

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

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

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

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

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

@ -1683,7 +1683,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
*/
_onSecurityIconClick: function(e) {
let state = this.selectedItem.attachment.securityState;
if (state === "broken" || state === "secure") {
if (state !== "insecure") {
// Choose the security tab.
NetMonitorView.NetworkDetails.widget.selectedIndex = 5;
}
@ -2605,7 +2605,7 @@ NetworkDetailsView.prototype = {
// in width and height attributes like the rest of the folk. Hack around
// this by getting the bounding client rect and subtracting the margins.
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);
};
}
@ -2765,10 +2765,22 @@ NetworkDetailsView.prototype = {
let errorbox = $("#security-error");
let infobox = $("#security-information");
if (securityInfo.state === "secure") {
if (securityInfo.state === "secure" || securityInfo.state === "weak") {
infobox.hidden = false;
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 disabledLabel = L10N.getStr("netmonitor.security.disabled");

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

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

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

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

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

@ -208,7 +208,7 @@ function test() {
.getAttribute("value"), "base64",
"The image encoding info isn't correct.");
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.");
deferred.resolve();

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

@ -13,6 +13,7 @@ add_task(function* () {
"test1.example.com": "security-state-insecure",
"example.com": "security-state-secure",
"nocert.example.com": "security-state-broken",
"rc4.example.com": "security-state-weak",
};
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);
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.
*/
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)
if (this.menulist.inputField) {

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

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

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

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

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

@ -726,7 +726,7 @@ Tooltip.prototype = {
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

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

@ -202,6 +202,14 @@
- in a "receive" state. -->
<!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
- in the security tab if a security error prevented the connection. -->
<!ENTITY netmonitorUI.security.error "An error occured:">

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

@ -44,6 +44,10 @@ netmonitor.security.state.insecure=The connection used to fetch this resource wa
# issues.
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):
# This string is used to indicate that a specific security feature is used by
# a connection in the security details tab.

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

@ -178,6 +178,11 @@
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 {
cursor: pointer;
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;
}
.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-pane {

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

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

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

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

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

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

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

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

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

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

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

@ -912,14 +912,19 @@ public:
mozStorageTransaction transaction(mDBConn, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
VisitData* lastPlace = nullptr;
VisitData* lastFetchedPlace = nullptr;
for (nsTArray<VisitData>::size_type i = 0; i < mPlaces.Length(); i++) {
VisitData& place = mPlaces.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
// visit we added.
bool known = lastPlace && lastPlace->IsSamePlaceAs(place);
bool known = lastFetchedPlace && lastFetchedPlace->IsSamePlaceAs(place);
if (!known) {
nsresult rv = mHistory->FetchPageInfo(place, &known);
if (NS_FAILED(rv)) {
@ -930,6 +935,17 @@ public:
}
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);
@ -953,8 +969,6 @@ public:
rv = NS_DispatchToMainThread(event);
NS_ENSURE_SUCCESS(rv, rv);
}
lastPlace = &mPlaces.ElementAt(i);
}
nsresult rv = transaction.Commit();
@ -2291,24 +2305,15 @@ History::FetchPageInfo(VisitData& _place, bool* _exists)
(_place.title.IsEmpty() && title.IsVoid()));
}
if (_place.hidden) {
// If this transition was hidden, it is possible that others were not.
// Any one visible transition makes this location visible. If database
// has location as visible, reflect that in our data structure.
int32_t hidden;
rv = stmt->GetInt32(3, &hidden);
NS_ENSURE_SUCCESS(rv, rv);
_place.hidden = !!hidden;
}
int32_t hidden;
rv = stmt->GetInt32(3, &hidden);
NS_ENSURE_SUCCESS(rv, rv);
_place.hidden = !!hidden;
if (!_place.typed) {
// If this transition wasn't typed, others might have been. If database
// has location as typed, reflect that in our data structure.
int32_t typed;
rv = stmt->GetInt32(4, &typed);
NS_ENSURE_SUCCESS(rv, rv);
_place.typed = !!typed;
}
int32_t typed;
rv = stmt->GetInt32(4, &typed);
NS_ENSURE_SUCCESS(rv, rv);
_place.typed = !!typed;
rv = stmt->GetInt32(5, &_place.frecency);
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.
*/
function VisitInfo(aTransitionType,
aVisitTime)
{
aVisitTime) {
this.transitionType =
aTransitionType === undefined ? TRANSITION_LINK : aTransitionType;
this.visitDate = aVisitTime || Date.now() * 1000;
}
function promiseUpdatePlaces(aPlaces) {
let deferred = Promise.defer();
PlacesUtils.asyncHistory.updatePlaces(aPlaces, {
_errors: [],
_results: [],
handleError: function handleError(aResultCode, aPlace) {
this._errors.push({ resultCode: aResultCode, info: aPlace});
},
handleResult: function handleResult(aPlace) {
this._results.push(aPlace);
},
handleCompletion: function handleCompletion() {
deferred.resolve({ errors: this._errors, results: this._results });
}
return new Promise((resolve, reject) => {
PlacesUtils.asyncHistory.updatePlaces(aPlaces, {
_errors: [],
_results: [],
handleError(aResultCode, aPlace) {
this._errors.push({ resultCode: aResultCode, info: aPlace});
},
handleResult(aPlace) {
this._results.push(aPlace);
},
handleCompletion() {
resolve({ errors: this._errors, results: this._results });
}
});
});
return deferred.promise;
}
/**
@ -63,18 +61,14 @@ function promiseUpdatePlaces(aPlaces) {
*/
function TitleChangedObserver(aURI,
aExpectedTitle,
aCallback)
{
aCallback) {
this.uri = aURI;
this.expectedTitle = aExpectedTitle;
this.callback = aCallback;
}
TitleChangedObserver.prototype = {
__proto__: NavHistoryObserver.prototype,
onTitleChanged: function(aURI,
aTitle,
aGUID)
{
onTitleChanged(aURI, aTitle, aGUID) {
do_log_info("onTitleChanged(" + aURI.spec + ", " + aTitle + ", " + aGUID + ")");
if (!this.uri.equals(aURI)) {
return;
@ -148,14 +142,12 @@ function do_check_title_for_uri(aURI,
////////////////////////////////////////////////////////////////////////////////
//// Test Functions
function test_interface_exists()
{
add_task(function* test_interface_exists() {
let history = Cc["@mozilla.org/browser/history;1"].getService(Ci.nsISupports);
do_check_true(history instanceof Ci.mozIAsyncHistory);
}
});
function test_invalid_uri_throws()
{
add_task(function* test_invalid_uri_throws() {
// First, test passing in nothing.
let place = {
visits: [
@ -188,10 +180,9 @@ function test_invalid_uri_throws()
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.
try {
PlacesUtils.asyncHistory.updatePlaces();
@ -219,10 +210,9 @@ function test_invalid_places_throws()
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.
let place = {
guid: "BAD_GUID",
@ -249,10 +239,9 @@ function test_invalid_guid_throws()
catch (e) {
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 =
NetUtil.newURI(TEST_DOMAIN + "test_no_id_or_guid_no_visits_throws");
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 = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_date_throws"),
visits: [
@ -308,10 +296,9 @@ function test_add_visit_no_date_throws()
catch (e) {
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 = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit_no_transitionType_throws"),
visits: [
@ -326,10 +313,9 @@ function test_add_visit_no_transitionType_throws()
catch (e) {
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.
let place = {
uri: NetUtil.newURI(TEST_DOMAIN +
@ -355,10 +341,9 @@ function test_add_visit_invalid_transitionType_throws()
catch (e) {
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.
const URLS = [
"about:config",
@ -404,10 +389,9 @@ function test_non_addable_uri_errors()
do_check_false(yield promiseIsURIVisited(place.info.uri));
}
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
// another visit, fails.
let place = {
@ -443,10 +427,9 @@ function test_duplicate_guid_errors()
do_check_false(yield promiseIsURIVisited(badPlaceInfo.info.uri));
yield promiseAsyncUpdates();
}
});
function test_invalid_referrerURI_ignored()
{
add_task(function* test_invalid_referrerURI_ignored() {
let place = {
uri: NetUtil.newURI(TEST_DOMAIN +
"test_invalid_referrerURI_ignored"),
@ -480,10 +463,9 @@ function test_invalid_referrerURI_ignored()
stmt.finalize();
yield promiseAsyncUpdates();
}
});
function test_nonnsIURI_referrerURI_ignored()
{
add_task(function* test_nonnsIURI_referrerURI_ignored() {
let place = {
uri: NetUtil.newURI(TEST_DOMAIN +
"test_nonnsIURI_referrerURI_ignored"),
@ -513,10 +495,9 @@ function test_nonnsIURI_referrerURI_ignored()
stmt.finalize();
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,
// older than 15 minutes as per RECENT_EVENT_THRESHOLD) is not saved by
// updatePlaces.
@ -573,10 +554,9 @@ function test_old_referrer_ignored()
stmt.finalize();
yield promiseAsyncUpdates();
}
});
function test_place_id_ignored()
{
add_task(function* test_place_id_ignored() {
let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_place_id_ignored_first"),
visits: [
@ -614,10 +594,9 @@ function test_place_id_ignored()
do_check_true(yield promiseIsURIVisited(badPlace.uri));
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
// the canAddURI test to make sure that the notification happens after *all*
// 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(callbackCountFailure, EXPECTED_COUNT_FAILURE);
yield promiseAsyncUpdates();
}
});
function test_add_visit()
{
add_task(function* test_add_visit() {
const VISIT_TIME = Date.now() * 1000;
let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_add_visit"),
@ -720,10 +698,9 @@ function test_add_visit()
yield promiseAsyncUpdates();
}
}
}
});
function test_properties_saved()
{
add_task(function* test_properties_saved() {
// Check each transition type to make sure it is saved properly.
let places = [];
for (let transitionType = TRANSITION_LINK;
@ -804,10 +781,9 @@ function test_properties_saved()
yield promiseAsyncUpdates();
}
}
}
});
function test_guid_saved()
{
add_task(function* test_guid_saved() {
let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_guid_saved"),
guid: "__TESTGUID__",
@ -828,10 +804,9 @@ function test_guid_saved()
do_check_eq(placeInfo.guid, place.guid);
do_check_guid_for_uri(uri, place.guid);
yield promiseAsyncUpdates();
}
});
function test_referrer_saved()
{
add_task(function* test_referrer_saved() {
let places = [
{ uri: NetUtil.newURI(TEST_DOMAIN + "test_referrer_saved/referrer"),
visits: [
@ -881,10 +856,9 @@ function test_referrer_saved()
yield promiseAsyncUpdates();
}
}
}
});
function test_guid_change_saved()
{
add_task(function* test_guid_change_saved() {
// First, add a visit for it.
let place = {
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);
yield promiseAsyncUpdates();
}
});
function test_title_change_saved()
{
add_task(function* test_title_change_saved() {
// First, add a visit for it.
let place = {
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);
yield promiseAsyncUpdates();
}
});
function test_no_title_does_not_clear_title()
{
add_task(function* test_no_title_does_not_clear_title() {
const TITLE = "test title";
// First, add a visit for it.
let place = {
@ -984,10 +956,9 @@ function test_no_title_does_not_clear_title()
do_check_title_for_uri(place.uri, TITLE);
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
// get notified if we do not specify a title.
let place = {
@ -1015,36 +986,35 @@ function test_title_change_notifies()
place.uri = NetUtil.newURI(place.uri.spec + "/new-visit-with-title");
place.title = "title 1";
function promiseTitleChangedObserver(aPlace) {
let deferred = Promise.defer();
let callbackCount = 0;
let observer = new TitleChangedObserver(aPlace.uri, aPlace.title, function() {
switch (++callbackCount) {
case 1:
// The third case to test is to make sure we get a notification when
// we change an existing place.
observer.expectedTitle = place.title = "title 2";
place.visits = [new VisitInfo()];
PlacesUtils.asyncHistory.updatePlaces(place);
break;
case 2:
PlacesUtils.history.removeObserver(silentObserver);
PlacesUtils.history.removeObserver(observer);
deferred.resolve();
break;
};
});
return new Promise((resolve, reject) => {
let callbackCount = 0;
let observer = new TitleChangedObserver(aPlace.uri, aPlace.title, function() {
switch (++callbackCount) {
case 1:
// The third case to test is to make sure we get a notification when
// we change an existing place.
observer.expectedTitle = place.title = "title 2";
place.visits = [new VisitInfo()];
PlacesUtils.asyncHistory.updatePlaces(place);
break;
case 2:
PlacesUtils.history.removeObserver(silentObserver);
PlacesUtils.history.removeObserver(observer);
resolve();
break;
};
});
PlacesUtils.history.addObserver(observer, false);
PlacesUtils.asyncHistory.updatePlaces(aPlace);
return deferred.promise;
PlacesUtils.history.addObserver(observer, false);
PlacesUtils.asyncHistory.updatePlaces(aPlace);
});
}
yield promiseTitleChangedObserver(place);
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
// nsINavHistoryObserver and the other is the uri-visit-saved observer topic.
let place = {
@ -1057,44 +1027,43 @@ function test_visit_notifies()
do_check_false(yield promiseIsURIVisited(place.uri));
function promiseVisitObserver(aPlace) {
let deferred = Promise.defer();
let callbackCount = 0;
let finisher = function() {
if (++callbackCount == 2) {
deferred.resolve();
return new Promise((resolve, reject) => {
let callbackCount = 0;
let finisher = function() {
if (++callbackCount == 2) {
resolve();
}
}
}
let visitObserver = new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType) {
let visit = place.visits[0];
do_check_eq(visit.visitDate, aVisitDate);
do_check_eq(visit.transitionType, aTransitionType);
let visitObserver = new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType) {
let visit = place.visits[0];
do_check_eq(visit.visitDate, aVisitDate);
do_check_eq(visit.transitionType, aTransitionType);
PlacesUtils.history.removeObserver(visitObserver);
finisher();
PlacesUtils.history.removeObserver(visitObserver);
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 promiseAsyncUpdates();
}
});
// test with empty mozIVisitInfoCallback object
function test_callbacks_not_supplied()
{
add_task(function* test_callbacks_not_supplied() {
const URLS = [
"imap://cyrus.andrew.cmu.edu/archive.imap", // bad URI
"http://mozilla.org/" // valid URI
@ -1121,40 +1090,36 @@ function test_callbacks_not_supplied()
PlacesUtils.asyncHistory.updatePlaces(places, {});
yield promiseAsyncUpdates();
}
});
////////////////////////////////////////////////////////////////////////////////
//// Test Runner
// Test that we don't wrongly overwrite typed and hidden when adding new visits.
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);
[
test_interface_exists,
test_invalid_uri_throws,
test_invalid_places_throws,
test_invalid_guid_throws,
test_no_visits_throws,
test_add_visit_no_date_throws,
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);
let db = yield PlacesUtils.promiseDBConnection();
let rows = yield db.execute("SELECT hidden, typed FROM moz_places WHERE url = :url",
{ url: "http://mozilla.org/" });
Assert.equal(rows[0].getResultByName("typed"), 1,
"The page should be marked as typed");
Assert.equal(rows[0].getResultByName("hidden"), 0,
"The page should be marked as not hidden");
});
function run_test()
{

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

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

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

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

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

@ -930,6 +930,14 @@ 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"] {
-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 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-";
this.markup.setTextContentForElement(elementId + "tagname", tagName);

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

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

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

@ -500,6 +500,7 @@ let NetworkHelper = {
* - state: The security of the connection used to fetch this
* request. Has one of following string values:
* * "insecure": the connection was not secure (only http)
* * "weak": the connection has minor security issues
* * "broken": secure connection failed (e.g. expired cert)
* * "secure": the connection was properly secured.
* If state == broken:
@ -511,6 +512,9 @@ let NetworkHelper = {
* See parseCertificateInfo for the contents.
* - hsts: true if host uses Strict Transport Security, 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) {
const info = {
@ -551,7 +555,7 @@ let NetworkHelper = {
* => .securityState has STATE_IS_BROKEN flag
* => .errorCode is NOT an NSS error code
* => .errorMessage is not available
* => state === "insecure"
* => state === "weak"
*/
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
@ -561,10 +565,26 @@ let NetworkHelper = {
const NSSErrorsService = Cc['@mozilla.org/nss_errors_service;1']
.getService(Ci.nsINSSErrorsService);
const SSLStatus = securityInfo.SSLStatus;
if (!NSSErrorsService.isNSSErrorCode(securityInfo.errorCode)) {
const state = securityInfo.securityState;
if (securityInfo.securityState & wpl.STATE_IS_SECURE) {
// The connection is secure.
info.state = "secure";
if (state & wpl.STATE_IS_SECURE) {
// The connection is 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.
info.cipherSuite = SSLStatus.cipherName;
@ -598,14 +618,10 @@ let NetworkHelper = {
info.hpkp = false;
}
} else if (NSSErrorsService.isNSSErrorCode(securityInfo.errorCode)) {
} else {
// The connection failed.
info.state = "broken";
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;
@ -683,6 +699,46 @@ let NetworkHelper = {
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)) {

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

@ -89,12 +89,12 @@ function test_secureSecurityInfo() {
}
/**
* Test that STATE_IS_BROKEN returns "insecure"
* Test that STATE_IS_BROKEN returns "weak"
*/
function test_brokenSecurityInfo() {
MockSecurityInfo.securityState = wpl.STATE_IS_BROKEN;
let result = NetworkHelper.parseSecurityInfo(MockSecurityInfo, {});
equal(result.state, "insecure",
"state == 'insecure' if securityState contains STATE_IS_BROKEN flag");
equal(result.state, "weak",
"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-state.js]
[test_security-info-static-hpkp.js]
[test_security-info-weakness-reasons.js]

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

@ -11,27 +11,35 @@ this.EXPORTED_SYMBOLS = [
let currentBrowser = null;
this.SelectParentHelper = {
populate: function(popup, items, selectedIndex) {
populate: function(menulist, items, selectedIndex) {
// Clear the current contents of the popup
popup.textContent = "";
populateChildren(popup, items, selectedIndex);
menulist.menupopup.textContent = "";
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;
this._registerListeners(popup);
popup.hidden = false;
this._registerListeners(menulist.menupopup);
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) {
popup.hidePopup();
hide: function(menulist) {
menulist.menupopup.hidePopup();
},
handleEvent: function(event) {
let popup = event.currentTarget;
let menulist = popup.parentNode;
switch (event.type) {
case "command":
@ -47,6 +55,7 @@ this.SelectParentHelper = {
currentBrowser.messageManager.sendAsyncMessage("Forms:DismissedDropDown", {});
currentBrowser = null;
this._unregisterListeners(popup);
menulist.hidden = true;
break;
}
},
@ -69,11 +78,6 @@ function populateChildren(element, options, selectedIndex, startIndex = 0, isGro
for (let option of options) {
let item = element.ownerDocument.createElement("menuitem");
item.setAttribute("label", option.textContent);
item.setAttribute("type", "radio");
if (index == selectedIndex) {
item.setAttribute("checked", "true");
}
element.appendChild(item);

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

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