Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-06-08 12:41:24 +02:00
commit 72bb8e2d41
188 changed files with 4726 additions and 2845 deletions

View File

@ -800,11 +800,12 @@ getParentCB(AtkObject *aAtkObj)
atkParent = parent ? AccessibleWrap::GetAtkObject(parent) : nullptr;
} else if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
ProxyAccessible* parent = proxy->Parent();
if (parent)
if (parent) {
atkParent = GetWrapperFor(parent);
// Otherwise this should be the proxy for the tab's top level document.
atkParent = AccessibleWrap::GetAtkObject(proxy->OuterDocOfRemoteBrowser());
} else {
// Otherwise this should be the proxy for the tab's top level document.
atkParent = AccessibleWrap::GetAtkObject(proxy->OuterDocOfRemoteBrowser());
}
}
if (atkParent)

View File

@ -456,7 +456,7 @@ DocAccessible::Shutdown()
// XXX thinking about ordering?
if (IPCAccessibilityActive()) {
DocAccessibleChild::Send__delete__(mIPCDoc);
mIPCDoc->Shutdown();
MOZ_ASSERT(!mIPCDoc);
}

View File

@ -70,6 +70,9 @@ DocAccessibleChild::IdToAccessible(const uint64_t& aID) const
if (!aID)
return mDoc;
if (!mDoc)
return nullptr;
return mDoc->GetAccessibleByUniqueID(reinterpret_cast<void*>(aID));
}
@ -225,7 +228,7 @@ DocAccessibleChild::RecvRelationByType(const uint64_t& aID,
const uint32_t& aType,
nsTArray<uint64_t>* aTargets)
{
Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
Accessible* acc = IdToAccessible(aID);
if (!acc)
return true;
@ -258,7 +261,7 @@ bool
DocAccessibleChild::RecvRelations(const uint64_t& aID,
nsTArray<RelationTargets>* aRelations)
{
Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
Accessible* acc = IdToAccessible(aID);
if (!acc)
return true;

View File

@ -32,10 +32,21 @@ public:
{ MOZ_COUNT_CTOR(DocAccessibleChild); }
~DocAccessibleChild()
{
mDoc->SetIPCDoc(nullptr);
// Shutdown() should have been called, but maybe it isn't if the process is
// killed?
MOZ_ASSERT(!mDoc);
if (mDoc)
mDoc->SetIPCDoc(nullptr);
MOZ_COUNT_DTOR(DocAccessibleChild);
}
void Shutdown()
{
mDoc->SetIPCDoc(nullptr);
mDoc = nullptr;
SendShutdown();
}
void ShowEvent(AccShowEvent* aShowEvent);
/*

View File

@ -8,6 +8,7 @@
#include "nsAutoPtr.h"
#include "mozilla/a11y/Platform.h"
#include "ProxyAccessible.h"
#include "mozilla/dom/TabParent.h"
namespace mozilla {
namespace a11y {
@ -186,6 +187,18 @@ DocAccessibleParent::ShutdownAccessibles(ProxyEntry* entry, void*)
return PL_DHASH_REMOVE;
}
bool
DocAccessibleParent::RecvShutdown()
{
Destroy();
if (!static_cast<dom::TabParent*>(Manager())->IsDestroyed()) {
return PDocAccessibleParent::Send__delete__(this);
}
return true;
}
void
DocAccessibleParent::Destroy()
{

View File

@ -59,6 +59,7 @@ public:
mParentDoc = nullptr;
}
virtual bool RecvShutdown() override;
void Destroy();
virtual void ActorDestroy(ActorDestroyReason aWhy) override
{

View File

@ -48,7 +48,7 @@ prio(normal upto high) sync protocol PDocAccessible
manager PBrowser;
parent:
__delete__();
Shutdown();
/*
* Notify the parent process the document in the child process is firing an
@ -67,6 +67,8 @@ parent:
BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
child:
__delete__();
// Accessible
prio(high) sync State(uint64_t aID) returns(uint64_t states);
prio(high) sync Name(uint64_t aID) returns(nsString name);

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1432051555000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1433264296000">
<emItems>
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
<versionRange minVersion="0" maxVersion="*">
@ -282,6 +282,15 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i914" id="{0153E448-190B-4987-BDE1-F256CADA672F}">
<versionRange minVersion="0" maxVersion="15.0.6" severity="1">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="39.0a1" maxVersion="*" />
</targetApplication>
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i678" id="{C4A4F5A0-4B89-4392-AFAC-D58010E349AF}">
<versionRange minVersion="0" maxVersion="*" severity="1">
@ -463,8 +472,13 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
<emItem blockID="i916" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
</versionRange>
<versionRange minVersion="0" maxVersion="15.0.4" severity="1">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="39.0a1" maxVersion="*" />
</targetApplication>
</versionRange>
<prefs>
</prefs>
@ -786,8 +800,13 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i111" os="WINNT" id="{C3949AC2-4B17-43ee-B4F1-D26B9D42404D}">
<emItem blockID="i918" os="WINNT" id="{C3949AC2-4B17-43ee-B4F1-D26B9D42404D}">
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
</versionRange>
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
<versionRange minVersion="39.0a1" maxVersion="*" />
</targetApplication>
</versionRange>
<prefs>
</prefs>

View File

@ -1924,3 +1924,8 @@ pref("browser.pocket.useLocaleList", true);
pref("browser.pocket.enabledLocales", "en-US de es-ES ja ja-JP-mac ru");
pref("view_source.tab", true);
// Enable Service Workers for desktop on non-release builds
#ifndef RELEASE_BUILD
pref("dom.serviceWorkers.enabled", true);
#endif

View File

@ -28,6 +28,159 @@ const gXPInstallObserver = {
return null;
},
pendingInstalls: new WeakMap(),
showInstallConfirmation: function(browser, installInfo, height = undefined) {
// If the confirmation notification is already open cache the installInfo
// and the new confirmation will be shown later
if (PopupNotifications.getNotification("addon-install-confirmation", browser)) {
let pending = this.pendingInstalls.get(browser);
if (pending) {
pending.push(installInfo);
} else {
this.pendingInstalls.set(browser, [installInfo]);
}
return;
}
const anchorID = "addons-notification-icon";
// Make notifications persist a minimum of 30 seconds
var options = {
timeout: Date.now() + 30000
};
try {
options.displayOrigin = installInfo.originatingURI.host;
} catch (e) {
// originatingURI might be missing or 'host' might throw for non-nsStandardURL nsIURIs.
}
let cancelInstallation = () => {
if (installInfo) {
for (let install of installInfo.installs)
install.cancel();
}
this.acceptInstallation = null;
let tab = gBrowser.getTabForBrowser(browser);
if (tab)
tab.removeEventListener("TabClose", cancelInstallation);
window.removeEventListener("unload", cancelInstallation);
// Make sure the browser is still alive.
if (gBrowser.browsers.indexOf(browser) == -1)
return;
let pending = this.pendingInstalls.get(browser);
if (pending && pending.length)
this.showInstallConfirmation(browser, pending.shift());
};
let unsigned = installInfo.installs.filter(i => i.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING);
let someUnsigned = unsigned.length > 0 && unsigned.length < installInfo.installs.length;
options.eventCallback = (aEvent) => {
switch (aEvent) {
case "removed":
cancelInstallation();
break;
case "shown":
let addonList = document.getElementById("addon-install-confirmation-content");
while (addonList.firstChild)
addonList.firstChild.remove();
for (let install of installInfo.installs) {
let container = document.createElement("hbox");
let name = document.createElement("label");
name.setAttribute("value", install.addon.name);
name.setAttribute("class", "addon-install-confirmation-name");
container.appendChild(name);
if (someUnsigned && install.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) {
let unsigned = document.createElement("label");
unsigned.setAttribute("value", gNavigatorBundle.getString("addonInstall.unsigned"));
unsigned.setAttribute("class", "addon-install-confirmation-unsigned");
container.appendChild(unsigned);
}
addonList.appendChild(container);
}
this.acceptInstallation = () => {
for (let install of installInfo.installs)
install.install();
installInfo = null;
Services.telemetry
.getHistogramById("SECURITY_UI")
.add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL_CLICK_THROUGH);
};
break;
}
};
options.learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL") +
"find-and-install-add-ons";
let messageString;
let notification = document.getElementById("addon-install-confirmation-notification");
if (unsigned.length == installInfo.installs.length) {
// None of the add-ons are verified
messageString = gNavigatorBundle.getString("addonConfirmInstallUnsigned.message");
notification.setAttribute("warning", "true");
}
else if (unsigned.length == 0) {
// All add-ons are verified or don't need to be verified
messageString = gNavigatorBundle.getString("addonConfirmInstall.message");
notification.removeAttribute("warning");
}
else {
// Some of the add-ons are unverified, the list of names will indicate
// which
messageString = gNavigatorBundle.getString("addonConfirmInstallSomeUnsigned.message");
notification.setAttribute("warning", "true");
}
let brandBundle = document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName");
messageString = PluralForm.get(installInfo.installs.length, messageString);
messageString = messageString.replace("#1", brandShortName);
messageString = messageString.replace("#2", installInfo.installs.length);
let cancelButton = document.getElementById("addon-install-confirmation-cancel");
cancelButton.label = gNavigatorBundle.getString("addonInstall.cancelButton.label");
cancelButton.accessKey = gNavigatorBundle.getString("addonInstall.cancelButton.accesskey");
let acceptButton = document.getElementById("addon-install-confirmation-accept");
acceptButton.label = gNavigatorBundle.getString("addonInstall.acceptButton.label");
acceptButton.accessKey = gNavigatorBundle.getString("addonInstall.acceptButton.accesskey");
if (height) {
let notification = document.getElementById("addon-install-confirmation-notification");
notification.style.minHeight = height + "px";
}
let tab = gBrowser.getTabForBrowser(browser);
if (tab) {
gBrowser.selectedTab = tab;
tab.addEventListener("TabClose", cancelInstallation);
}
window.addEventListener("unload", cancelInstallation);
PopupNotifications.show(browser, "addon-install-confirmation", messageString,
anchorID, null, null, options);
Services.telemetry
.getHistogramById("SECURITY_UI")
.add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL);
},
observe: function (aSubject, aTopic, aData)
{
var brandBundle = document.getElementById("bundle_brand");
@ -54,22 +207,6 @@ const gXPInstallObserver = {
// originatingURI might be missing or 'host' might throw for non-nsStandardURL nsIURIs.
}
let cancelInstallation = () => {
if (installInfo) {
for (let install of installInfo.installs)
install.cancel();
}
if (aTopic == "addon-install-confirmation")
this.acceptInstallation = null;
let tab = gBrowser.getTabForBrowser(browser);
if (tab)
tab.removeEventListener("TabClose", cancelInstallation);
window.removeEventListener("unload", cancelInstallation);
};
switch (aTopic) {
case "addon-install-disabled": {
notificationID = "xpinstall-disabled";
@ -188,106 +325,16 @@ const gXPInstallObserver = {
this._removeProgressNotification(browser);
break; }
case "addon-install-confirmation": {
let unsigned = installInfo.installs.filter(i => i.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING);
let someUnsigned = unsigned.length > 0 && unsigned.length < installInfo.installs.length;
options.eventCallback = (aEvent) => {
switch (aEvent) {
case "removed":
cancelInstallation();
break;
case "shown":
let addonList = document.getElementById("addon-install-confirmation-content");
while (addonList.firstChild)
addonList.firstChild.remove();
for (let install of installInfo.installs) {
let container = document.createElement("hbox");
let name = document.createElement("label");
name.setAttribute("value", install.addon.name);
name.setAttribute("class", "addon-install-confirmation-name");
container.appendChild(name);
if (someUnsigned && install.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) {
let unsigned = document.createElement("label");
unsigned.setAttribute("value", gNavigatorBundle.getString("addonInstall.unsigned"));
unsigned.setAttribute("class", "addon-install-confirmation-unsigned");
container.appendChild(unsigned);
}
addonList.appendChild(container);
}
this.acceptInstallation = () => {
for (let install of installInfo.installs)
install.install();
installInfo = null;
Services.telemetry
.getHistogramById("SECURITY_UI")
.add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL_CLICK_THROUGH);
};
break;
}
};
options.learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL") +
"find-and-install-add-ons";
let notification = document.getElementById("addon-install-confirmation-notification");
if (unsigned.length == installInfo.installs.length) {
// None of the add-ons are verified
messageString = gNavigatorBundle.getString("addonConfirmInstallUnsigned.message");
notification.setAttribute("warning", "true");
}
else if (unsigned.length == 0) {
// All add-ons are verified or don't need to be verified
messageString = gNavigatorBundle.getString("addonConfirmInstall.message");
notification.removeAttribute("warning");
}
else {
// Some of the add-ons are unverified, the list of names will indicate
// which
messageString = gNavigatorBundle.getString("addonConfirmInstallSomeUnsigned.message");
notification.setAttribute("warning", "true");
}
messageString = PluralForm.get(installInfo.installs.length, messageString);
messageString = messageString.replace("#1", brandShortName);
messageString = messageString.replace("#2", installInfo.installs.length);
let cancelButton = document.getElementById("addon-install-confirmation-cancel");
cancelButton.label = gNavigatorBundle.getString("addonInstall.cancelButton.label");
cancelButton.accessKey = gNavigatorBundle.getString("addonInstall.cancelButton.accesskey");
let acceptButton = document.getElementById("addon-install-confirmation-accept");
acceptButton.label = gNavigatorBundle.getString("addonInstall.acceptButton.label");
acceptButton.accessKey = gNavigatorBundle.getString("addonInstall.acceptButton.accesskey");
let showNotification = () => {
let tab = gBrowser.getTabForBrowser(browser);
if (tab) {
gBrowser.selectedTab = tab;
tab.addEventListener("TabClose", cancelInstallation);
}
window.addEventListener("unload", cancelInstallation);
let height = undefined;
if (PopupNotifications.isPanelOpen) {
let rect = document.getElementById("addon-progress-notification").getBoundingClientRect();
let notification = document.getElementById("addon-install-confirmation-notification");
notification.style.minHeight = rect.height + "px";
height = rect.height;
}
PopupNotifications.show(browser, notificationID, messageString, anchorID,
action, null, options);
this._removeProgressNotification(browser);
Services.telemetry
.getHistogramById("SECURITY_UI")
.add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL);
this.showInstallConfirmation(browser, installInfo, height);
};
let progressNotification = PopupNotifications.getNotification("addon-progress", browser);

View File

@ -61,8 +61,20 @@ var FullScreen = {
this._fullScrToggler.addEventListener("dragenter", this._expandCallback, false);
}
if (enterFS) {
gNavToolbox.setAttribute("inFullscreen", true);
document.documentElement.setAttribute("inFullscreen", true);
} else {
gNavToolbox.removeAttribute("inFullscreen");
document.documentElement.removeAttribute("inFullscreen");
}
// show/hide menubars, toolbars (except the full screen toolbar)
this.showXULChrome("toolbar", !enterFS);
// On OS X Lion, we don't want to hide toolbars when entering
// fullscreen, unless we're entering DOM fullscreen.
if (document.mozFullScreen || !this.useLionFullScreen) {
this.showXULChrome("toolbar", !enterFS);
}
if (enterFS) {
document.addEventListener("keypress", this._keyToggleCallback, false);
@ -557,14 +569,6 @@ var FullScreen = {
}
}
if (aShow) {
gNavToolbox.removeAttribute("inFullscreen");
document.documentElement.removeAttribute("inFullscreen");
} else {
gNavToolbox.setAttribute("inFullscreen", true);
document.documentElement.setAttribute("inFullscreen", true);
}
ToolbarIconColor.inferFromText();
// For Lion fullscreen, all fullscreen controls are hidden, don't

View File

@ -1181,7 +1181,7 @@ var gBrowserInit = {
break;
case "restoreAll":
for (let browserWin of browserWindows()) {
for (let tab of window.gBrowser.tabs) {
for (let tab of browserWin.gBrowser.tabs) {
SessionStore.reviveCrashedTab(tab);
}
}

View File

@ -34,11 +34,11 @@ function get_observer_topic(aNotificationId) {
return topic;
}
function wait_for_progress_notification(aCallback) {
wait_for_notification(PROGRESS_NOTIFICATION, aCallback, "popupshowing");
function wait_for_progress_notification(aCallback, aExpectedCount = 1) {
wait_for_notification(PROGRESS_NOTIFICATION, aCallback, aExpectedCount, "popupshowing");
}
function wait_for_notification(aId, aCallback, aEvent = "popupshown") {
function wait_for_notification(aId, aCallback, aExpectedCount = 1, aEvent = "popupshown") {
info("Waiting for " + aId + " notification");
let topic = get_observer_topic(aId);
@ -70,10 +70,11 @@ function wait_for_notification(aId, aCallback, aEvent = "popupshown") {
function verify() {
info("Saw a notification");
ok(PopupNotifications.isPanelOpen, "Panel should be open");
is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
is(PopupNotifications.panel.childNodes.length, aExpectedCount, "Should be the right number of notifications");
if (PopupNotifications.panel.childNodes.length) {
is(PopupNotifications.panel.childNodes[0].id,
aId + "-notification", "Should have seen the right notification");
let nodes = Array.from(PopupNotifications.panel.childNodes);
let notification = nodes.find(n => n.id == aId + "-notification");
ok(notification, "Should have seen the right notification");
}
aCallback(PopupNotifications.panel);
}
@ -135,6 +136,15 @@ function accept_install_dialog() {
}
}
function cancel_install_dialog() {
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
document.getElementById("addon-install-confirmation-cancel").click();
} else {
let win = Services.wm.getMostRecentWindow("Addons:Install");
win.document.documentElement.cancelDialog();
}
}
function wait_for_single_notification(aCallback) {
function inner_waiter() {
info("Waiting for single notification");
@ -456,6 +466,84 @@ function test_multiple() {
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
},
function test_sequential() {
// This test is only relevant if using the new doorhanger UI
if (!Preferences.get("xpinstall.customConfirmationUI", false)) {
runNextTest();
return;
}
// Wait for the progress notification
wait_for_progress_notification(function(aPanel) {
// Wait for the install confirmation dialog
wait_for_install_dialog(function() {
// Wait for the progress notification
// Should see the right add-on
let container = document.getElementById("addon-install-confirmation-content");
is(container.childNodes.length, 1, "Should be one item listed");
is(container.childNodes[0].firstChild.getAttribute("value"), "XPI Test", "Should have the right add-on");
wait_for_progress_notification(function(aPanel) {
// Should still have the right add-on in the confirmation notification
is(container.childNodes.length, 1, "Should be one item listed");
is(container.childNodes[0].firstChild.getAttribute("value"), "XPI Test", "Should have the right add-on");
// Wait for the install to complete, we won't see a new confirmation
// notification
Services.obs.addObserver(function observer() {
Services.obs.removeObserver(observer, "addon-install-confirmation");
// Make sure browser-addons.js executes first
executeSoon(function () {
// Should have dropped the progress notification
is(PopupNotifications.panel.childNodes.length, 1, "Should be the right number of notifications");
is(PopupNotifications.panel.childNodes[0].id, "addon-install-confirmation-notification",
"Should only be showing one install confirmation");
// Should still have the right add-on in the confirmation notification
is(container.childNodes.length, 1, "Should be one item listed");
is(container.childNodes[0].firstChild.getAttribute("value"), "XPI Test", "Should have the right add-on");
cancel_install_dialog();
ok(PopupNotifications.isPanelOpen, "Panel should still be open");
is(PopupNotifications.panel.childNodes.length, 1, "Should be the right number of notifications");
is(PopupNotifications.panel.childNodes[0].id, "addon-install-confirmation-notification",
"Should still have an install confirmation open");
// Should have the next add-on's confirmation dialog
is(container.childNodes.length, 1, "Should be one item listed");
is(container.childNodes[0].firstChild.getAttribute("value"), "Theme Test", "Should have the right add-on");
Services.perms.remove("example.com", "install");
wait_for_notification_close(() => {
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
});
cancel_install_dialog();
});
}, "addon-install-confirmation", false);
}, 2);
var triggers = encodeURIComponent(JSON.stringify({
"Theme XPI": "theme.xpi"
}));
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
});
});
var pm = Services.perms;
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
var triggers = encodeURIComponent(JSON.stringify({
"Restartless XPI": "restartless.xpi"
}));
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
},
function test_someunverified() {
// This test is only relevant if using the new doorhanger UI and allowing
// unsigned add-ons

View File

@ -48,7 +48,6 @@ support-files =
[browser_bug818118.js]
[browser_bug820497.js]
[browser_clearplugindata.js]
skip-if = e10s # bug 1149253
[browser_CTP_context_menu.js]
skip-if = toolkit == "gtk2" || toolkit == "gtk3" # fails intermittently on Linux (bug 909342)
[browser_CTP_crashreporting.js]

View File

@ -25,7 +25,7 @@
}
.preview-input-toolbar {
display: -moz-box;
display: flex;
width: 100%;
}
@ -39,7 +39,7 @@
margin-bottom: 1px;
padding-top: 0;
padding-bottom: 0;
-moz-box-flex: 1;
flex: 1;
}
:root {

View File

@ -52,6 +52,7 @@ support-files =
[browser_perf-details-04.js]
[browser_perf-details-05.js]
[browser_perf-details-06.js]
[browser_perf-details-07.js]
[browser_perf-events-calltree.js]
[browser_perf-front-basic-profiler-01.js]
[browser_perf-front-basic-timeline-01.js]

View File

@ -0,0 +1,63 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that when flame chart views scroll to change selection,
* other detail views are rerendered
*/
let HORIZONTAL_AXIS = 1;
let VERTICAL_AXIS = 2;
function* spawnTest() {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, PerformanceController, OverviewView, DetailsView, WaterfallView, JsCallTreeView, JsFlameGraphView } = panel.panelWin;
yield startRecording(panel);
yield stopRecording(panel);
let waterfallRendered = once(WaterfallView, EVENTS.WATERFALL_RENDERED);
let calltreeRendered = once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED);
let flamegraphRendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
OverviewView.setTimeInterval({ startTime: 10, endTime: 20 });
DetailsView.selectView("waterfall");
yield waterfallRendered;
DetailsView.selectView("js-calltree");
yield calltreeRendered;
DetailsView.selectView("js-flamegraph");
yield flamegraphRendered;
waterfallRendered = once(WaterfallView, EVENTS.WATERFALL_RENDERED);
calltreeRendered = once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED);
let overviewRangeSelected = once(OverviewView, EVENTS.OVERVIEW_RANGE_SELECTED);
once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED).then(() =>
ok(false, "FlameGraphView should not rerender, but be handled via its graph widget"));
// Reset the range to full view, trigger a "selection" event as if
// our mouse has done this
scroll(JsFlameGraphView.graph, 200, HORIZONTAL_AXIS, 10);
DetailsView.selectView("waterfall");
yield waterfallRendered;
ok(true, "Waterfall rerendered by flame graph changing interval");
DetailsView.selectView("js-calltree");
yield calltreeRendered;
ok(true, "CallTree rerendered by flame graph changing interval");
yield teardown(panel);
finish();
}
// EventUtils just doesn't work!
function scroll(graph, wheel, axis, x, y = 1) {
x /= window.devicePixelRatio;
y /= window.devicePixelRatio;
graph._onMouseMove({ testX: x, testY: y });
graph._onMouseWheel({ testX: x, testY: y, axis, detail: wheel, axis,
HORIZONTAL_AXIS,
VERTICAL_AXIS
});
}

View File

@ -9,7 +9,6 @@
function* spawnTest() {
let { target, panel } = yield initPerformance(MARKERS_URL);
let { $, $$, EVENTS, PerformanceController, OverviewView, WaterfallView } = panel.panelWin;
let { L10N } = devtools.require("devtools/performance/global");
// Hijack the markers massaging part of creating the waterfall view,
// to prevent collapsing markers and allowing this test to verify
@ -45,9 +44,9 @@ function* spawnTest() {
const tests = {
ConsoleTime: function (marker) {
shouldHaveLabel($, L10N.getStr("timeline.markerDetail.consoleTimerName"), "!!!", marker);
shouldHaveStack($, "startStack", marker);
shouldHaveStack($, "endStack", marker);
shouldHaveLabel($, "Timer Name:", "!!!", marker);
return true;
},
TimeStamp: function (marker) {
@ -83,10 +82,12 @@ function* spawnTest() {
let m = markers[i];
EventUtils.sendMouseEvent({ type: "mousedown" }, bar);
if (testsDone.indexOf(m.name) === -1 && tests[m.name]) {
let fullTestComplete = tests[m.name](m);
if (fullTestComplete) {
testsDone.push(m.name);
if (tests[m.name]) {
if (testsDone.indexOf(m.name) === -1) {
let fullTestComplete = tests[m.name](m);
if (fullTestComplete) {
testsDone.push(m.name);
}
}
} else {
info(`TODO: Need to add marker details tests for ${m.name}`);

View File

@ -44,6 +44,15 @@ let DetailsSubview = {
*/
rangeChangeDebounceTime: 0,
/**
* When the overview range changes, all details views will require a
* rerendering at a later point, determined by `shouldUpdateWhenShown` and
* `canUpdateWhileHidden` and whether or not its the current view.
* Set `requiresUpdateOnRangeChange` to false to not invalidate the view
* when the range changes.
*/
requiresUpdateOnRangeChange: true,
/**
* Flag specifying if this view should be updated when selected. This will
* be set to true, for example, when the range changes in the overview and
@ -93,6 +102,9 @@ let DetailsSubview = {
* Fired when a range is selected or cleared in the OverviewView.
*/
_onOverviewRangeChange: function (_, interval) {
if (!this.requiresUpdateOnRangeChange) {
return;
}
if (DetailsView.isViewSelected(this)) {
let debounced = () => {
if (!this.shouldUpdateWhileMouseIsActive && OverviewView.isMouseActive) {

View File

@ -86,7 +86,13 @@ let JsFlameGraphView = Heritage.extend(DetailsSubview, {
*/
_onRangeChangeInGraph: function () {
let interval = this.graph.getViewRange();
OverviewView.setTimeInterval(interval, { stopPropagation: true });
// Squelch rerendering this view when we update the range here
// to avoid recursion, as our FlameGraph handles rerendering itself
// when originating from within the graph.
this.requiresUpdateOnRangeChange = false;
OverviewView.setTimeInterval(interval);
this.requiresUpdateOnRangeChange = true;
},
/**

View File

@ -84,7 +84,13 @@ let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
*/
_onRangeChangeInGraph: function () {
let interval = this.graph.getViewRange();
OverviewView.setTimeInterval(interval, { stopPropagation: true });
// Squelch rerendering this view when we update the range here
// to avoid recursion, as our FlameGraph handles rerendering itself
// when originating from within the graph.
this.requiresUpdateOnRangeChange = false;
OverviewView.setTimeInterval(interval);
this.requiresUpdateOnRangeChange = true;
},
/**

View File

@ -57,6 +57,7 @@ support-files =
[browser_graphs-07b.js]
[browser_graphs-07c.js]
[browser_graphs-07d.js]
[browser_graphs-07e.js]
[browser_graphs-08.js]
[browser_graphs-09a.js]
[browser_graphs-09b.js]

View File

@ -0,0 +1,105 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that selections are drawn onto the canvas.
const TEST_DATA = [{ delta: 112, value: 48 }, { delta: 213, value: 59 }, { delta: 313, value: 60 }, { delta: 413, value: 59 }, { delta: 530, value: 59 }, { delta: 646, value: 58 }, { delta: 747, value: 60 }, { delta: 863, value: 48 }, { delta: 980, value: 37 }, { delta: 1097, value: 30 }, { delta: 1213, value: 29 }, { delta: 1330, value: 23 }, { delta: 1430, value: 10 }, { delta: 1534, value: 17 }, { delta: 1645, value: 20 }, { delta: 1746, value: 22 }, { delta: 1846, value: 39 }, { delta: 1963, value: 26 }, { delta: 2080, value: 27 }, { delta: 2197, value: 35 }, { delta: 2312, value: 47 }, { delta: 2412, value: 53 }, { delta: 2514, value: 60 }, { delta: 2630, value: 37 }, { delta: 2730, value: 36 }, { delta: 2830, value: 37 }, { delta: 2946, value: 36 }, { delta: 3046, value: 40 }, { delta: 3163, value: 47 }, { delta: 3280, value: 41 }, { delta: 3380, value: 35 }, { delta: 3480, value: 27 }, { delta: 3580, value: 39 }, { delta: 3680, value: 42 }, { delta: 3780, value: 49 }, { delta: 3880, value: 55 }, { delta: 3980, value: 60 }, { delta: 4080, value: 60 }, { delta: 4180, value: 60 }];
let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
let CURRENT_ZOOM = 1;
add_task(function*() {
yield promiseTab("about:blank");
yield performTest();
gBrowser.removeCurrentTab();
});
function* performTest() {
let [host, win, doc] = yield createHost();
let graph = new LineGraphWidget(doc.body, "fps");
yield graph.once("ready");
graph.setData(TEST_DATA);
info("Testing with normal zoom.");
testGraph(graph);
info("Testing while zoomed out.");
setZoom(host.frame, .5);
testGraph(graph);
info("Testing while zoomed in.");
setZoom(host.frame, 2);
testGraph(graph);
yield graph.destroy();
host.destroy();
}
function testGraph(graph) {
graph.dropSelection();
info("Making a selection.");
dragStart(graph, 100);
ok(graph.hasSelectionInProgress(),
"The selection should start (1).");
is(graph.getSelection().start, 100,
"The current selection start value is correct (1).");
is(graph.getSelection().end, 100,
"The current selection end value is correct (1).");
hover(graph, 200);
ok(graph.hasSelectionInProgress(),
"The selection should still be in progress (2).");
is(graph.getSelection().start, 100,
"The current selection start value is correct (2).");
is(graph.getSelection().end, 200,
"The current selection end value is correct (2).");
dragStop(graph, 300);
ok(!graph.hasSelectionInProgress(),
"The selection should have stopped (3).");
is(graph.getSelection().start, 100,
"The current selection start value is correct (3).");
is(graph.getSelection().end, 300,
"The current selection end value is correct (3).");
}
function setZoom(frame, zoomValue) {
let contViewer = frame.docShell.contentViewer;
CURRENT_ZOOM = contViewer.fullZoom = zoomValue;
}
// EventUtils just doesn't work!
function dispatchEvent(graph, x, y, fn) {
x *= CURRENT_ZOOM;
y *= CURRENT_ZOOM;
x /= window.devicePixelRatio;
y /= window.devicePixelRatio;
let quad = graph._canvas.getBoxQuads({
relativeTo: window.document
})[0];
let screenX = (window.screenX + quad.p1.x + x);
let screenY = (window.screenY + quad.p1.y + y);
fn({
screenX: screenX,
screenY: screenY,
});
}
function hover(graph, x, y = 1) {
dispatchEvent(graph, x, y, graph._onMouseMove);
}
function dragStart(graph, x, y = 1) {
dispatchEvent(graph, x, y, graph._onMouseMove);
dispatchEvent(graph, x, y, graph._onMouseDown);
}
function dragStop(graph, x, y = 1) {
dispatchEvent(graph, x, y, graph._onMouseMove);
dispatchEvent(graph, x, y, graph._onMouseUp);
}

View File

@ -10,6 +10,7 @@ const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
const {DevToolsWorker} = Cu.import("resource://gre/modules/devtools/shared/worker.js", {});
const {LayoutHelpers} = Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", {});
this.EXPORTED_SYMBOLS = [
"GraphCursor",
@ -977,6 +978,12 @@ AbstractCanvasGraph.prototype = {
let mouseX = Math.max(0, Math.min(x, maxX)) * this._pixelRatio;
let mouseY = Math.max(0, Math.min(x, maxY)) * this._pixelRatio;
// The coordinates need to be modified with the current zoom level
// to prevent them from being wrong.
let zoom = LayoutHelpers.getCurrentZoom(this._canvas);
mouseX /= zoom;
mouseY /= zoom;
return {mouseX,mouseY};
},

View File

@ -38,7 +38,7 @@
<body>
<div id="root" class="devtools-monospace">
<div class="devtools-toolbar">
<div id="ruleview-toolbar" class="devtools-toolbar">
<div class="devtools-searchbox">
<input id="ruleview-searchbox"
class="devtools-searchinput devtools-rule-searchbox"
@ -47,6 +47,12 @@
</div>
<!-- TODO : Bug 1165122 : Show this button by default -->
<button hidden="true" id="ruleview-add-rule-button" title="&addRuleButtonTooltip;" class="devtools-button"></button>
<button id="pseudo-class-panel-toggle" class="devtools-button"></button>
</div>
<div id="pseudo-class-panel" class="devtools-toolbar" hidden="true">
<label><input id="pseudo-hover-toggle" type="checkbox" value=":hover" />:hover</label>
<label><input id="pseudo-active-toggle" type="checkbox" value=":active" />:active</label>
<label><input id="pseudo-focus-toggle" type="checkbox" value=":focus" />:focus</label>
</div>
</div>

View File

@ -1130,11 +1130,18 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
this._onFilterKeyPress = this._onFilterKeyPress.bind(this);
this._onClearSearch = this._onClearSearch.bind(this);
this._onFilterTextboxContextMenu = this._onFilterTextboxContextMenu.bind(this);
this._onTogglePseudoClassPanel = this._onTogglePseudoClassPanel.bind(this);
this._onTogglePseudoClass = this._onTogglePseudoClass.bind(this);
this.element = this.doc.getElementById("ruleview-container");
this.addRuleButton = this.doc.getElementById("ruleview-add-rule-button");
this.searchField = this.doc.getElementById("ruleview-searchbox");
this.searchClearButton = this.doc.getElementById("ruleview-searchinput-clear");
this.pseudoClassPanel = this.doc.getElementById("pseudo-class-panel");
this.pseudoClassToggle = this.doc.getElementById("pseudo-class-panel-toggle");
this.hoverCheckbox = this.doc.getElementById("pseudo-hover-toggle");
this.activeCheckbox = this.doc.getElementById("pseudo-active-toggle");
this.focusCheckbox = this.doc.getElementById("pseudo-focus-toggle");
this.searchClearButton.hidden = true;
@ -1145,6 +1152,10 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
this.searchField.addEventListener("keypress", this._onFilterKeyPress);
this.searchField.addEventListener("contextmenu", this._onFilterTextboxContextMenu);
this.searchClearButton.addEventListener("click", this._onClearSearch);
this.pseudoClassToggle.addEventListener("click", this._onTogglePseudoClassPanel);
this.hoverCheckbox.addEventListener("click", this._onTogglePseudoClass);
this.activeCheckbox.addEventListener("click", this._onTogglePseudoClass);
this.focusCheckbox.addEventListener("click", this._onTogglePseudoClass);
this._handlePrefChange = this._handlePrefChange.bind(this);
this._onSourcePrefChanged = this._onSourcePrefChanged.bind(this);
@ -1823,8 +1834,19 @@ CssRuleView.prototype = {
this.searchField.removeEventListener("contextmenu",
this._onFilterTextboxContextMenu);
this.searchClearButton.removeEventListener("click", this._onClearSearch);
this.pseudoClassToggle.removeEventListener("click",
this._onTogglePseudoClassPanel);
this.hoverCheckbox.removeEventListener("click", this._onTogglePseudoClass);
this.activeCheckbox.removeEventListener("click", this._onTogglePseudoClass);
this.focusCheckbox.removeEventListener("click", this._onTogglePseudoClass);
this.searchField = null;
this.searchClearButton = null;
this.pseudoClassPanel = null;
this.pseudoClassToggle = null;
this.hoverCheckbox = null;
this.activeCheckbox = null;
this.focusCheckbox = null;
if (this.element.parentNode) {
this.element.parentNode.removeChild(this.element);
@ -1849,10 +1871,12 @@ CssRuleView.prototype = {
}
this.clear();
this.clearPseudoClassPanel();
this._viewedElement = aElement;
if (!this._viewedElement) {
this._showEmpty();
this.refreshPseudoClassPanel();
return promise.resolve(undefined);
}
@ -1894,6 +1918,45 @@ CssRuleView.prototype = {
});
},
/**
* Clear the pseudo class options panel by removing the checked and disabled
* attributes for each checkbox.
*/
clearPseudoClassPanel: function() {
this.hoverCheckbox.checked = this.hoverCheckbox.disabled = false;
this.activeCheckbox.checked = this.activeCheckbox.disabled = false;
this.focusCheckbox.checked = this.focusCheckbox.disabled = false;
},
/**
* Update the pseudo class options for the currently highlighted element.
*/
refreshPseudoClassPanel: function() {
if (!this._elementStyle || !this.inspector.selection.isElementNode()) {
this.hoverCheckbox.disabled = true;
this.activeCheckbox.disabled = true;
this.focusCheckbox.disabled = true;
return;
}
for (let pseudoClassLock of this._elementStyle.element.pseudoClassLocks) {
switch (pseudoClassLock) {
case ":hover": {
this.hoverCheckbox.checked = true;
break;
}
case ":active": {
this.activeCheckbox.checked = true;
break;
}
case ":focus": {
this.focusCheckbox.checked = true;
break;
}
}
}
},
_populate: function(clearRules = false) {
let elementStyle = this._elementStyle;
return this._elementStyle.populate().then(() => {
@ -1906,6 +1969,8 @@ CssRuleView.prototype = {
}
this._createEditors();
this.refreshPseudoClassPanel();
// Notify anyone that cares that we refreshed.
this.emit("ruleview-refreshed");
return undefined;
@ -2289,7 +2354,29 @@ CssRuleView.prototype = {
}
this._editorsExpandedForFilter = [];
}
},
/**
* Called when the pseudo class panel button is clicked and toggles
* the display of the pseudo class panel.
*/
_onTogglePseudoClassPanel: function() {
if (this.pseudoClassPanel.hidden) {
this.pseudoClassToggle.setAttribute("checked", "true");
} else {
this.pseudoClassToggle.removeAttribute("checked");
}
this.pseudoClassPanel.hidden = !this.pseudoClassPanel.hidden;
},
/**
* Called when a pseudo class checkbox is clicked and toggles
* the pseudo class for the current selected element.
*/
_onTogglePseudoClass: function(event) {
let target = event.currentTarget;
this.inspector.togglePseudoClass(target.value);
}
};
/**

View File

@ -24,9 +24,28 @@ body {
flex: 1;
}
#root .devtools-toolbar {
.devtools-toolbar {
width: 100%;
display: -moz-box;
display: flex;
}
#pseudo-class-panel {
position: relative;
top: -1px;
overflow-y: hidden;
max-height: 24px;
justify-content: space-around;
transition-property: max-height;
transition-duration: 150ms;
transition-timing-function: ease;
}
#pseudo-class-panel[hidden] {
max-height: 0px;
}
#pseudo-class-panel > label {
-moz-user-select: none;
}
.ruleview {

View File

@ -114,6 +114,7 @@ skip-if = (os == "win" && debug) || e10s # bug 963492: win. bug 1040653: e10s.
[browser_ruleview_pseudo-element_01.js]
[browser_ruleview_pseudo-element_02.js]
skip-if = e10s # Bug 1090340
[browser_ruleview_pseudo_lock_options.js]
[browser_ruleview_refresh-on-attribute-change_01.js]
[browser_ruleview_refresh-on-attribute-change_02.js]
[browser_ruleview_refresh-on-style-change.js]

View File

@ -0,0 +1,104 @@
/* 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 the rule view pseudo lock options work properly.
let TEST_URI = [
"<style type='text/css'>",
" div {",
" color: red;",
" }",
" div:hover {",
" color: blue;",
" }",
" div:active {",
" color: yellow;",
" }",
" div:focus {",
" color: green;",
" }",
"</style>",
"<div>test div</div>"
].join("\n");
add_task(function*() {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
yield selectNode("div", inspector);
info("Toggle the pseudo class panel open");
ok(view.pseudoClassPanel.hidden, "Pseudo Class Panel Hidden");
view.pseudoClassToggle.click();
ok(!view.pseudoClassPanel.hidden, "Pseudo Class Panel Opened");
ok(!view.hoverCheckbox.disabled, ":hover checkbox is not disabled");
ok(!view.activeCheckbox.disabled, ":active checkbox is not disabled");
ok(!view.focusCheckbox.disabled, ":focus checkbox is not disabled");
info("Toggle each pseudo lock and check that the pseudo lock is added");
yield togglePseudoClass(inspector, view, view.hoverCheckbox);
yield assertPseudoAdded(inspector, view, ":hover", 3, 1);
yield togglePseudoClass(inspector, view, view.hoverCheckbox);
yield assertPseudoRemoved(inspector, view, 2);
yield togglePseudoClass(inspector, view, view.activeCheckbox);
yield assertPseudoAdded(inspector, view, ":active", 3, 1);
yield togglePseudoClass(inspector, view, view.activeCheckbox);
yield assertPseudoRemoved(inspector, view, 2);
yield togglePseudoClass(inspector, view, view.focusCheckbox);
yield assertPseudoAdded(inspector, view, ":focus", 3, 1);
yield togglePseudoClass(inspector, view, view.focusCheckbox);
yield assertPseudoRemoved(inspector, view, 2);
info("Toggle all pseudo lock and check that the pseudo lock is added");
yield togglePseudoClass(inspector, view, view.hoverCheckbox);
yield togglePseudoClass(inspector, view, view.activeCheckbox);
yield togglePseudoClass(inspector, view, view.focusCheckbox);
yield assertPseudoAdded(inspector, view, ":focus", 5, 1);
yield assertPseudoAdded(inspector, view, ":active", 5, 2);
yield assertPseudoAdded(inspector, view, ":hover", 5, 3);
yield togglePseudoClass(inspector, view, view.hoverCheckbox);
yield togglePseudoClass(inspector, view, view.activeCheckbox);
yield togglePseudoClass(inspector, view, view.focusCheckbox);
yield assertPseudoRemoved(inspector, view, 2);
info("Select a null element");
yield view.selectElement(null);
ok(!view.hoverCheckbox.checked && view.hoverCheckbox.disabled,
":hover checkbox is unchecked and disabled");
ok(!view.activeCheckbox.checked && view.activeCheckbox.disabled,
":active checkbox is unchecked and disabled");
ok(!view.focusCheckbox.checked && view.focusCheckbox.disabled,
":focus checkbox is unchecked and disabled");
info("Toggle the pseudo class panel close");
view.pseudoClassToggle.click();
ok(view.pseudoClassPanel.hidden, "Pseudo Class Panel Closed");
});
function* togglePseudoClass(inspector, ruleView, pseudoClassOption) {
info("Toggle the pseudoclass, wait for it to be applied");
let onRefresh = inspector.once("rule-view-refreshed");
pseudoClassOption.click();
yield onRefresh;
}
function* assertPseudoAdded(inspector, ruleView, pseudoClass, numRules,
childIndex) {
info("Check that the ruleview contains the pseudo-class rule");
is(ruleView.element.children.length, numRules,
"Should have " + numRules + " rules.");
is(getRuleViewRuleEditor(ruleView, childIndex).rule.selectorText,
"div" + pseudoClass, "rule view is showing " + pseudoClass + " rule");
}
function* assertPseudoRemoved(inspector, ruleView, numRules) {
info("Check that the ruleview no longer contains the pseudo-class rule");
is(ruleView.element.children.length, numRules,
"Should have " + numRules + " rules.");
is(getRuleViewRuleEditor(ruleView, 1).rule.selectorText, "div",
"Second rule is div");
}

View File

@ -664,8 +664,9 @@
@RESPATH@/browser/chrome/shumway.manifest
@RESPATH@/browser/chrome/shumway/*
#endif
@RESPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
@RESPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/chrome.manifest
@RESPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
@RESPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
@RESPATH@/chrome/toolkit@JAREXT@
@RESPATH@/chrome/toolkit.manifest
@RESPATH@/chrome/recording.manifest

View File

@ -258,6 +258,7 @@ browser.jar:
skin/classic/browser/devtools/add.svg (../shared/devtools/images/add.svg)
skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg)
skin/classic/browser/devtools/filter-swatch.svg (../shared/devtools/images/filter-swatch.svg)
skin/classic/browser/devtools/pseudo-class.svg (../shared/devtools/images/pseudo-class.svg)
skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png)
skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png)
skin/classic/browser/devtools/performance-icons.svg (../shared/devtools/images/performance-icons.svg)
@ -469,6 +470,7 @@ browser.jar:
skin/classic/browser/warning16.png (../shared/warning16.png)
skin/classic/browser/warning16@2x.png (../shared/warning16@2x.png)
../extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/chrome.jar:
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
% override chrome://browser/skin/feeds/audioFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
% override chrome://browser/skin/feeds/videoFeedIcon.png chrome://browser/skin/feeds/feedIcon.png

View File

@ -373,6 +373,7 @@ browser.jar:
skin/classic/browser/devtools/add.svg (../shared/devtools/images/add.svg)
skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg)
skin/classic/browser/devtools/filter-swatch.svg (../shared/devtools/images/filter-swatch.svg)
skin/classic/browser/devtools/pseudo-class.svg (../shared/devtools/images/pseudo-class.svg)
skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png)
skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png)
skin/classic/browser/devtools/performance-icons.svg (../shared/devtools/images/performance-icons.svg)
@ -613,6 +614,7 @@ browser.jar:
skin/classic/browser/warning16.png (../shared/warning16.png)
skin/classic/browser/warning16@2x.png (../shared/warning16@2x.png)
../extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/chrome.jar:
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
% override chrome://browser/skin/feeds/audioFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png
% override chrome://browser/skin/feeds/videoFeedIcon.png chrome://browser/skin/feeds/feedIcon.png

View File

@ -153,7 +153,7 @@ body {
#root .devtools-toolbar {
width: 100%;
display: -moz-box;
display: flex;
}
.link {

View File

@ -0,0 +1,29 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style>
use[id^="pseudo-class"]:not(:target) {
display: none;
}
</style>
<rect id="class-block-maskBG" width="8" height="8" fill="#fff"/>
<rect id="class-block" width="8" height="8" rx="1" ry="1"/>
<mask id="mask-block-solid">
<use xlink:href="#class-block-maskBG"/>
<use xlink:href="#class-block" transform="translate(3 3)" fill="#000"/>
</mask>
<g id="pseudo-class-shape">
<rect x=".5" y=".5" width="7" height="7" rx="1" ry="1" mask="url(#mask-block-solid)" fill="none" stroke="currentColor" stroke-width="1"/>
<use xlink:href="#class-block" mask="url(#mask-block-solid)" fill="currentColor" fill-opacity=".4"/>
<use xlink:href="#class-block" mask="url(#mask-block-solid)" fill="currentColor" transform="translate(4 4)"/>
<g transform="translate(8 8)" fill="currentColor">
<path d="M2.5,0C2.2,0,2,0.2,2,0.5C2,0.8,2.2,1,2.5,1C2.8,1,3,0.8,3,0.5 C3,0.2,2.8,0,2.5,0z M4.5,0C4.2,0,4,0.2,4,0.5C4,0.8,4.2,1,4.5,1C4.8,1,5,0.8,5,0.5C5,0.2,4.8,0,4.5,0z M0.5,6C0.8,6,1,5.8,1,5.5 C1,5.2,0.8,5,0.5,5C0.2,5,0,5.2,0,5.5C0,5.8,0.2,6,0.5,6z M0.5,4C0.8,4,1,3.8,1,3.5C1,3.2,0.8,3,0.5,3C0.2,3,0,3.2,0,3.5 C0,3.8,0.2,4,0.5,4z M7.5,2C7.2,2,7,2.2,7,2.5C7,2.8,7.2,3,7.5,3C7.8,3,8,2.8,8,2.5C8,2.2,7.8,2,7.5,2z M7.5,4C7.2,4,7,4.2,7,4.5 C7,4.8,7.2,5,7.5,5C7.8,5,8,4.8,8,4.5C8,4.2,7.8,4,7.5,4z M5.5,7C5.2,7,5,7.2,5,7.5C5,7.8,5.2,8,5.5,8C5.8,8,6,7.8,6,7.5 C6,7.2,5.8,7,5.5,7z M3.5,7C3.2,7,3,7.2,3,7.5C3,7.8,3.2,8,3.5,8C3.8,8,4,7.8,4,7.5C4,7.2,3.8,7,3.5,7z M0.5,2C0.8,2,1,1.8,1,1.5v-1 C1,0.2,0.8,0,0.5,0C0.2,0,0,0.2,0,0.5v1C0,1.8,0.2,2,0.5,2z M8,0.5C8,0.2,7.8,0,7.5,0h-1C6.2,0,6,0.2,6,0.5C6,0.8,6.2,1,6.5,1h1 C7.8,1,8,0.8,8,0.5z M7.5,6C7.2,6,7,6.2,7,6.5v1C7,7.8,7.2,8,7.5,8C7.8,8,8,7.8,8,7.5v-1C8,6.2,7.8,6,7.5,6z M1.5,7h-1 C0.2,7,0,7.2,0,7.5C0,7.8,0.2,8,0.5,8h1C1.8,8,2,7.8,2,7.5C2,7.2,1.8,7,1.5,7z"/>
<use xlink:href="#class-block" fill-opacity=".2"/>
</g>
</g>
</defs>
<use xlink:href="#pseudo-class-shape" id="pseudo-class" color="#edf0f1"/>
<use xlink:href="#pseudo-class-shape" id="pseudo-class-checked" color="#3089C9"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -273,3 +273,11 @@
background-image: url("chrome://browser/skin/devtools/add.svg");
background-size: cover;
}
#pseudo-class-panel-toggle::before {
background-image: url("chrome://browser/skin/devtools/pseudo-class.svg#pseudo-class");
background-size: cover;
}
#pseudo-class-panel-toggle[checked]::before {
background-image: url("chrome://browser/skin/devtools/pseudo-class.svg#pseudo-class-checked");
}

View File

@ -368,8 +368,8 @@
/* Searchbox is a div container element for a search input element */
.devtools-searchbox {
display: -moz-box;
-moz-box-flex: 1;
display: flex;
flex: 1;
position: relative;
}

View File

@ -347,6 +347,7 @@ browser.jar:
skin/classic/browser/devtools/add.svg (../shared/devtools/images/add.svg)
skin/classic/browser/devtools/filters.svg (../shared/devtools/filters.svg)
skin/classic/browser/devtools/filter-swatch.svg (../shared/devtools/images/filter-swatch.svg)
skin/classic/browser/devtools/pseudo-class.svg (../shared/devtools/images/pseudo-class.svg)
skin/classic/browser/devtools/controls.png (../shared/devtools/images/controls.png)
skin/classic/browser/devtools/controls@2x.png (../shared/devtools/images/controls@2x.png)
skin/classic/browser/devtools/performance-icons.svg (../shared/devtools/images/performance-icons.svg)
@ -563,6 +564,7 @@ browser.jar:
skin/classic/browser/warning16.png (../shared/warning16.png)
skin/classic/browser/warning16@2x.png (../shared/warning16@2x.png)
../extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/chrome.jar:
% override chrome://browser/skin/page-livemarks.png chrome://browser/skin/feeds/feedIcon16.png
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png
% override chrome://browser/skin/feeds/audioFeedIcon16.png chrome://browser/skin/feeds/feedIcon16.png

Binary file not shown.

Binary file not shown.

View File

@ -96,6 +96,7 @@ http://example.net:80 privileged
http://prefixexample.com:80
https://example.com:443 privileged
https://example.org:443 privileged
https://test1.example.com:443 privileged
https://test2.example.com:443 privileged
https://sub1.test1.example.com:443 privileged

View File

@ -947,6 +947,29 @@ nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int line
return;
}
if (cx.mType == NS_SKIN_LOCATION) {
bool chromeSkinOnly = false;
nsresult rv = chromeuri->SchemeIs("chrome", &chromeSkinOnly);
chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
if (chromeSkinOnly) {
rv = resolveduri->SchemeIs("chrome", &chromeSkinOnly);
chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
}
if (chromeSkinOnly) {
nsAutoCString chromePath, resolvedPath;
chromeuri->GetPath(chromePath);
resolveduri->GetPath(resolvedPath);
chromeSkinOnly = StringBeginsWith(chromePath, NS_LITERAL_CSTRING("/skin/")) &&
StringBeginsWith(resolvedPath, NS_LITERAL_CSTRING("/skin/"));
}
if (!chromeSkinOnly) {
LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
"Cannot register non-chrome://.../skin/ URIs '%s' and '%s' as overrides and/or to be overridden from a skin manifest.",
chrome, resolved);
return;
}
}
if (!CanLoadResource(resolveduri)) {
LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
"Cannot register non-local URI '%s' for an override.", resolved);

View File

@ -247,6 +247,7 @@ nsString* nsContentUtils::sModifierSeparator = nullptr;
bool nsContentUtils::sInitialized = false;
bool nsContentUtils::sIsFullScreenApiEnabled = false;
bool nsContentUtils::sTrustedFullScreenOnly = true;
bool nsContentUtils::sIsCutCopyAllowed = true;
bool nsContentUtils::sIsPerformanceTimingEnabled = false;
bool nsContentUtils::sIsResourceTimingEnabled = false;
bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
@ -514,6 +515,9 @@ nsContentUtils::Init()
Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
"full-screen-api.allow-trusted-requests-only");
Preferences::AddBoolVarCache(&sIsCutCopyAllowed,
"dom.allow_cut_copy", true);
Preferences::AddBoolVarCache(&sIsPerformanceTimingEnabled,
"dom.enable_performance", true);
@ -6632,7 +6636,8 @@ nsContentUtils::IsRequestFullScreenAllowed()
bool
nsContentUtils::IsCutCopyAllowed()
{
return EventStateManager::IsHandlingUserInput() ||
return (!IsCutCopyRestricted() &&
EventStateManager::IsHandlingUserInput()) ||
IsCallerChrome();
}

View File

@ -1863,6 +1863,15 @@ public:
*/
static bool IsRequestFullScreenAllowed();
/**
* Returns true if calling execCommand with 'cut' or 'copy' arguments
* is restricted to chrome code.
*/
static bool IsCutCopyRestricted()
{
return !sIsCutCopyAllowed;
}
/**
* Returns true if calling execCommand with 'cut' or 'copy' arguments is
* allowed in the current context. These are only allowed if the user initiated
@ -2434,6 +2443,7 @@ private:
static bool sAllowXULXBL_for_file;
static bool sIsFullScreenApiEnabled;
static bool sTrustedFullScreenOnly;
static bool sIsCutCopyAllowed;
static uint32_t sHandlingInputTimeout;
static bool sIsPerformanceTimingEnabled;
static bool sIsResourceTimingEnabled;

View File

@ -29,11 +29,11 @@ namespace dom {
namespace cache {
namespace db {
const int32_t kMaxWipeSchemaVersion = 10;
const int32_t kMaxWipeSchemaVersion = 11;
namespace {
const int32_t kLatestSchemaVersion = 10;
const int32_t kLatestSchemaVersion = 11;
const int32_t kMaxEntriesPerStatement = 255;
const uint32_t kPageSize = 4 * 1024;
@ -301,6 +301,10 @@ CreateSchema(mozIStorageConnection* aConn)
"response_headers_guard INTEGER NOT NULL, "
"response_body_id TEXT NULL, "
"response_security_info_id INTEGER NULL REFERENCES security_info(id), "
"response_redirected INTEGER NOT NULL, "
// Note that response_redirected_url is either going to be empty, or
// it's going to be a URL different than response_url.
"response_redirected_url TEXT NOT NULL, "
"cache_id INTEGER NOT NULL REFERENCES caches(id) ON DELETE CASCADE"
");"
));
@ -1468,6 +1472,8 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
"response_headers_guard, "
"response_body_id, "
"response_security_info_id, "
"response_redirected, "
"response_redirected_url, "
"cache_id "
") VALUES ("
":request_method, "
@ -1488,6 +1494,8 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
":response_headers_guard, "
":response_body_id, "
":response_security_info_id, "
":response_redirected, "
":response_redirected_url, "
":cache_id "
");"
), getter_AddRefs(state));
@ -1567,6 +1575,14 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
}
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("response_redirected"),
aResponse.channelInfo().redirected() ? 1 : 0);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("response_redirected_url"),
aResponse.channelInfo().redirectedURI());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1658,6 +1674,8 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
"entries.response_status_text, "
"entries.response_headers_guard, "
"entries.response_body_id, "
"entries.response_redirected, "
"entries.response_redirected_url, "
"security_info.data "
"FROM entries "
"LEFT OUTER JOIN security_info "
@ -1705,7 +1723,15 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
}
rv = state->GetBlobAsUTF8String(6, aSavedResponseOut->mValue.channelInfo().securityInfo());
int32_t redirected;
rv = state->GetInt32(6, &redirected);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
aSavedResponseOut->mValue.channelInfo().redirected() = !!redirected;
rv = state->GetUTF8String(7, aSavedResponseOut->mValue.channelInfo().redirectedURI());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->GetBlobAsUTF8String(8, aSavedResponseOut->mValue.channelInfo().securityInfo());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(

View File

@ -13,6 +13,7 @@
#include "nsContentUtils.h"
#include "nsCopySupport.h"
#include "nsFocusManager.h"
#include "nsFontMetrics.h"
#include "nsFrameSelection.h"
#include "nsIContentIterator.h"
#include "nsIPresShell.h"
@ -1081,18 +1082,44 @@ ContentEventHandler::OnQueryCaretRect(WidgetQueryContentEvent* aEvent)
rv = frame->GetPointFromOffset(range->StartOffset(), &posInFrame);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mReply.mWritingMode = frame->GetWritingMode();
bool isVertical = aEvent->mReply.mWritingMode.IsVertical();
nsRect rect;
rect.x = posInFrame.x;
rect.y = posInFrame.y;
rect.width = caretRect.width;
rect.height = frame->GetSize().height;
nscoord fontHeight = 0;
float inflation = nsLayoutUtils::FontSizeInflationFor(frame);
nsRefPtr<nsFontMetrics> fontMetrics;
rv = nsLayoutUtils::GetFontMetricsForFrame(frame, getter_AddRefs(fontMetrics),
inflation);
if (NS_WARN_IF(!fontMetrics)) {
// If we cannot get font height, use frame size instead.
fontHeight = isVertical ? frame->GetSize().width : frame->GetSize().height;
} else {
fontHeight = fontMetrics->MaxAscent() + fontMetrics->MaxDescent();
}
if (isVertical) {
rect.width = fontHeight;
rect.height = caretRect.height;
} else {
rect.width = caretRect.width;
rect.height = fontHeight;
}
rv = ConvertToRootViewRelativeOffset(frame, rect);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
aEvent->mReply.mWritingMode = frame->GetWritingMode();
// If the caret rect is empty, let's make it non-empty rect.
if (!aEvent->mReply.mRect.width) {
aEvent->mReply.mRect.width = 1;
}
if (!aEvent->mReply.mRect.height) {
aEvent->mReply.mRect.height = 1;
}
aEvent->mSucceeded = true;
return NS_OK;
}

View File

@ -13,6 +13,7 @@
#include "mozilla/ipc/ChannelInfo.h"
#include "nsIJARChannel.h"
#include "nsJARChannel.h"
#include "nsNetUtil.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -20,6 +21,7 @@ using namespace mozilla::dom;
void
ChannelInfo::InitFromChannel(nsIChannel* aChannel)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
nsCOMPtr<nsISupports> securityInfo;
@ -28,6 +30,20 @@ ChannelInfo::InitFromChannel(nsIChannel* aChannel)
SetSecurityInfo(securityInfo);
}
nsLoadFlags loadFlags = 0;
aChannel->GetLoadFlags(&loadFlags);
mRedirected = (loadFlags & nsIChannel::LOAD_REPLACE);
if (mRedirected) {
// Save the spec and not the nsIURI object itself, since those objects are
// not thread-safe, and releasing them somewhere other than the main thread
// is not possible.
nsCOMPtr<nsIURI> redirectedURI;
aChannel->GetURI(getter_AddRefs(redirectedURI));
if (redirectedURI) {
redirectedURI->GetSpec(mRedirectedURISpec);
}
}
mInited = true;
}
@ -37,6 +53,8 @@ ChannelInfo::InitFromIPCChannelInfo(const ipc::IPCChannelInfo& aChannelInfo)
MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
mSecurityInfo = aChannelInfo.securityInfo();
mRedirectedURISpec = aChannelInfo.redirectedURI();
mRedirected = aChannelInfo.redirected();
mInited = true;
}
@ -56,16 +74,22 @@ ChannelInfo::SetSecurityInfo(nsISupports* aSecurityInfo)
nsresult
ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mInited);
// These pointers may be null at this point. They must be checked before
// being dereferenced.
nsCOMPtr<nsIHttpChannel> httpChannel =
do_QueryInterface(aChannel);
nsCOMPtr<nsIJARChannel> jarChannel =
do_QueryInterface(aChannel);
if (!mSecurityInfo.IsEmpty()) {
nsCOMPtr<nsISupports> infoObj;
nsresult rv = NS_DeserializeObject(mSecurityInfo, getter_AddRefs(infoObj));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIHttpChannel> httpChannel =
do_QueryInterface(aChannel);
if (httpChannel) {
net::HttpBaseChannel* httpBaseChannel =
static_cast<net::HttpBaseChannel*>(httpChannel.get());
@ -74,8 +98,6 @@ ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel)
return rv;
}
} else {
nsCOMPtr<nsIJARChannel> jarChannel =
do_QueryInterface(aChannel);
if (NS_WARN_IF(!jarChannel)) {
return NS_ERROR_FAILURE;
}
@ -84,6 +106,30 @@ ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel)
}
}
if (mRedirected) {
nsLoadFlags flags = 0;
aChannel->GetLoadFlags(&flags);
flags |= nsIChannel::LOAD_REPLACE;
aChannel->SetLoadFlags(flags);
nsCOMPtr<nsIURI> redirectedURI;
nsresult rv = NS_NewURI(getter_AddRefs(redirectedURI),
mRedirectedURISpec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (httpChannel) {
net::HttpBaseChannel* httpBaseChannel =
static_cast<net::HttpBaseChannel*>(httpChannel.get());
httpBaseChannel->OverrideURI(redirectedURI);
} else {
if (NS_WARN_IF(!jarChannel)) {
return NS_ERROR_FAILURE;
}
static_cast<nsJARChannel*>(jarChannel.get())->OverrideURI(redirectedURI);
}
}
return NS_OK;
}
@ -98,6 +144,8 @@ ChannelInfo::AsIPCChannelInfo() const
IPCChannelInfo ipcInfo;
ipcInfo.securityInfo() = mSecurityInfo;
ipcInfo.redirectedURI() = mRedirectedURISpec;
ipcInfo.redirected() = mRedirected;
return ipcInfo;
}

View File

@ -8,8 +8,10 @@
#define mozilla_dom_ChannelInfo_h
#include "nsString.h"
#include "nsCOMPtr.h"
class nsIChannel;
class nsIURI;
namespace mozilla {
namespace ipc {
@ -42,12 +44,15 @@ public:
ChannelInfo()
: mInited(false)
, mRedirected(false)
{
}
ChannelInfo(const ChannelInfo& aRHS)
: mSecurityInfo(aRHS.mSecurityInfo)
, mRedirectedURISpec(aRHS.mRedirectedURISpec)
, mInited(aRHS.mInited)
, mRedirected(aRHS.mRedirected)
{
}
@ -55,7 +60,9 @@ public:
operator=(const ChannelInfo& aRHS)
{
mSecurityInfo = aRHS.mSecurityInfo;
mRedirectedURISpec = aRHS.mRedirectedURISpec;
mInited = aRHS.mInited;
mRedirected = aRHS.mRedirected;
return *this;
}
@ -78,7 +85,9 @@ private:
private:
nsCString mSecurityInfo;
nsCString mRedirectedURISpec;
bool mInited;
bool mRedirected;
};
} // namespace dom

View File

@ -8,6 +8,8 @@ namespace ipc {
struct IPCChannelInfo
{
nsCString securityInfo;
nsCString redirectedURI;
bool redirected;
};
} // namespace ipc

View File

@ -85,7 +85,10 @@ class ImageLoadTask : public nsRunnable
public:
explicit ImageLoadTask(HTMLImageElement *aElement) :
mElement(aElement)
{}
{
mDocument = aElement->OwnerDoc();
mDocument->BlockOnload();
}
NS_IMETHOD Run()
{
@ -93,12 +96,14 @@ public:
mElement->mPendingImageLoadTask = nullptr;
mElement->LoadSelectedImage(true, true);
}
mDocument->UnblockOnload(false);
return NS_OK;
}
private:
~ImageLoadTask() {}
nsRefPtr<HTMLImageElement> mElement;
nsCOMPtr<nsIDocument> mDocument;
};
HTMLImageElement::HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)

View File

@ -3569,12 +3569,22 @@ nsHTMLDocument::QueryCommandSupported(const nsAString & commandID,
bool
nsHTMLDocument::QueryCommandSupported(const nsAString& commandID)
{
// Gecko technically supports the paste command, but non-privileged content
// will be unable to call it. For that reason, we report that paste is
// not supported to this non-privileged content (as it effectively is).
bool restricted = commandID.LowerCaseEqualsLiteral("paste");
if (restricted && !nsContentUtils::IsCallerChrome()) {
return false;
// Gecko technically supports all the clipboard commands including
// cut/copy/paste, but non-privileged content will be unable to call
// paste, and depending on the pref "dom.allow_cut_copy", cut and copy
// may also be disallowed to be called from non-privileged content.
// For that reason, we report the support status of corresponding
// command accordingly.
if (!nsContentUtils::IsCallerChrome()) {
if (commandID.LowerCaseEqualsLiteral("paste")) {
return false;
}
if (nsContentUtils::IsCutCopyRestricted()) {
if (commandID.LowerCaseEqualsLiteral("cut") ||
commandID.LowerCaseEqualsLiteral("copy")) {
return false;
}
}
}
// commandID is supported if it can be converted to a Midas command

View File

@ -594,5 +594,4 @@ support-files = file_bug871161-1.html file_bug871161-2.html
[test_window_open_close.html]
skip-if = buildapp == 'b2g' # bug 1129014
[test_img_complete.html]
[test_viewport_resize.html]
skip-if = os == 'win' || os == 'mac' # bug 1163911
[test_viewport_resize.html]

View File

@ -16,6 +16,7 @@
#include "mozilla/Mutex.h"
#include "mozilla/dom/Date.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/DetailedPromise.h"
#include "mozilla/dom/MediaKeySessionBinding.h"
#include "mozilla/dom/MediaKeysBinding.h"
#include "mozilla/dom/MediaKeyMessageEventBinding.h"

View File

@ -104,3 +104,4 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet'
[test_bug1012662_editor.html]
[test_bug1012662_noeditor.html]
[test_bug1161721.html]
[test_bug1170911.html]

View File

@ -0,0 +1,90 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1012662
-->
<head>
<title>Test for Bug 1170911</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1170911">Mozilla Bug 1170911</a>
<p id="display"></p>
<div id="content">
<textarea>textarea text</textarea>
</div>
<pre id="test">
<script>
const TEXTAREA = document.querySelector('textarea');
const TEXTAREA_VALUE = TEXTAREA.value;
function doTest() {
is(document.queryCommandSupported("copy"), false,
"Copy support should have been disabled");
is(document.queryCommandSupported("cut"), false,
"Cut support should have been disabled");
document.addEventListener("keydown", tryCopy);
synthesizeKey("Q", {});
}
function tryCopy(evt) {
evt.preventDefault();
document.removeEventListener("keydown", tryCopy);
TEXTAREA.setSelectionRange(0, TEXTAREA_VALUE.length);
TEXTAREA.focus();
SimpleTest.waitForClipboard(null, function () {
is(document.queryCommandEnabled("copy"), false,
"Copy should not be allowed when dom.allow_cut_copy is off");
is(document.execCommand("copy"), false,
"Copy should not be executed when dom.allow_cut_copy is off");
is(TEXTAREA.value, TEXTAREA_VALUE,
"Content in the textarea shouldn't be changed");
TEXTAREA.value = TEXTAREA_VALUE;
},
/* success fn */ SimpleTest.finish,
/* failure fn */ function () {
document.addEventListener("keydown", tryCut);
synthesizeKey("Q", {});
},
/* flavor */ undefined,
/* timeout */ undefined,
/* expect failure */ true);
}
function tryCut(evt) {
evt.preventDefault();
document.removeEventListener("keydown", tryCut);
TEXTAREA.setSelectionRange(0, TEXTAREA_VALUE.length);
TEXTAREA.focus();
SimpleTest.waitForClipboard(null, function () {
is(document.queryCommandEnabled("cut"), false,
"Cut should not be allowed when dom.allow_cut_copy is off");
is(document.execCommand("cut"), false,
"Cut should not be executed when dom.allow_cut_copy is off");
is(TEXTAREA.value, TEXTAREA_VALUE,
"Content in the textarea shouldn't be changed");
},
/* success fn */ SimpleTest.finish,
/* failure fn */ SimpleTest.finish,
/* flavor */ undefined,
/* timeout */ undefined,
/* expect failure */ true);
}
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(() => {
SpecialPowers.pushPrefEnv({"set": [["dom.allow_cut_copy", false]]}, doTest);
});
</script>
</pre>
</body>
</html>

View File

@ -917,11 +917,11 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"Selection",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "ServiceWorker", disabled: true, b2g: false},
{name: "ServiceWorker", release: false, b2g: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "ServiceWorkerContainer", disabled: true, b2g: false},
{name: "ServiceWorkerContainer", release: false, b2g: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "ServiceWorkerRegistration", disabled: true, b2g: false},
{name: "ServiceWorkerRegistration", release: false, b2g: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
"SettingsLock",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -17,6 +17,10 @@ function runTests() {
return testFetchAppResource('test_custom_content_type',
'customContentType', 'text/html');
})
.then(testRedirectedResponse)
.then(testRedirectedHttpsResponse)
.then(testCachedRedirectedResponse)
.then(testCachedRedirectedHttpsResponse)
.then(done);
}
</script>

View File

@ -0,0 +1,2 @@
<!DOCTYPE html>
real index

View File

@ -0,0 +1 @@
Access-Control-Allow-Origin: *

View File

@ -0,0 +1,5 @@
function handleRequest(request, response) {
response.setStatusLine(null, 308, "Permanent Redirect");
response.setHeader("Access-Control-Allow-Origin", "*", false);
response.setHeader("Location", "https://example.org/tests/dom/workers/test/serviceworkers/app-protocol/realindex.html", false);
}

View File

@ -0,0 +1,5 @@
function handleRequest(request, response) {
response.setStatusLine(null, 308, "Permanent Redirect");
response.setHeader("Access-Control-Allow-Origin", "*", false);
response.setHeader("Location", "http://example.org/tests/dom/workers/test/serviceworkers/app-protocol/realindex.html", false);
}

View File

@ -1,3 +1,20 @@
const kHTTPRedirect = "http://example.com/tests/dom/workers/test/serviceworkers/app-protocol/redirect.sjs";
const kHTTPSRedirect = "https://example.com/tests/dom/workers/test/serviceworkers/app-protocol/redirect-https.sjs";
self.addEventListener('install', (event) => {
event.waitUntil(
self.caches.open("origin-app-cache")
.then(c => {
return Promise.all(
[
c.add(kHTTPRedirect),
c.add(kHTTPSRedirect),
]
);
})
);
});
self.addEventListener('fetch', (event) => {
if (event.request.url.indexOf('foo.txt') >= 0) {
event.respondWith(new Response('swresponse', {
@ -17,4 +34,30 @@ self.addEventListener('fetch', (event) => {
headers: {'Content-Type': 'text/html'}
}));
}
if (event.request.url.indexOf('redirected.html') >= 0) {
event.respondWith(fetch(kHTTPRedirect));
}
if (event.request.url.indexOf('redirected-https.html') >= 0) {
event.respondWith(fetch(kHTTPSRedirect));
}
if (event.request.url.indexOf('redirected-cached.html') >= 0) {
event.respondWith(
self.caches.open("origin-app-cache")
.then(c => {
return c.match(kHTTPRedirect);
})
);
}
if (event.request.url.indexOf('redirected-https-cached.html') >= 0) {
event.respondWith(
self.caches.open("origin-app-cache")
.then(c => {
return c.match(kHTTPSRedirect);
})
);
}
});

View File

@ -37,3 +37,36 @@ function testFetchAppResource(aUrl,
});
});
}
function testRedirectedResponse() {
return testRedirectedResponseWorker("redirected", "IFRAMELOADED");
}
function testRedirectedHttpsResponse() {
return testRedirectedResponseWorker("redirected-https", "HTTPSIFRAMELOADED");
}
function testCachedRedirectedResponse() {
return testRedirectedResponseWorker("redirected-cached", "IFRAMELOADED");
}
function testCachedRedirectedHttpsResponse() {
return testRedirectedResponseWorker("redirected-https-cached", "HTTPSIFRAMELOADED");
}
function testRedirectedResponseWorker(aFrameId, aAlert) {
// Because of the CSP policies applied to privileged apps, we cannot run
// inline script inside realindex.html, and loading a script from the app://
// URI is also not an option, so we let the parent iframe which has access
// to the SpecialPowers API use those privileges to access the document.
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.src = aFrameId + ".html";
iframe.id = aFrameId;
return new Promise(resolve => {
iframe.addEventListener("load", event => {
alert(aAlert);
resolve();
}, false);
});
}

View File

@ -0,0 +1,4 @@
function handleRequest(request, response) {
response.setStatusLine(null, 308, "Permanent Redirect");
response.setHeader("Location", "https://example.org/tests/dom/workers/test/serviceworkers/fetch/origin/https/realindex.html", false);
}

View File

@ -0,0 +1,23 @@
var prefix = "/tests/dom/workers/test/serviceworkers/fetch/origin/https/";
self.addEventListener("install", function(event) {
event.waitUntil(
self.caches.open("origin-cache")
.then(c => {
return c.add(prefix + 'index-https.sjs');
})
);
});
self.addEventListener("fetch", function(event) {
if (event.request.url.indexOf("index-cached-https.sjs") >= 0) {
event.respondWith(
self.caches.open("origin-cache")
.then(c => {
return c.match(prefix + 'index-https.sjs');
})
);
} else {
event.respondWith(fetch(event.request));
}
});

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<script>
window.opener.postMessage({status: "domain", data: document.domain}, "*");
window.opener.postMessage({status: "origin", data: location.origin}, "*");
window.opener.postMessage({status: "done"}, "*");
</script>

View File

@ -0,0 +1 @@
Access-Control-Allow-Origin: https://example.com

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<script>
function ok(v, msg) {
window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
}
function done(reg) {
ok(reg.active, "The active worker should be available.");
window.parent.postMessage({status: "registrationdone"}, "*");
}
navigator.serviceWorker.ready.then(done);
navigator.serviceWorker.register("origin_test.js", {scope: "."});
</script>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<script>
navigator.serviceWorker.getRegistration(".").then(function(registration) {
registration.unregister().then(function(success) {
if (success) {
window.parent.postMessage({status: "unregistrationdone"}, "*");
}
}, function(e) {
dump("Unregistering the SW failed with " + e + "\n");
});
});
</script>

View File

@ -0,0 +1,4 @@
function handleRequest(request, response) {
response.setStatusLine(null, 308, "Permanent Redirect");
response.setHeader("Location", "https://example.org/tests/dom/workers/test/serviceworkers/fetch/origin/realindex.html", false);
}

View File

@ -0,0 +1,4 @@
function handleRequest(request, response) {
response.setStatusLine(null, 308, "Permanent Redirect");
response.setHeader("Location", "http://example.org/tests/dom/workers/test/serviceworkers/fetch/origin/realindex.html", false);
}

View File

@ -0,0 +1,35 @@
var prefix = "/tests/dom/workers/test/serviceworkers/fetch/origin/";
self.addEventListener("install", function(event) {
event.waitUntil(
self.caches.open("origin-cache")
.then(c => {
return Promise.all(
[
c.add(prefix + 'index.sjs'),
c.add(prefix + 'index-to-https.sjs'),
]
);
})
);
});
self.addEventListener("fetch", function(event) {
if (event.request.url.indexOf("index-cached.sjs") >= 0) {
event.respondWith(
self.caches.open("origin-cache")
.then(c => {
return c.match(prefix + 'index.sjs');
})
);
} else if (event.request.url.indexOf("index-to-https-cached.sjs") >= 0) {
event.respondWith(
self.caches.open("origin-cache")
.then(c => {
return c.match(prefix + 'index-to-https.sjs');
})
);
} else {
event.respondWith(fetch(event.request));
}
});

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<script>
window.opener.postMessage({status: "domain", data: document.domain}, "*");
window.opener.postMessage({status: "origin", data: location.origin}, "*");
window.opener.postMessage({status: "done"}, "*");
</script>

View File

@ -0,0 +1 @@
Access-Control-Allow-Origin: http://mochi.test:8888

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<script>
function ok(v, msg) {
window.parent.postMessage({status: "ok", result: !!v, message: msg}, "*");
}
function done(reg) {
ok(reg.active, "The active worker should be available.");
window.parent.postMessage({status: "registrationdone"}, "*");
}
navigator.serviceWorker.ready.then(done);
navigator.serviceWorker.register("origin_test.js", {scope: "."});
</script>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<script>
navigator.serviceWorker.getRegistration(".").then(function(registration) {
registration.unregister().then(function(success) {
if (success) {
window.parent.postMessage({status: "unregistrationdone"}, "*");
}
}, function(e) {
dump("Unregistering the SW failed with " + e + "\n");
});
});
</script>

View File

@ -47,6 +47,19 @@ support-files =
fetch/https/clonedresponse/register.html
fetch/https/clonedresponse/unregister.html
fetch/https/clonedresponse/https_test.js
fetch/origin/index.sjs
fetch/origin/index-to-https.sjs
fetch/origin/realindex.html
fetch/origin/realindex.html^headers^
fetch/origin/register.html
fetch/origin/unregister.html
fetch/origin/origin_test.js
fetch/origin/https/index-https.sjs
fetch/origin/https/realindex.html
fetch/origin/https/realindex.html^headers^
fetch/origin/https/register.html
fetch/origin/https/unregister.html
fetch/origin/https/origin_test.js
fetch/requesturl/index.html
fetch/requesturl/redirect.sjs
fetch/requesturl/redirector.html
@ -159,3 +172,9 @@ support-files =
[test_skip_waiting.html]
[test_strict_mode_error.html]
[test_cross_origin_url_after_redirect.html]
[test_origin_after_redirect.html]
[test_origin_after_redirect_cached.html]
[test_origin_after_redirect_to_https.html]
[test_origin_after_redirect_to_https_cached.html]
[test_https_origin_after_redirect.html]
[test_https_origin_after_redirect_cached.html]

View File

@ -28,7 +28,8 @@ function setup() {
['dom.mozBrowserFramesEnabled', true],
['dom.serviceWorkers.exemptFromPerDomainMax', true],
['dom.serviceWorkers.enabled', true],
['dom.serviceWorkers.testing.enabled', true]
['dom.serviceWorkers.testing.enabled', true],
['dom.caches.enabled', true],
]}, () => {
SpecialPowers.pushPermissions([
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
@ -103,6 +104,18 @@ function loadControlled() {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/HTTPSIFRAMELOADED/.exec(message)) {
let doc = SpecialPowers.wrap(iframe).contentDocument;
let innerDoc = SpecialPowers.wrap(doc.getElementById("redirected-https").contentDocument);
let innerLocation = innerDoc.defaultView.location;
is(innerDoc.domain, "example.org", "Correct domain expected (https)");
is(innerLocation.origin, "https://example.org", "Correct origin expected (https)");
} else if (/IFRAMELOADED/.exec(message)) {
let doc = SpecialPowers.wrap(iframe).contentDocument;
let innerDoc = SpecialPowers.wrap(doc.getElementById("redirected").contentDocument);
let innerLocation = innerDoc.defaultView.location;
is(innerDoc.domain, "example.org", "Correct domain expected");
is(innerLocation.origin, "http://example.org", "Correct origin expected");
} else if (/DONE/.exec(message)) {
ok(true, "Messaging from app complete");
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);

View File

@ -0,0 +1,56 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test the origin of a redirected response from a service worker</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/origin/https/register.html";
var win;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
win = window.open("https://example.com/tests/dom/workers/test/serviceworkers/fetch/origin/https/index-https.sjs", "mywindow", "width=100,height=100");
} else if (e.data.status == "domain") {
is(e.data.data, "example.org", "Correct domain expected");
} else if (e.data.status == "origin") {
is(e.data.data, "https://example.org", "Correct origin expected");
} else if (e.data.status == "done") {
win.close();
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/origin/https/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.caches.enabled", true],
]}, runTest);
};
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test the origin of a redirected response from a service worker</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/origin/https/register.html";
var win;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
win = window.open("https://example.com/tests/dom/workers/test/serviceworkers/fetch/origin/https/index-cached-https.sjs", "mywindow", "width=100,height=100");
} else if (e.data.status == "domain") {
is(e.data.data, "example.org", "Correct domain expected");
} else if (e.data.status == "origin") {
is(e.data.data, "https://example.org", "Correct origin expected");
} else if (e.data.status == "done") {
win.close();
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/origin/https/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.caches.enabled", true],
]}, runTest);
};
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test the origin of a redirected response from a service worker</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/register.html";
var win;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
win = window.open("/tests/dom/workers/test/serviceworkers/fetch/origin/index.sjs", "mywindow", "width=100,height=100");
} else if (e.data.status == "domain") {
is(e.data.data, "example.org", "Correct domain expected");
} else if (e.data.status == "origin") {
is(e.data.data, "http://example.org", "Correct origin expected");
} else if (e.data.status == "done") {
win.close();
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.caches.enabled", true],
]}, runTest);
};
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test the origin of a redirected response from a service worker</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/register.html";
var win;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
win = window.open("/tests/dom/workers/test/serviceworkers/fetch/origin/index-cached.sjs", "mywindow", "width=100,height=100");
} else if (e.data.status == "domain") {
is(e.data.data, "example.org", "Correct domain expected");
} else if (e.data.status == "origin") {
is(e.data.data, "http://example.org", "Correct origin expected");
} else if (e.data.status == "done") {
win.close();
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.caches.enabled", true],
]}, runTest);
};
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test the origin of a redirected response from a service worker</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/register.html";
var win;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
win = window.open("/tests/dom/workers/test/serviceworkers/fetch/origin/index-to-https.sjs", "mywindow", "width=100,height=100");
} else if (e.data.status == "domain") {
is(e.data.data, "example.org", "Correct domain expected");
} else if (e.data.status == "origin") {
is(e.data.data, "https://example.org", "Correct origin expected");
} else if (e.data.status == "done") {
win.close();
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.caches.enabled", true],
]}, runTest);
};
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test the origin of a redirected response from a service worker</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var iframe;
function runTest() {
iframe = document.querySelector("iframe");
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/register.html";
var win;
window.onmessage = function(e) {
if (e.data.status == "ok") {
ok(e.data.result, e.data.message);
} else if (e.data.status == "registrationdone") {
win = window.open("/tests/dom/workers/test/serviceworkers/fetch/origin/index-to-https-cached.sjs", "mywindow", "width=100,height=100");
} else if (e.data.status == "domain") {
is(e.data.data, "example.org", "Correct domain expected");
} else if (e.data.status == "origin") {
is(e.data.data, "https://example.org", "Correct origin expected");
} else if (e.data.status == "done") {
win.close();
iframe.src = "/tests/dom/workers/test/serviceworkers/fetch/origin/unregister.html";
} else if (e.data.status == "unregistrationdone") {
window.onmessage = null;
ok(true, "Test finished successfully");
SimpleTest.finish();
}
};
}
SimpleTest.waitForExplicitFinish();
onload = function() {
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.caches.enabled", true],
]}, runTest);
};
</script>
</pre>
</body>
</html>

View File

@ -157,7 +157,7 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"Response",
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "ServiceWorkerRegistration", disabled: true, b2g: false },
{ name: "ServiceWorkerRegistration", release: false, b2g: false },
// IMPORTANT: Do not change this list without review from a DOM peer!
"TextDecoder",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -2246,7 +2246,7 @@ gfxPlatform::OptimalFormatForContent(gfxContentType aContent)
*/
static bool sLayersSupportsD3D9 = false;
static bool sLayersSupportsD3D11 = false;
static bool sANGLESupportsD3D11 = false;
bool gANGLESupportsD3D11 = false;
static bool sLayersSupportsHardwareVideoDecoding = false;
static bool sLayersHardwareVideoDecodingFailed = false;
static bool sBufferRotationCheckPref = true;
@ -2291,7 +2291,7 @@ InitLayersAccelerationPrefs()
}
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, &status))) {
if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
sANGLESupportsD3D11 = true;
gANGLESupportsD3D11 = true;
}
}
}
@ -2347,7 +2347,7 @@ bool
gfxPlatform::CanUseDirect3D11ANGLE()
{
MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
return sANGLESupportsD3D11;
return gANGLESupportsD3D11;
}

View File

@ -131,6 +131,8 @@ enum eGfxLog {
// when searching through pref langs, max number of pref langs
const uint32_t kMaxLenPrefLangList = 32;
extern bool gANGLESupportsD3D11;
#define UNINITIALIZED_VALUE (-1)
inline const char*

View File

@ -577,7 +577,12 @@ static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
mozilla::TimeStamp previousVsync = display->mPreviousTimestamp;
display->mPreviousTimestamp = nextVsync;
mozilla::TimeStamp now = TimeStamp::Now();
MOZ_ASSERT(nextVsync > previousVsync);
if (nextVsync <= previousVsync) {
TimeDuration next = nextVsync - now;
TimeDuration prev = now - previousVsync;
printf_stderr("Next from now: %f, prev from now: %f\n", next.ToMilliseconds(), prev.ToMilliseconds());
MOZ_ASSERT(false, "Next vsync less than previous vsync\n");
}
// Bug 1158321 - The VsyncCallback can sometimes execute before the reported
// vsync time. In those cases, normalize the timestamp to Now() as sending

View File

@ -1718,12 +1718,14 @@ bool DoesD3D11DeviceWork(ID3D11Device *device)
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: could not parse version\n"));
#endif
gANGLESupportsD3D11 = false;
return false;
}
if (displayLinkModuleVersion <= V(8,6,1,36484)) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: too old version\n"));
#endif
gANGLESupportsD3D11 = false;
return false;
}
}

View File

@ -6,15 +6,19 @@ const expectedString = "Hello\nWorld";
function run_test() {
var failures = false;
var encodingConverter = CreateScriptableConverter();
var decoders = [
var encoders = [
"Big5",
"Big5-HKSCS",
"EUC-JP",
"EUC-KR",
"gb18030",
"gbk",
"IBM866",
"ISO-2022-JP",
"ISO-8859-1",
"ISO-8859-2",
"ISO-8859-3",
"ISO-8859-4",
"ISO-8859-5",
@ -27,7 +31,6 @@ function run_test() {
"ISO-8859-14",
"ISO-8859-15",
"ISO-8859-16",
"ISO-8859-2",
"KOI8-R",
"KOI8-U",
"Shift_JIS",
@ -41,23 +44,18 @@ function run_test() {
"windows-1257",
"windows-1258",
"windows-874",
"macintosh",
"x-mac-cyrillic",
"x-user-defined",
"UTF-8"
];
var counter = 0;
while (counter < decoders.length) {
++counter;
var charset = decoders[counter];
while (counter < encoders.length) {
var charset = encoders[counter++];
dump("testing " + counter + " " + charset + "\n");
try {
encodingConverter.charset = charset;
} catch(e) {
dump("Warning: couldn't set encoder charset to " + charset + "\n");
continue;
}
encodingConverter.charset = charset;
var codepageString = encodingConverter.ConvertFromUnicode(inString) +
encodingConverter.Finish();
if (codepageString != expectedString) {

View File

@ -4,6 +4,7 @@ load('CharsetConversionTests.js');
function run_test() {
var failures = false;
var decodingConverter = CreateScriptableConverter();
var decoders = [
"Big5",
@ -13,6 +14,8 @@ function run_test() {
"gb18030",
"IBM866",
"ISO-2022-JP",
"ISO-8859-1",
"ISO-8859-2",
"ISO-8859-3",
"ISO-8859-4",
"ISO-8859-5",
@ -25,7 +28,6 @@ function run_test() {
"ISO-8859-14",
"ISO-8859-15",
"ISO-8859-16",
"ISO-8859-2",
"KOI8-R",
"KOI8-U",
"Shift_JIS",
@ -39,22 +41,18 @@ function run_test() {
"windows-1257",
"windows-1258",
"windows-874",
"macintosh",
"x-mac-cyrillic",
"x-user-defined",
"UTF-8"
];
var counter = 0;
while (counter < decoders.length) {
++counter;
var charset = decoders[counter];
var charset = decoders[counter++];
dump("testing " + counter + " " + charset + "\n");
try {
decodingConverter.charset = charset;
} catch(e) {
dump("Warning: couldn't set decoder charset to " + charset + "\n");
continue;
}
decodingConverter.charset = charset;
for (var i = 0x80; i < 0x100; ++i) {
var inString = String.fromCharCode(i);
var outString;

View File

@ -6,7 +6,7 @@ load('CharsetConversionTests.js');
const inString = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u20AC\u4E02\u4E04\u4E05\u4E06\u4E0F\u4E12\u4E17\u4E1F\u4E20\u4E21\u4E23\u4E26\u4E29\u4E2E\u4E2F\u4E31\u4E33\u4E35\u4E37\u4E3C\u4E40\u4E41\u4E42\u4E44\u4E46\u4E4A\u4E51\u4E55\u4E57\u4E5A\u4E5B\u4E62\u4E63\u4E64\u4E65\u4E67\u4E68\u4E6A\u4E6B\u4E6C\u4E6D\u4E6E\u4E6F\u4E72\u4E74\u4E75\u4E76\u4E77\u4E78\u4E79\u4E7A\u4E7B\u4E7C\u4E7D\u4E7F\u4E80\u4E81\u4E82\u4E83\u4E84\u4E85\u4E87\u4E8A\uFFFD";
const expectedString = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x80\x81@\x81A\x81B\x81C\x81D\x81E\x81F\x81G\x81H\x81I\x81J\x81K\x81L\x81M\x81N\x81O\x81P\x81Q\x81R\x81S\x81T\x81U\x81V\x81W\x81X\x81Y\x81Z\x81[\x81\\\x81]\x81^\x81_\x81`\x81a\x81b\x81c\x81d\x81e\x81f\x81g\x81h\x81i\x81j\x81k\x81l\x81m\x81n\x81o\x81p\x81q\x81r\x81s\x81t\x81u\x81v\x81w\x81x\x81y\x81z\x81{\x81|\x81}\x81~";
const expectedString = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x80\x81@\x81A\x81B\x81C\x81D\x81E\x81F\x81G\x81H\x81I\x81J\x81K\x81L\x81M\x81N\x81O\x81P\x81Q\x81R\x81S\x81T\x81U\x81V\x81W\x81X\x81Y\x81Z\x81[\x81\\\x81]\x81^\x81_\x81`\x81a\x81b\x81c\x81d\x81e\x81f\x81g\x81h\x81i\x81j\x81k\x81l\x81m\x81n\x81o\x81p\x81q\x81r\x81s\x81t\x81u\x81v\x81w\x81x\x81y\x81z\x81{\x81|\x81}\x81~?";
const aliases = [ "gbk", "x-gbk" ];

View File

@ -0,0 +1,77 @@
// Tests encoding of unmapped characters
load('CharsetConversionTests.js');
const inString = "\u2764";
const expectedString = "?";
function run_test() {
var failures = false;
var encodingConverter = CreateScriptableConverter();
// this list excludes codepages that can represent all Unicode
var encoders = [
"Big5",
"Big5-HKSCS",
"EUC-JP",
"EUC-KR",
"gbk",
"IBM866",
"ISO-2022-JP",
"ISO-8859-3",
"ISO-8859-4",
"ISO-8859-5",
"ISO-8859-6",
"ISO-8859-7",
"ISO-8859-8",
"ISO-8859-8-I",
"ISO-8859-10",
"ISO-8859-13",
"ISO-8859-14",
"ISO-8859-15",
"ISO-8859-16",
"ISO-8859-2",
"KOI8-R",
"KOI8-U",
"Shift_JIS",
"windows-1250",
"windows-1251",
"windows-1252",
"windows-1253",
"windows-1254",
"windows-1255",
"windows-1256",
"windows-1257",
"windows-1258",
"windows-874",
"x-mac-cyrillic"
];
var counter = 0;
while (counter < encoders.length) {
var charset = encoders[counter++];
dump("testing " + counter + " " + charset + "\n");
encodingConverter.charset = charset;
var codepageString = encodingConverter.ConvertFromUnicode(inString) +
encodingConverter.Finish();
if (codepageString != expectedString) {
dump(charset + " encoding failed\n");
for (var i = 0; i < expectedString.length; ++i) {
if (i >= codepageString.length) {
dump("output length " + codepageString.length +
" less than expected length " + expectedString.length + "\n");
break;
}
if (codepageString.charAt(i) != expectedString.charAt(i)) {
dump(i.toString(16) + ": 0x" +
codepageString.charCodeAt(i).toString(16) + " != " +
expectedString.charCodeAt(i).toString(16) + "\n");
}
}
failures = true;
}
}
if (failures) {
do_throw("test failed\n");
}
}

View File

@ -120,3 +120,4 @@ support-files =
[test_utf8_illegals.js]
[test_input_stream.js]
[test_bug1008832.js]
[test_unmapped.js]

View File

@ -1,4 +1,4 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -79,30 +79,35 @@ void nsUnicodeToGB18030::Create4BytesEncoder()
m4BytesEncoder = new nsUnicodeTo4BytesGB18030();
}
bool nsUnicodeToGB18030::EncodeSurrogate(
char16_t aSurrogateHigh,
char16_t aSurrogateLow,
char* aOut)
nsresult nsUnicodeToGB18030::EncodeSurrogate(char16_t aSurrogateHigh,
char16_t aSurrogateLow,
char* aOut,
int32_t aDestLength,
int32_t aBufferLength)
{
if( NS_IS_HIGH_SURROGATE(aSurrogateHigh) &&
if( NS_IS_HIGH_SURROGATE(aSurrogateHigh) &&
NS_IS_LOW_SURROGATE(aSurrogateLow) )
{
// notice that idx does not include the 0x10000
// notice that idx does not include the 0x10000
uint32_t idx = ((aSurrogateHigh - (char16_t)0xD800) << 10 ) |
(aSurrogateLow - (char16_t) 0xDC00);
if (aDestLength + 4 > aBufferLength) {
return NS_OK_UENC_MOREOUTPUT;
}
unsigned char *out = (unsigned char*) aOut;
// notice this is from 0x90 for supplment planes
out[0] = (idx / (10*126*10)) + 0x90;
// notice this is from 0x90 for supplementary planes
out[0] = (idx / (10*126*10)) + 0x90;
idx %= (10*126*10);
out[1] = (idx / (10*126)) + 0x30;
idx %= (10*126);
out[2] = (idx / (10)) + 0x81;
out[3] = (idx % 10) + 0x30;
return true;
}
return false;
}
return NS_OK;
}
return NS_ERROR_UENC_NOMAPPING;
}
//----------------------------------------------------------------------
// Class nsUnicodeToGBK [implementation]
@ -122,70 +127,66 @@ void nsUnicodeToGBK::Create4BytesEncoder()
{
m4BytesEncoder = nullptr;
}
bool nsUnicodeToGBK::TryExtensionEncoder(
char16_t aChar,
char* aOut,
int32_t *aOutLen
)
nsresult nsUnicodeToGBK::TryExtensionEncoder(char16_t aChar,
char* aOut,
int32_t *aOutLen)
{
if( NS_IS_HIGH_SURROGATE(aChar) ||
if( NS_IS_HIGH_SURROGATE(aChar) ||
NS_IS_LOW_SURROGATE(aChar) )
{
// performance tune for surrogate characters
return false;
return NS_ERROR_UENC_NOMAPPING;
}
if(! mExtensionEncoder )
CreateExtensionEncoder();
if(mExtensionEncoder)
if(mExtensionEncoder)
{
int32_t len = 1;
nsresult res = NS_OK;
res = mExtensionEncoder->Convert(&aChar, &len, aOut, aOutLen);
if(NS_SUCCEEDED(res) && (*aOutLen > 0))
return true;
return mExtensionEncoder->Convert(&aChar, &len, aOut, aOutLen);
}
return false;
return NS_ERROR_UENC_NOMAPPING;
}
bool nsUnicodeToGBK::Try4BytesEncoder(
nsresult nsUnicodeToGBK::Try4BytesEncoder(
char16_t aChar,
char* aOut,
int32_t *aOutLen
)
{
if( NS_IS_HIGH_SURROGATE(aChar) ||
if( NS_IS_HIGH_SURROGATE(aChar) ||
NS_IS_LOW_SURROGATE(aChar) )
{
// performance tune for surrogate characters
return false;
return NS_ERROR_UENC_NOMAPPING;
}
if(! m4BytesEncoder )
Create4BytesEncoder();
if(m4BytesEncoder)
if(m4BytesEncoder)
{
int32_t len = 1;
nsresult res = NS_OK;
res = m4BytesEncoder->Convert(&aChar, &len, aOut, aOutLen);
NS_ASSERTION(NS_FAILED(res) || ((1 == len) && (4 == *aOutLen)),
"unexpect conversion length");
if(NS_SUCCEEDED(res) && (*aOutLen > 0))
return true;
return res;
}
return false;
return NS_ERROR_UENC_NOMAPPING;
}
bool nsUnicodeToGBK::EncodeSurrogate(
char16_t aSurrogateHigh,
char16_t aSurrogateLow,
char* aOut)
{
return false; // GBK cannot encode Surrogate, let the subclass encode it.
}
NS_IMETHODIMP nsUnicodeToGBK::ConvertNoBuff(
const char16_t * aSrc,
int32_t * aSrcLength,
char * aDest,
int32_t * aDestLength)
nsresult nsUnicodeToGBK::EncodeSurrogate(char16_t aSurrogateHigh,
char16_t aSurrogateLow,
char* aOut,
int32_t aDestLength,
int32_t aBufferLength)
{
return NS_ERROR_UENC_NOMAPPING; // GBK cannot encode Surrogate, let the subclass encode it.
}
NS_IMETHODIMP nsUnicodeToGBK::ConvertNoBuffNoErr(const char16_t * aSrc,
int32_t * aSrcLength,
char * aDest,
int32_t * aDestLength)
{
int32_t iSrcLength = 0;
int32_t iDestLength = 0;
@ -217,59 +218,56 @@ NS_IMETHODIMP nsUnicodeToGBK::ConvertNoBuff(
iDestLength +=2;
} else {
int32_t aOutLen = 2;
// make sure we still have 2 bytes for output first
if(iDestLength+2 > *aDestLength)
{
res = NS_OK_UENC_MOREOUTPUT;
break;
}
// we cannot map in the common mapping. Let's try to
// call the delegated 2 byte converter for the gbk or gb18030
// unique 2 byte mapping
if(TryExtensionEncoder(unicode, aDest, &aOutLen))
{
res = TryExtensionEncoder(unicode, aDest, &aOutLen);
if (res == NS_OK) {
iDestLength += aOutLen;
aDest += aOutLen;
} else if (res == NS_OK_UENC_MOREOUTPUT) {
break;
} else {
// make sure we still have 4 bytes for output first
if(iDestLength+4 > *aDestLength)
{
res = NS_OK_UENC_MOREOUTPUT;
break;
}
// we still cannot map. Let's try to
// call the delegated GB18030 4 byte converter
// call the delegated GB18030 4 byte converter
aOutLen = 4;
if( NS_IS_HIGH_SURROGATE(unicode) )
{
if((iSrcLength+1) < *aSrcLength ) {
if(EncodeSurrogate(aSrc[0],aSrc[1], aDest)) {
res = EncodeSurrogate(aSrc[0],aSrc[1], aDest,
iDestLength, *aDestLength);
if (res == NS_OK) {
// since we got a surrogate pair, we need to increment src.
iSrcLength++ ;
iSrcLength++ ;
aSrc++;
iDestLength += aOutLen;
aDest += aOutLen;
} else {
// only get a high surrogate, but not a low surrogate
res = NS_ERROR_UENC_NOMAPPING;
iSrcLength++; // include length of the unmapped character
if (res == NS_ERROR_UENC_NOMAPPING) {
// only get a high surrogate, but not a low surrogate
iSrcLength++; // include length of the unmapped character
}
break;
}
} else {
mSurrogateHigh = aSrc[0];
res = NS_OK;
break; // this will go to afterwhileloop
}
} else {
if( NS_IS_LOW_SURROGATE(unicode) )
{
if(NS_IS_HIGH_SURROGATE(mSurrogateHigh)) {
if(EncodeSurrogate(mSurrogateHigh, aSrc[0], aDest)) {
res = EncodeSurrogate(mSurrogateHigh, aSrc[0], aDest,
iDestLength, *aDestLength);
if (res == NS_OK) {
iDestLength += aOutLen;
aDest += aOutLen;
} else {
// only get a high surrogate, but not a low surrogate
res = NS_ERROR_UENC_NOMAPPING;
iSrcLength++; // include length of the unmapped character
if (res == NS_ERROR_UENC_NOMAPPING) {
// only get a high surrogate, but not a low surrogate
iSrcLength++; // include length of the unmapped character
}
break;
}
} else {
@ -279,22 +277,23 @@ NS_IMETHODIMP nsUnicodeToGBK::ConvertNoBuff(
break;
}
} else {
if(Try4BytesEncoder(unicode, aDest, &aOutLen))
{
res = Try4BytesEncoder(unicode, aDest, &aOutLen);
if (res == NS_OK) {
NS_ASSERTION((aOutLen == 4), "we should always generate 4 bytes here");
iDestLength += aOutLen;
aDest += aOutLen;
} else {
res = NS_ERROR_UENC_NOMAPPING;
iSrcLength++; // include length of the unmapped character
if (res == NS_ERROR_UENC_NOMAPPING) {
iSrcLength++; // include length of the unmapped character
}
break;
}
}
}
}
}
}
}
iSrcLength++ ; // Each unicode char just count as one in char16_t string;
iSrcLength++ ; // Each unicode char just count as one in char16_t string;
mSurrogateHigh = 0;
aSrc++;
if ( iDestLength >= (*aDestLength) && (iSrcLength < *aSrcLength) )

View File

@ -1,4 +1,4 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -35,16 +35,10 @@ protected:
//--------------------------------------------------------------------
// Subclassing of nsEncoderSupport class [declaration]
NS_IMETHOD ConvertNoBuff(const char16_t * aSrc,
int32_t * aSrcLength,
char * aDest,
int32_t * aDestLength);
NS_IMETHOD ConvertNoBuffNoErr(const char16_t * aSrc, int32_t * aSrcLength,
char * aDest, int32_t * aDestLength)
{
return NS_OK;
} // just make it not abstract;
NS_IMETHOD ConvertNoBuffNoErr(const char16_t * aSrc,
int32_t * aSrcLength,
char * aDest,
int32_t * aDestLength);
virtual void CreateExtensionEncoder();
virtual void Create4BytesEncoder();
@ -54,9 +48,11 @@ protected:
protected:
char16_t mSurrogateHigh;
nsGBKConvUtil mUtil;
bool TryExtensionEncoder(char16_t aChar, char* aDest, int32_t* aOutLen);
bool Try4BytesEncoder(char16_t aChar, char* aDest, int32_t* aOutLen);
virtual bool EncodeSurrogate(char16_t aSurrogateHigh, char16_t aSurrogateLow, char* aDest);
nsresult TryExtensionEncoder(char16_t aChar, char* aDest, int32_t* aOutLen);
nsresult Try4BytesEncoder(char16_t aChar, char* aDest, int32_t* aOutLen);
virtual nsresult EncodeSurrogate(char16_t aSurrogateHigh,
char16_t aSurrogateLow, char* aDest,
int32_t aDestLength, int32_t aBufferLength);
};
class nsUnicodeToGB18030: public nsUnicodeToGBK
@ -67,7 +63,9 @@ public:
protected:
virtual void CreateExtensionEncoder();
virtual void Create4BytesEncoder();
virtual bool EncodeSurrogate(char16_t aSurrogateHigh, char16_t aSurrogateLow, char* aDest);
virtual nsresult EncodeSurrogate(char16_t aSurrogateHigh,
char16_t aSurrogateLow, char* aDest,
int32_t aDestLength, int32_t aBufferLength);
};
#endif /* nsUnicodeToGBK_h___ */

View File

@ -1,145 +0,0 @@
/*
* Header file of Pure API function declarations.
*
* (C) Copyright IBM Corporation. 2006, 2006. All Rights Reserved.
* You may recompile and redistribute these definitions as required.
*
* Version 1.0
*/
#if defined(PURIFY) || defined(QUANTIFY)
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
// Don't include this file directly, use purify.h instead.
// If you need something that's not there, add it.
#ifdef PURIFY_PRIVATE_INCLUDE
#define PURE_H_VERSION 1
#include <stddef.h>
//////////////////////////////
// API's Specific to Purify //
//////////////////////////////
// TRUE when Purify is running.
int __cdecl PurifyIsRunning(void) ;
//
// Print a string to the viewer.
//
int __cdecl PurePrintf(const char *fmt, ...) ;
int __cdecl PurifyPrintf(const char *fmt, ...) ;
//
// Purify functions for leak and memory-in-use functionalty.
//
size_t __cdecl PurifyNewInuse(void) ;
size_t __cdecl PurifyAllInuse(void) ;
size_t __cdecl PurifyClearInuse(void) ;
size_t __cdecl PurifyNewLeaks(void) ;
size_t __cdecl PurifyAllLeaks(void) ;
size_t __cdecl PurifyClearLeaks(void) ;
//
// Purify functions for handle leakage.
//
size_t __cdecl PurifyAllHandlesInuse(void) ;
size_t __cdecl PurifyNewHandlesInuse(void) ;
//
// Functions that tell you about the state of memory.
//
size_t __cdecl PurifyDescribe(void *addr) ;
size_t __cdecl PurifyWhatColors(void *addr, size_t size) ;
//
// Functions to test the state of memory. If the memory is not
// accessable, an error is signaled just as if there were a memory
// reference and the function returns false.
//
int __cdecl PurifyAssertIsReadable(const void *addr, size_t size) ; // size used to be an int, until IA64 came along
int __cdecl PurifyAssertIsWritable(const void *addr, size_t size) ;
//
// Functions to test the state of memory. If the memory is not
// accessable, these functions return false. No error is signaled.
//
int __cdecl PurifyIsReadable(const void *addr, size_t size) ;
int __cdecl PurifyIsWritable(const void *addr, size_t size) ;
int __cdecl PurifyIsInitialized(const void *addr, size_t size) ;
//
// Functions to set the state of memory.
//
void __cdecl PurifyMarkAsInitialized(void *addr, size_t size) ;
void __cdecl PurifyMarkAsUninitialized(void *addr, size_t size) ;
//
// Functions to do late detection of ABWs, FMWs, IPWs.
//
#define PURIFY_HEAP_CRT (HANDLE) ~(__int64) 1 /* 0xfffffffe */
#define PURIFY_HEAP_ALL (HANDLE) ~(__int64) 2 /* 0xfffffffd */
#define PURIFY_HEAP_BLOCKS_LIVE 0x80000000
#define PURIFY_HEAP_BLOCKS_DEFERRED_FREE 0x40000000
#define PURIFY_HEAP_BLOCKS_ALL (PURIFY_HEAP_BLOCKS_LIVE|PURIFY_HEAP_BLOCKS_DEFERRED_FREE)
int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr) ;
int __cdecl PurifySetLateDetectScanCounter(int counter);
int __cdecl PurifySetLateDetectScanInterval(int seconds);
//
// Functions to support pool allocators
//
void __cdecl PurifySetPoolId(const void *mem, int id);
int __cdecl PurifyGetPoolId(const void *mem);
void __cdecl PurifySetUserData(const void *mem, void *data);
void * __cdecl PurifyGetUserData(const void *mem);
void __cdecl PurifyMapPool(int id, void(*fn)());
////////////////////////////////
// API's Specific to Quantify //
////////////////////////////////
// TRUE when Quantify is running.
int __cdecl QuantifyIsRunning(void) ;
//
// Functions for controlling collection
//
int __cdecl QuantifyDisableRecordingData(void) ;
int __cdecl QuantifyStartRecordingData(void) ;
int __cdecl QuantifyStopRecordingData(void) ;
int __cdecl QuantifyClearData(void) ;
int __cdecl QuantifyIsRecordingData(void) ;
// Add a comment to the dataset
int __cdecl QuantifyAddAnnotation(char *) ;
// Save the current data, creating a "checkpoint" dataset
int __cdecl QuantifySaveData(void) ;
// Set the name of the current thread in the viewer
int __cdecl QuantifySetThreadName(char *) ;
////////////////////////////////
// API's Specific to Coverage //
////////////////////////////////
// TRUE when Coverage is running.
int __cdecl CoverageIsRunning(void) ;
//
// Functions for controlling collection
//
int __cdecl CoverageDisableRecordingData(void) ;
int __cdecl CoverageStartRecordingData(void) ;
int __cdecl CoverageStopRecordingData(void) ;
int __cdecl CoverageClearData(void) ;
int __cdecl CoverageIsRecordingData(void) ;
// Add a comment to the dataset
int __cdecl CoverageAddAnnotation(char *) ;
// Save the current data, creating a "checkpoint" dataset
int __cdecl CoverageSaveData(void) ;
#endif // PURIFY_PRIVATE_INCLUDE
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif
#endif // defined(PURIFY) || defined(QUANTIFY)

View File

@ -1,152 +0,0 @@
/*
* Header file of Pure API function declarations.
*
* Explicitly no copyright.
* You may recompile and redistribute these definitions as required.
*
* NOTE1: In some situations when compiling with MFC, you should
* enable the setting 'Not using precompiled headers' in Visual C++
* to avoid a compiler diagnostic.
*
* NOTE2: This file works through the use of deep magic. Calls to functions
* in this file are replaced with calls into the OCI runtime system
* when an instrumented version of this program is run.
*
* NOTE3: The static vars avoidGy_n (where n is a unique number) are used
* to prevent optimizing the functions away when compiler option
* /Gy is set. This is needed so that NOTE2 works properly.
*/
// Chromium note: We used to only compile this code if PURIFY was defined,
// because we did special builds with all optimizations turned off for Purify.
// However, for profiling with Quantify, we want most/all optimizations turned
// on so that we measure something closer to real execution.
#ifdef _WINDOWS // we only use Purify/Quantify on Windows
#pragma once
extern int errno;
typedef int ptrdiff_t;
typedef unsigned int size_t;
typedef unsigned short wchar_t;
static int avoidGy_1 = 0;
static int avoidGy_2 = 0;
static int avoidGy_3 = 0;
static int avoidGy_4 = 0;
static int avoidGy_5 = 0;
static int avoidGy_6 = 0;
static int avoidGy_7 = 0;
static int avoidGy_8 = 0;
static int avoidGy_9 = 0;
static int avoidGy_10 = 0;
static int avoidGy_11 = 0;
static int avoidGy_12 = 0;
static int avoidGy_13 = 0;
static int avoidGy_14 = 0;
static int avoidGy_15 = 0;
static int avoidGy_16 = 0;
static int avoidGy_17 = 0;
static int avoidGy_18 = 0;
static int avoidGy_19 = 0;
static int avoidGy_20 = 0;
static int avoidGy_21 = 0;
static int avoidGy_22 = 0;
static int avoidGy_23 = 0;
static int avoidGy_24 = 0;
static int avoidGy_25 = 0;
static int avoidGy_26 = 0;
static int avoidGy_27 = 0;
static int avoidGy_28 = 0;
static int avoidGy_29 = 0;
static int avoidGy_30 = 0;
static int avoidGy_31 = 0;
static int avoidGy_32 = 0;
static int avoidGy_33 = 0;
static int avoidGy_34 = 0;
static int avoidGy_35 = 0;
static int avoidGy_36 = 0;
static int avoidGy_37 = 0;
static int avoidGy_38 = 0;
static int avoidGy_39 = 0;
static int avoidGy_40 = 0;
static int avoidGy_41 = 0;
static int avoidGy_42 = 0;
static int avoidGy_43 = 0;
static int avoidGy_44 = 0;
static int avoidGy_45 = 0;
static int avoidGy_46 = 0;
static int avoidGy_47 = 0;
static int avoidGy_48 = 0;
static int avoidGy_49 = 0;
static int avoidGy_50 = 0;
static int avoidGy_51 = 0;
static int avoidGy_52 = 0;
static int avoidGy_53 = 0;
static int avoidGy_54 = 0;
static int avoidGy_55 = 0;
static int avoidGy_56 = 0;
static int avoidGy_57 = 0;
static int avoidGy_58 = 0;
static int avoidGy_59 = 0;
static int avoidGy_60 = 0;
static int avoidGy_61 = 0;
static int avoidGy_62 = 0;
static int avoidGy_63 = 0;
static int avoidGy_64 = 0;
static int avoidGy_65 = 0;
static int avoidGy_PL_01 = 0;
static int avoidGy_PL_02 = 0;
__declspec(dllexport) int __cdecl PurePrintf(const char *fmt, ...) { if(!++avoidGy_1); fmt; return 0; }
__declspec(dllexport) int __cdecl PurifyIsRunning(void) { if(!++avoidGy_2); return 0; }
__declspec(dllexport) int __cdecl PurifyPrintf(const char *fmt, ...) { if(!++avoidGy_3); fmt; return 0; }
__declspec(dllexport) size_t __cdecl PurifyNewInuse(void) { if(!++avoidGy_4); return 0; }
__declspec(dllexport) size_t __cdecl PurifyAllInuse(void) { if(!++avoidGy_5); return 0; }
__declspec(dllexport) size_t __cdecl PurifyClearInuse(void) { if(!++avoidGy_6); return 0; }
__declspec(dllexport) size_t __cdecl PurifyNewLeaks(void) { if(!++avoidGy_7); return 0; }
__declspec(dllexport) size_t __cdecl PurifyAllLeaks(void) { if(!++avoidGy_8); return 0; }
__declspec(dllexport) size_t __cdecl PurifyClearLeaks(void) { if(!++avoidGy_9); return 0; }
__declspec(dllexport) size_t __cdecl PurifyAllHandlesInuse(void) { if(!++avoidGy_10); return 0; }
__declspec(dllexport) size_t __cdecl PurifyNewHandlesInuse(void) { if(!++avoidGy_11); return 0; }
__declspec(dllexport) size_t __cdecl PurifyDescribe(void *addr) { if(!++avoidGy_12); addr; return 0; }
__declspec(dllexport) int __cdecl PurifyWhatColors(void *addr, size_t size) { if(!++avoidGy_13); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyAssertIsReadable(const void *addr, size_t size) { if(!++avoidGy_14); addr; size; return 1; }
__declspec(dllexport) int __cdecl PurifyAssertIsWritable(const void *addr, size_t size) { if(!++avoidGy_15); addr; size; return 1; }
__declspec(dllexport) int __cdecl PurifyIsReadable(const void *addr, size_t size) { if(!++avoidGy_16); addr; size; return 1; }
__declspec(dllexport) int __cdecl PurifyIsWritable(const void *addr, size_t size) { if(!++avoidGy_17); addr; size; return 1; }
__declspec(dllexport) int __cdecl PurifyIsInitialized(const void *addr, size_t size) { if(!++avoidGy_18); addr; size; return 1; }
__declspec(dllexport) int __cdecl PurifyRed(void *addr, size_t size) { if(!++avoidGy_19); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyGreen(void *addr, size_t size) { if(!++avoidGy_20); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyYellow(void *addr, size_t size) { if(!++avoidGy_21); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyBlue(void *addr, size_t size) { if(!++avoidGy_22); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyMarkAsInitialized(void *addr, size_t size) { if(!++avoidGy_23); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyMarkAsUninitialized(void *addr, size_t size) { if(!++avoidGy_24); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyMarkForTrap(void *addr, size_t size) { if(!++avoidGy_25); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyMarkForNoTrap(void *addr, size_t size) { if(!++avoidGy_26); addr; size; return 0; }
__declspec(dllexport) int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr)
{ if(!++avoidGy_27); hHeap; dwFlags; addr; return 1; }
__declspec(dllexport) int __cdecl PurifySetLateDetectScanCounter(int counter) { if(!++avoidGy_28); counter; return 0; };
__declspec(dllexport) int __cdecl PurifySetLateDetectScanInterval(int seconds) { if(!++avoidGy_29); seconds; return 0; };
__declspec(dllexport) void __cdecl PurifySetPoolId(const void *mem, int id) { if(!++avoidGy_61); mem; id; return; };
__declspec(dllexport) int __cdecl PurifyGetPoolId(const void *mem) { if(!++avoidGy_62); mem; return 0; };
__declspec(dllexport) void __cdecl PurifySetUserData(const void *mem, void *data) { if(!++avoidGy_63); mem; data; return; };
__declspec(dllexport) void * __cdecl PurifyGetUserData(const void *mem) { if(!++avoidGy_64); mem; return 0; };
__declspec(dllexport) void __cdecl PurifyMapPool(int id, void(*fn)()) { if(!++avoidGy_65); id; fn; return; };
__declspec(dllexport) int __cdecl CoverageIsRunning(void) { if(!++avoidGy_30); return 0; }
__declspec(dllexport) int __cdecl CoverageDisableRecordingData(void) { if(!++avoidGy_31); return 0; }
__declspec(dllexport) int __cdecl CoverageStartRecordingData(void) { if(!++avoidGy_32); return 0; }
__declspec(dllexport) int __cdecl CoverageStopRecordingData(void) { if(!++avoidGy_33); return 0; }
__declspec(dllexport) int __cdecl CoverageClearData(void) { if(!++avoidGy_34); return 0; }
__declspec(dllexport) int __cdecl CoverageIsRecordingData(void) { if(!++avoidGy_35); return 0; }
__declspec(dllexport) int __cdecl CoverageAddAnnotation(char *str) { if(!++avoidGy_36); str; return 0; }
__declspec(dllexport) int __cdecl CoverageSaveData(void) { if(!++avoidGy_37); return 0; }
__declspec(dllexport) int __cdecl QuantifyIsRunning(void) { if(!++avoidGy_42); return 0; }
__declspec(dllexport) int __cdecl QuantifyDisableRecordingData(void) { if(!++avoidGy_43); return 0; }
__declspec(dllexport) int __cdecl QuantifyStartRecordingData(void) { if(!++avoidGy_44); return 0; }
__declspec(dllexport) int __cdecl QuantifyStopRecordingData(void) { if(!++avoidGy_45); return 0; }
__declspec(dllexport) int __cdecl QuantifyClearData(void) { if(!++avoidGy_46); return 0; }
__declspec(dllexport) int __cdecl QuantifyIsRecordingData(void) { if(!++avoidGy_47); return 0; }
__declspec(dllexport) int __cdecl QuantifyAddAnnotation(char *str) { if(!++avoidGy_48); str; return 0; }
__declspec(dllexport) int __cdecl QuantifySaveData(void) { if(!++avoidGy_49); return 0; }
__declspec(dllexport) int __cdecl QuantifySetThreadName(const char *szName) { if(!++avoidGy_50) ; szName; return 0; }
#endif // _WINDOWS

View File

@ -147,7 +147,7 @@ public:
};
template<class ListenerT>
class /*NS_INTERFACE_CLASS*/ IProtocolManager
class IProtocolManager
{
public:
enum ActorDestroyReason {

View File

@ -125,17 +125,11 @@ class CxxCodeGen(CodePrinter, Visitor):
def visitClass(self, c):
if c.specializes is not None:
self.printdentln('template<>')
if c.struct:
self.printdent('struct')
else:
self.printdent('class')
if c.interface:
# FIXME/cjones: turn this "on" when we get the analysis
self.write(' /*NS_INTERFACE_CLASS*/')
if c.abstract:
# FIXME/cjones: turn this "on" when we get the analysis
self.write(' /*NS_ABSTRACT_CLASS*/')
self.write(' '+ c.name)
if c.final:
self.write(' final')

Some files were not shown because too many files have changed in this diff Show More