This commit is contained in:
Phil Ringnalda 2016-10-03 20:51:52 -07:00
Родитель 31b75f4537 c1e745733c
Коммит 73ccc79fc3
261 изменённых файлов: 3894 добавлений и 2093 удалений

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

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Bug 1280590 - xpcshell failure in windows7 Bug 1302855 changed build system to fold browsercomps into xul

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

@ -291,14 +291,20 @@ EventTree::FindOrInsert(Accessible* aContainer)
AccMutationEvent* ev = node->mDependentEvents[idx]; AccMutationEvent* ev = node->mDependentEvents[idx];
if (ev->GetAccessible() == parent) { if (ev->GetAccessible() == parent) {
#ifdef A11Y_LOG #ifdef A11Y_LOG
if (logging::IsEnabledAll(logging::eEventTree | if (logging::IsEnabled(logging::eEventTree)) {
logging::eVerbose)) {
logging::MsgBegin("EVENTS_TREE", logging::MsgBegin("EVENTS_TREE",
"Rejecting node since contained by show/hide target"); "Rejecting node contained by show/hide");
logging::AccessibleInfo("Container", aContainer); logging::AccessibleInfo("Node", aContainer);
logging::MsgEnd(); logging::MsgEnd();
} }
#endif #endif
// If the node is rejected, then check if it has related hide event
// on stack, and if so, then connect it to the parent show event.
if (ev->IsShow()) {
AccShowEvent* showEv = downcast_accEvent(ev);
Controller(aContainer)->
WithdrawPrecedingEvents(&showEv->mPrecedingEvents);
}
return nullptr; return nullptr;
} }
} }

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

@ -53,18 +53,14 @@ StyleInfo::TextIndent(nsAString& aValue)
switch (styleCoord.GetUnit()) { switch (styleCoord.GetUnit()) {
case eStyleUnit_Coord: case eStyleUnit_Coord:
coordVal = styleCoord.GetCoordValue(); coordVal = styleCoord.GetCoordValue();
aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
aValue.AppendLiteral("px");
break; break;
case eStyleUnit_Percent: case eStyleUnit_Percent:
{ aValue.AppendFloat(styleCoord.GetPercentValue() * 100);
nsIFrame* frame = mElement->GetPrimaryFrame(); aValue.AppendLiteral("%");
MOZ_ASSERT(frame, "frame must be a valid pointer.");
nsIFrame* containerFrame = frame->GetContainingBlock();
nscoord percentageBase = containerFrame->GetContentRect().width;
coordVal = NSCoordSaturatingMultiply(percentageBase,
styleCoord.GetPercentValue());
break; break;
}
case eStyleUnit_Null: case eStyleUnit_Null:
case eStyleUnit_Normal: case eStyleUnit_Normal:
@ -79,11 +75,9 @@ StyleInfo::TextIndent(nsAString& aValue)
case eStyleUnit_Integer: case eStyleUnit_Integer:
case eStyleUnit_Enumerated: case eStyleUnit_Enumerated:
case eStyleUnit_Calc: case eStyleUnit_Calc:
aValue.AppendLiteral("0px");
break; break;
} }
aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
aValue.AppendLiteral("px");
} }
void void

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

@ -559,13 +559,14 @@
} }
/** /**
* Move 't9_c2_moved' node by aria-owns, and then move 't9_c3_moved' node * Move 't9_c3_moved' node under 't9_c2_moved', and then move 't9_c2_moved'
* under 't9_c2_moved' (same as test9 but has different aria-owns * node by aria-owns (same as test10 but has different aria-owns
* ordering), the eventing looks same way as in test9: * ordering), the eventing looks same way as in test10:
* reorder for 't9_c1' * reorder for 't9_c1'
* hide for 't9_c1_child' * hide for 't9_c1_child'
* show for 't9_c2_moved' * show for 't9_c2_moved'
* reorder for 't9_c2' * reorder for 't9_c2'
* hide for 't9_c2_child'
* hide for 't9_c2_moved' * hide for 't9_c2_moved'
* reorder for 't9_c3' * reorder for 't9_c3'
* hide for 't9_c3_moved' * hide for 't9_c3_moved'
@ -604,6 +605,51 @@
}; };
} }
/**
* Move a node 't10_c3_moved' by aria-owns under a node 't10_c2_moved',
* moved by under 't10_1', so that the eventing looks this way:
* reorder for 't10_c1'
* hide for 't10_c1_child'
* show for 't10_c2_moved'
* reorder for 't10_c2'
* hide for 't10_c2_child'
* hide for 't10_c2_moved'
* reorder for 't10_c3'
* hide for 't10_c3_moved'
*
* The hide events for 't10_c2_moved' and 't10_c3_moved' should be delivered
* before the show event for 't10_c2_moved'.
*/
function test10()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode('t10_c1_child')),
new invokerChecker(EVENT_HIDE, getNode('t10_c2_moved')),
new invokerChecker(EVENT_HIDE, getNode('t10_c3_moved')),
new invokerChecker(EVENT_SHOW, getNode('t10_c2_moved')),
new invokerChecker(EVENT_REORDER, 't10_c1'),
new invokerChecker(EVENT_HIDE, getNode('t10_c2_child')),
new invokerChecker(EVENT_REORDER, 't10_c2'),
new invokerChecker(EVENT_REORDER, 't10_c3')
];
this.invoke = function test10_invoke()
{
// Remove child nodes from 't10_c1' and 't10_c2' containers to give
// the event tree a needed structure ('t10_c1' and 't10_c2' nodes go first
// in the event tree),
getNode('t10_c1_child').remove();
getNode('t10_c2_child').remove();
// then do aria-owns stuff.
getNode('t10_c1').setAttribute('aria-owns', 't10_c2_moved');
getNode('t10_c2_moved').setAttribute('aria-owns', 't10_c3_moved');
};
this.getID = function test10_getID() {
return "Move a node by aria-owns into a node moved by aria-owns to left within the tree";
};
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Do tests. // Do tests.
@ -639,6 +685,7 @@
gQueue.push(new test7()); gQueue.push(new test7());
gQueue.push(new test8()); gQueue.push(new test8());
gQueue.push(new test9()); gQueue.push(new test9());
gQueue.push(new test10());
gQueue.invoke(); // Will call SimpleTest.finish(); gQueue.invoke(); // Will call SimpleTest.finish();
} }
@ -757,5 +804,16 @@
<div id="t9_c3_moved"></div> <div id="t9_c3_moved"></div>
</div> </div>
</div> </div>
<div id="t10">
<div id="t10_c1"><div id="t10_c1_child"></div></div>
<div id="t10_c2">
<div id="t10_c2_child"></div>
<div id="t10_c2_moved"></div>
</div>
<div id="t10_c3">
<div id="t10_c3_moved"></div>
</div>
</div>
</body> </body>
</html> </html>

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

@ -361,8 +361,8 @@
function showHiddenParentOfVisibleChild() function showHiddenParentOfVisibleChild()
{ {
this.eventSeq = [ this.eventSeq = [
new invokerChecker(EVENT_SHOW, getNode("c4_middle")),
new invokerChecker(EVENT_HIDE, getNode("c4_child")), new invokerChecker(EVENT_HIDE, getNode("c4_child")),
new invokerChecker(EVENT_SHOW, getNode("c4_middle")),
new invokerChecker(EVENT_REORDER, getNode("c4")) new invokerChecker(EVENT_REORDER, getNode("c4"))
]; ];

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

@ -80,16 +80,6 @@ static bool IsArg(const char* arg, const char* s)
return false; return false;
} }
/**
* A helper class which calls NS_LogInit/NS_LogTerm in its scope.
*/
class ScopedLogging
{
public:
ScopedLogging() { NS_LogInit(); }
~ScopedLogging() { NS_LogTerm(); }
};
XRE_GetFileFromPathType XRE_GetFileFromPath; XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_CreateAppDataType XRE_CreateAppData; XRE_CreateAppDataType XRE_CreateAppData;
XRE_FreeAppDataType XRE_FreeAppData; XRE_FreeAppDataType XRE_FreeAppData;

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

@ -59,6 +59,7 @@ skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliabil
[browser_urlbarKeepStateAcrossTabSwitches.js] [browser_urlbarKeepStateAcrossTabSwitches.js]
[browser_urlbarOneOffs.js] [browser_urlbarOneOffs.js]
[browser_urlbarPrivateBrowsingWindowChange.js] [browser_urlbarPrivateBrowsingWindowChange.js]
[browser_urlbarRaceWithTabs.js]
[browser_urlbarRevert.js] [browser_urlbarRevert.js]
[browser_urlbarSearchSingleWordNotification.js] [browser_urlbarSearchSingleWordNotification.js]
[browser_urlbarSearchSuggestions.js] [browser_urlbarSearchSuggestions.js]

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

@ -0,0 +1,57 @@
const kURL = "http://example.org/browser/browser/base/content/test/urlbar/dummy_page.html";
function* addBookmark(bookmark) {
if (bookmark.keyword) {
yield PlacesUtils.keywords.insert({
keyword: bookmark.keyword,
url: bookmark.url,
});
}
let bm = yield PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: bookmark.url,
title: bookmark.title,
});
registerCleanupFunction(function* () {
yield PlacesUtils.bookmarks.remove(bm);
if (bookmark.keyword) {
yield PlacesUtils.keywords.remove(bookmark.keyword);
}
});
}
/**
* Check that if the user hits enter and ctrl-t at the same time, we open the URL in the right tab.
*/
add_task(function* hitEnterLoadInRightTab() {
info("Opening new tab");
let oldTabCreatedPromise = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
BrowserOpenTab();
let oldTab = (yield oldTabCreatedPromise).target;
let oldTabLoadedPromise = BrowserTestUtils.browserLoaded(oldTab.linkedBrowser, false, kURL);
oldTabLoadedPromise.then(() => info("Old tab loaded"));
let newTabCreatedPromise = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabOpen");
info("Creating bookmark and keyword");
yield addBookmark({title: "Test for keyword bookmark and URL", url: kURL, keyword: "urlbarkeyword"});
info("Filling URL bar, sending <return> and opening a tab");
gURLBar.value = "urlbarkeyword";
gURLBar.select();
EventUtils.sendKey("return");
BrowserOpenTab();
info("Waiting for new tab");
let newTab = (yield newTabCreatedPromise).target;
info("Created new tab; waiting for either tab to load");
let newTabLoadedPromise = BrowserTestUtils.browserLoaded(newTab.linkedBrowser, false, kURL);
newTabLoadedPromise.then(() => info("New tab loaded"));
yield Promise.race([newTabLoadedPromise, oldTabLoadedPromise]);
is(newTab.linkedBrowser.currentURI.spec, "about:newtab", "New tab still has about:newtab");
is(oldTab.linkedBrowser.currentURI.spec, kURL, "Old tab loaded URL");
info("Closing new tab");
yield BrowserTestUtils.removeTab(newTab);
info("Closing old tab");
yield BrowserTestUtils.removeTab(oldTab);
info("Finished");
});

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

@ -399,6 +399,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
let mayInheritPrincipal = false; let mayInheritPrincipal = false;
let postData = null; let postData = null;
let browser = gBrowser.selectedBrowser;
let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
let matchLastLocationChange = true; let matchLastLocationChange = true;
@ -435,7 +436,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
); );
break; break;
} }
this._loadURL(url, postData, where, openUILinkParams, this._loadURL(url, browser, postData, where, openUILinkParams,
matchLastLocationChange, mayInheritPrincipal); matchLastLocationChange, mayInheritPrincipal);
return; return;
} }
@ -456,7 +457,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
[url, postData] = [url, postData] =
this._recordSearchEngineLoad(selectedOneOff.engine, value, this._recordSearchEngineLoad(selectedOneOff.engine, value,
event, where, openUILinkParams); event, where, openUILinkParams);
this._loadURL(url, postData, where, openUILinkParams, this._loadURL(url, browser, postData, where, openUILinkParams,
matchLastLocationChange, mayInheritPrincipal); matchLastLocationChange, mayInheritPrincipal);
return; return;
} }
@ -466,8 +467,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
getShortcutOrURIAndPostData(url).then(({url, postData, mayInheritPrincipal}) => { getShortcutOrURIAndPostData(url).then(({url, postData, mayInheritPrincipal}) => {
if (url) { if (url) {
matchLastLocationChange = matchLastLocationChange =
lastLocationChange == gBrowser.selectedBrowser.lastLocationChange; lastLocationChange == browser.lastLocationChange;
this._loadURL(url, postData, where, openUILinkParams, this._loadURL(url, browser, postData, where, openUILinkParams,
matchLastLocationChange, mayInheritPrincipal); matchLastLocationChange, mayInheritPrincipal);
} }
}); });
@ -487,6 +488,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<method name="_loadURL"> <method name="_loadURL">
<parameter name="url"/> <parameter name="url"/>
<parameter name="browser"/>
<parameter name="postData"/> <parameter name="postData"/>
<parameter name="openUILinkWhere"/> <parameter name="openUILinkWhere"/>
<parameter name="openUILinkParams"/> <parameter name="openUILinkParams"/>
@ -494,9 +496,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<parameter name="mayInheritPrincipal"/> <parameter name="mayInheritPrincipal"/>
<body><![CDATA[ <body><![CDATA[
this.value = url; this.value = url;
gBrowser.userTypedValue = url; browser.userTypedValue = url;
if (gInitialPages.includes(url)) { if (gInitialPages.includes(url)) {
gBrowser.selectedBrowser.initialPageLoadedFromURLBar = url; browser.initialPageLoadedFromURLBar = url;
} }
try { try {
addToUrlbarHistory(url); addToUrlbarHistory(url);
@ -509,6 +511,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
let params = { let params = {
postData: postData, postData: postData,
allowThirdPartyFixup: true, allowThirdPartyFixup: true,
currentBrowser: browser,
}; };
if (openUILinkWhere == "current") { if (openUILinkWhere == "current") {
params.indicateErrorPageLoad = true; params.indicateErrorPageLoad = true;
@ -528,7 +531,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Focus the content area before triggering loads, since if the load // Focus the content area before triggering loads, since if the load
// occurs in a new tab, we want focus to be restored to the content // occurs in a new tab, we want focus to be restored to the content
// area when the current tab is re-selected. // area when the current tab is re-selected.
gBrowser.selectedBrowser.focus(); browser.focus();
if (openUILinkWhere == "current" && !matchLastLocationChange) { if (openUILinkWhere == "current" && !matchLastLocationChange) {
return; return;

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

@ -226,6 +226,19 @@ function openLinkIn(url, where, params) {
var aForceAboutBlankViewerInCurrent = var aForceAboutBlankViewerInCurrent =
params.forceAboutBlankViewerInCurrent; params.forceAboutBlankViewerInCurrent;
// Establish a window in which we're running this code.
var w = getTopWin();
if ((where == "tab" || where == "tabshifted") &&
w && !w.toolbar.visible) {
w = getTopWin(true);
aRelatedToCurrent = false;
}
// Can only do this after we're sure of what |w| will be the rest of this function.
// Note that if |w| is null we might have no current browser (we'll open a new window).
var aCurrentBrowser = params.currentBrowser || (w && w.gBrowser.selectedBrowser);
if (where == "save") { if (where == "save") {
// TODO(1073187): propagate referrerPolicy. // TODO(1073187): propagate referrerPolicy.
@ -244,13 +257,6 @@ function openLinkIn(url, where, params) {
return; return;
} }
var w = getTopWin();
if ((where == "tab" || where == "tabshifted") &&
w && !w.toolbar.visible) {
w = getTopWin(true);
aRelatedToCurrent = false;
}
if (!w || where == "window") { if (!w || where == "window") {
// This propagates to window.arguments. // This propagates to window.arguments.
var sa = Cc["@mozilla.org/supports-array;1"]. var sa = Cc["@mozilla.org/supports-array;1"].
@ -318,12 +324,17 @@ function openLinkIn(url, where, params) {
} catch (e) {} } catch (e) {}
} }
if (where == "current" && w.gBrowser.selectedTab.pinned && // NB: we avoid using |w| here because in the 'popup window' case,
// if we pass a currentBrowser param |w.gBrowser| might not be the
// tabbrowser that contains |aCurrentBrowser|. We really only care
// about the tab linked to |aCurrentBrowser|.
let tab = aCurrentBrowser.ownerGlobal.gBrowser.getTabForBrowser(aCurrentBrowser);
if (where == "current" && tab.pinned &&
!aAllowPinnedTabHostChange) { !aAllowPinnedTabHostChange) {
try { try {
// nsIURI.host can throw for non-nsStandardURL nsIURIs. // nsIURI.host can throw for non-nsStandardURL nsIURIs.
if (!uriObj || (!uriObj.schemeIs("javascript") && if (!uriObj || (!uriObj.schemeIs("javascript") &&
w.gBrowser.currentURI.host != uriObj.host)) { aCurrentBrowser.currentURI.host != uriObj.host)) {
where = "tab"; where = "tab";
loadInBackground = false; loadInBackground = false;
} }
@ -365,7 +376,7 @@ function openLinkIn(url, where, params) {
w.gBrowser.selectedBrowser.createAboutBlankContentViewer(aPrincipal); w.gBrowser.selectedBrowser.createAboutBlankContentViewer(aPrincipal);
} }
w.gBrowser.loadURIWithFlags(url, { aCurrentBrowser.loadURIWithFlags(url, {
flags: flags, flags: flags,
referrerURI: aNoReferrer ? null : aReferrerURI, referrerURI: aNoReferrer ? null : aReferrerURI,
referrerPolicy: aReferrerPolicy, referrerPolicy: aReferrerPolicy,
@ -394,7 +405,7 @@ function openLinkIn(url, where, params) {
break; break;
} }
w.gBrowser.selectedBrowser.focus(); aCurrentBrowser.focus();
if (!loadInBackground && w.isBlankPageURL(url)) { if (!loadInBackground && w.isBlankPageURL(url)) {
w.focusAndSelectUrlBar(); w.focusAndSelectUrlBar();

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

@ -12,7 +12,8 @@ SOURCES += [
'nsModule.cpp', 'nsModule.cpp',
] ]
XPCOMBinaryComponent('browsercomps') Library('browsercomps')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
'../about', '../about',
@ -21,22 +22,3 @@ LOCAL_INCLUDES += [
'../migration', '../migration',
'../shell', '../shell',
] ]
if CONFIG['OS_ARCH'] == 'WINNT':
OS_LIBS += [
'esent',
'netapi32',
'ole32',
'shell32',
'shlwapi',
'version',
]
DELAYLOAD_DLLS += [
'esent.dll',
'netapi32.dll',
]
# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
# GTK2: Need to link with glib for GNOME shell service
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'):
OS_LIBS += CONFIG['TK_LIBS']

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

@ -20,7 +20,7 @@
#include "nsDirectoryServiceUtils.h" #include "nsDirectoryServiceUtils.h"
#include "mozilla/ModuleUtils.h" #include "mozilla/ModuleUtils.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsStringAPI.h" #include "nsString.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "nsIPrefLocalizedString.h" #include "nsIPrefLocalizedString.h"

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

@ -185,9 +185,15 @@ IsDocumentElement(const char *start, const char* end)
static bool static bool
ContainsTopLevelSubstring(nsACString& dataString, const char *substring) ContainsTopLevelSubstring(nsACString& dataString, const char *substring)
{ {
int32_t offset = dataString.Find(substring); nsACString::const_iterator start, end;
if (offset == -1) dataString.BeginReading(start);
dataString.EndReading(end);
if (!FindInReadable(nsCString(substring), start, end)){
return false; return false;
}
auto offset = start.get() - dataString.Data();
const char *begin = dataString.BeginReading(); const char *begin = dataString.BeginReading();
@ -312,9 +318,10 @@ nsFeedSniffer::GetMIMETypeFromContent(nsIRequest* request,
// RSS 1.0 // RSS 1.0
if (!isFeed) { if (!isFeed) {
bool foundNS_RDF = FindInReadable(NS_LITERAL_CSTRING(NS_RDF), dataString);
bool foundNS_RSS = FindInReadable(NS_LITERAL_CSTRING(NS_RSS), dataString);
isFeed = ContainsTopLevelSubstring(dataString, "<rdf:RDF") && isFeed = ContainsTopLevelSubstring(dataString, "<rdf:RDF") &&
dataString.Find(NS_RDF) != -1 && foundNS_RDF && foundNS_RSS;
dataString.Find(NS_RSS) != -1;
} }
// If we sniffed a feed, coerce our internal type // If we sniffed a feed, coerce our internal type

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

@ -6,7 +6,7 @@
#include "nsIContentSniffer.h" #include "nsIContentSniffer.h"
#include "nsIStreamListener.h" #include "nsIStreamListener.h"
#include "nsStringAPI.h" #include "nsString.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
class nsFeedSniffer final : public nsIContentSniffer, class nsFeedSniffer final : public nsIContentSniffer,

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

@ -9,9 +9,10 @@
#include "nsArrayEnumerator.h" #include "nsArrayEnumerator.h"
#include "nsCOMArray.h" #include "nsCOMArray.h"
#include "nsIURI.h"
#include "nsIVariant.h" #include "nsIVariant.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsStringAPI.h" #include "nsString.h"
#include "nsWindowsMigrationUtils.h" #include "nsWindowsMigrationUtils.h"
#include "prtime.h" #include "prtime.h"

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

@ -14,7 +14,7 @@
#include "nsDirectoryServiceDefs.h" #include "nsDirectoryServiceDefs.h"
#include "nsIPrefService.h" #include "nsIPrefService.h"
#include "prenv.h" #include "prenv.h"
#include "nsStringAPI.h" #include "nsString.h"
#include "nsIGConfService.h" #include "nsIGConfService.h"
#include "nsIGIOService.h" #include "nsIGIOService.h"
#include "nsIGSettingsService.h" #include "nsIGSettingsService.h"
@ -70,16 +70,16 @@ static const MimeTypeAssociation appTypes[] = {
// GConf registry key constants // GConf registry key constants
#define DG_BACKGROUND "/desktop/gnome/background" #define DG_BACKGROUND "/desktop/gnome/background"
static const char kDesktopImageKey[] = DG_BACKGROUND "/picture_filename"; #define kDesktopImageKey DG_BACKGROUND "/picture_filename"
static const char kDesktopOptionsKey[] = DG_BACKGROUND "/picture_options"; #define kDesktopOptionsKey DG_BACKGROUND "/picture_options"
static const char kDesktopDrawBGKey[] = DG_BACKGROUND "/draw_background"; #define kDesktopDrawBGKey DG_BACKGROUND "/draw_background"
static const char kDesktopColorKey[] = DG_BACKGROUND "/primary_color"; #define kDesktopColorKey DG_BACKGROUND "/primary_color"
static const char kDesktopBGSchema[] = "org.gnome.desktop.background"; #define kDesktopBGSchema "org.gnome.desktop.background"
static const char kDesktopImageGSKey[] = "picture-uri"; #define kDesktopImageGSKey "picture-uri"
static const char kDesktopOptionGSKey[] = "picture-options"; #define kDesktopOptionGSKey "picture-options"
static const char kDesktopDrawBGGSKey[] = "draw-background"; #define kDesktopDrawBGGSKey "draw-background"
static const char kDesktopColorGSKey[] = "primary-color"; #define kDesktopColorGSKey "primary-color"
nsresult nsresult
nsGNOMEShellService::Init() nsGNOMEShellService::Init()
@ -508,7 +508,8 @@ static void
ColorToCString(uint32_t aColor, nsCString& aResult) ColorToCString(uint32_t aColor, nsCString& aResult)
{ {
// The #rrrrggggbbbb format is used to match gdk_color_to_string() // The #rrrrggggbbbb format is used to match gdk_color_to_string()
char *buf = aResult.BeginWriting(13); aResult.SetLength(13);
char *buf = aResult.BeginWriting();
if (!buf) if (!buf)
return; return;

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

@ -7,7 +7,7 @@
#define nsgnomeshellservice_h____ #define nsgnomeshellservice_h____
#include "nsIGNOMEShellService.h" #include "nsIGNOMEShellService.h"
#include "nsStringAPI.h" #include "nsString.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
class nsGNOMEShellService final : public nsIGNOMEShellService class nsGNOMEShellService final : public nsIGNOMEShellService

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

@ -20,7 +20,7 @@
#include "nsIProperties.h" #include "nsIProperties.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsShellService.h" #include "nsShellService.h"
#include "nsStringAPI.h" #include "nsString.h"
#include "nsIDocShell.h" #include "nsIDocShell.h"
#include "nsILoadContext.h" #include "nsILoadContext.h"

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

@ -12,6 +12,7 @@
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsIDOMHTMLImageElement.h" #include "nsIDOMHTMLImageElement.h"
#include "nsIImageLoadingContent.h" #include "nsIImageLoadingContent.h"
#include "nsIOutputStream.h"
#include "nsIPrefService.h" #include "nsIPrefService.h"
#include "nsIPrefLocalizedString.h" #include "nsIPrefLocalizedString.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
@ -465,7 +466,7 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
return NS_OK; return NS_OK;
} }
res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, PromiseFlatString(keyName).get(), res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName.get(),
0, KEY_SET_VALUE, &theKey); 0, KEY_SET_VALUE, &theKey);
if (REG_FAILED(res)) { if (REG_FAILED(res)) {
// If updating the open command fails try to update it using the helper // If updating the open command fails try to update it using the helper
@ -474,10 +475,9 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
return NS_OK; return NS_OK;
} }
const nsString &flatValue = PromiseFlatString(valueData);
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
(const BYTE *) flatValue.get(), (const BYTE *) valueData.get(),
(flatValue.Length() + 1) * sizeof(char16_t)); (valueData.Length() + 1) * sizeof(char16_t));
// Close the key that was created. // Close the key that was created.
::RegCloseKey(theKey); ::RegCloseKey(theKey);
if (REG_FAILED(res)) { if (REG_FAILED(res)) {
@ -529,9 +529,8 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
if (REG_FAILED(res) || char16_t('\0') != *currValue) { if (REG_FAILED(res) || char16_t('\0') != *currValue) {
// Key wasn't set or was set to something other than our registry entry. // Key wasn't set or was set to something other than our registry entry.
// Delete the key along with all of its childrean and then recreate it. // Delete the key along with all of its childrean and then recreate it.
const nsString &flatName = PromiseFlatString(keyName); ::SHDeleteKeyW(HKEY_CURRENT_USER, keyName.get());
::SHDeleteKeyW(HKEY_CURRENT_USER, flatName.get()); res = ::RegCreateKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, nullptr,
res = ::RegCreateKeyExW(HKEY_CURRENT_USER, flatName.get(), 0, nullptr,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
nullptr, &theKey, nullptr); nullptr, &theKey, nullptr);
if (REG_FAILED(res)) { if (REG_FAILED(res)) {
@ -583,10 +582,9 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
NS_ConvertUTF8toUTF16 valueData(VAL_OPEN); NS_ConvertUTF8toUTF16 valueData(VAL_OPEN);
valueData.Replace(offset, 9, appLongPath); valueData.Replace(offset, 9, appLongPath);
const nsString &flatValue = PromiseFlatString(valueData);
res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
(const BYTE *) flatValue.get(), (const BYTE *) valueData.get(),
(flatValue.Length() + 1) * sizeof(char16_t)); (valueData.Length() + 1) * sizeof(char16_t));
// Close the key that was created. // Close the key that was created.
::RegCloseKey(theKey); ::RegCloseKey(theKey);
// If updating the FTP protocol handlers shell open command fails try to // If updating the FTP protocol handlers shell open command fails try to

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

@ -7,7 +7,7 @@
#define nswindowsshellservice_h____ #define nswindowsshellservice_h____
#include "nscore.h" #include "nscore.h"
#include "nsStringAPI.h" #include "nsString.h"
#include "nsIWindowsShellService.h" #include "nsIWindowsShellService.h"
#include "nsITimer.h" #include "nsITimer.h"

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

@ -149,7 +149,6 @@
@RESPATH@/browser/components/prebuilt-interfaces.manifest @RESPATH@/browser/components/prebuilt-interfaces.manifest
@RESPATH@/browser/components/interfaces.xpt @RESPATH@/browser/components/interfaces.xpt
#endif #endif
@RESPATH@/browser/components/components.manifest
@RESPATH@/components/alerts.xpt @RESPATH@/components/alerts.xpt
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
#ifdef XP_WIN32 #ifdef XP_WIN32
@ -445,7 +444,6 @@
@RESPATH@/browser/components/nsSessionStore.js @RESPATH@/browser/components/nsSessionStore.js
@RESPATH@/components/nsURLFormatter.manifest @RESPATH@/components/nsURLFormatter.manifest
@RESPATH@/components/nsURLFormatter.js @RESPATH@/components/nsURLFormatter.js
@RESPATH@/browser/components/@DLL_PREFIX@browsercomps@DLL_SUFFIX@
@RESPATH@/components/txEXSLTRegExFunctions.manifest @RESPATH@/components/txEXSLTRegExFunctions.manifest
@RESPATH@/components/txEXSLTRegExFunctions.js @RESPATH@/components/txEXSLTRegExFunctions.js
@RESPATH@/components/toolkitplaces.manifest @RESPATH@/components/toolkitplaces.manifest

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

@ -8,6 +8,7 @@ configobj.pth:python/configobj
jsmin.pth:python/jsmin jsmin.pth:python/jsmin
mach.pth:python/mach mach.pth:python/mach
mozbuild.pth:python/mozbuild mozbuild.pth:python/mozbuild
mozversioncontrol.pth:python/mozversioncontrol
mozlint.pth:python/mozlint mozlint.pth:python/mozlint
pymake.pth:build/pymake pymake.pth:build/pymake
optional:setup.py:python/psutil:build_ext:--inplace optional:setup.py:python/psutil:build_ext:--inplace

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

@ -923,8 +923,8 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI,
if (hasFlags) { if (hasFlags) {
// Allow domains that were whitelisted in the prefs. In 99.9% of cases, // Allow domains that were whitelisted in the prefs. In 99.9% of cases,
// this array is empty. // this array is empty.
for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) { for (nsIURI* uri : EnsureFileURIWhitelist()) {
if (EqualOrSubdomain(aSourceURI, mFileURIWhitelist[i])) { if (EqualOrSubdomain(aSourceURI, uri)) {
return NS_OK; return NS_OK;
} }
} }
@ -1459,38 +1459,7 @@ nsScriptSecurityManager::ScriptSecurityPrefChanged()
Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled); Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled);
sStrictFileOriginPolicy = sStrictFileOriginPolicy =
Preferences::GetBool(sFileOriginPolicyPrefName, false); Preferences::GetBool(sFileOriginPolicyPrefName, false);
mFileURIWhitelist.reset();
//
// Rebuild the set of principals for which we allow file:// URI loads. This
// implements a small subset of an old pref-based CAPS people that people
// have come to depend on. See bug 995943.
//
mFileURIWhitelist.Clear();
auto policies = mozilla::Preferences::GetCString("capability.policy.policynames");
for (uint32_t base = SkipPast<IsWhitespaceOrComma>(policies, 0), bound = 0;
base < policies.Length();
base = SkipPast<IsWhitespaceOrComma>(policies, bound))
{
// Grab the current policy name.
bound = SkipUntil<IsWhitespaceOrComma>(policies, base);
auto policyName = Substring(policies, base, bound - base);
// Figure out if this policy allows loading file:// URIs. If not, we can skip it.
nsCString checkLoadURIPrefName = NS_LITERAL_CSTRING("capability.policy.") +
policyName +
NS_LITERAL_CSTRING(".checkloaduri.enabled");
if (!Preferences::GetString(checkLoadURIPrefName.get()).LowerCaseEqualsLiteral("allaccess")) {
continue;
}
// Grab the list of domains associated with this policy.
nsCString domainPrefName = NS_LITERAL_CSTRING("capability.policy.") +
policyName +
NS_LITERAL_CSTRING(".sites");
auto siteList = Preferences::GetCString(domainPrefName.get());
AddSitesToFileURIWhitelist(siteList);
}
} }
void void
@ -1516,7 +1485,7 @@ nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList)
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), site, nullptr, nullptr, sIOService); nsresult rv = NS_NewURI(getter_AddRefs(uri), site, nullptr, nullptr, sIOService);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
mFileURIWhitelist.AppendElement(uri); mFileURIWhitelist.ref().AppendElement(uri);
} else { } else {
nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1")); nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1"));
if (console) { if (console) {
@ -1676,3 +1645,45 @@ nsScriptSecurityManager::PolicyAllowsScript(nsIURI* aURI, bool *aRv)
return NS_OK; return NS_OK;
} }
const nsTArray<nsCOMPtr<nsIURI>>&
nsScriptSecurityManager::EnsureFileURIWhitelist()
{
if (mFileURIWhitelist.isSome()) {
return mFileURIWhitelist.ref();
}
//
// Rebuild the set of principals for which we allow file:// URI loads. This
// implements a small subset of an old pref-based CAPS people that people
// have come to depend on. See bug 995943.
//
mFileURIWhitelist.emplace();
auto policies = mozilla::Preferences::GetCString("capability.policy.policynames");
for (uint32_t base = SkipPast<IsWhitespaceOrComma>(policies, 0), bound = 0;
base < policies.Length();
base = SkipPast<IsWhitespaceOrComma>(policies, bound))
{
// Grab the current policy name.
bound = SkipUntil<IsWhitespaceOrComma>(policies, base);
auto policyName = Substring(policies, base, bound - base);
// Figure out if this policy allows loading file:// URIs. If not, we can skip it.
nsCString checkLoadURIPrefName = NS_LITERAL_CSTRING("capability.policy.") +
policyName +
NS_LITERAL_CSTRING(".checkloaduri.enabled");
if (!Preferences::GetString(checkLoadURIPrefName.get()).LowerCaseEqualsLiteral("allaccess")) {
continue;
}
// Grab the list of domains associated with this policy.
nsCString domainPrefName = NS_LITERAL_CSTRING("capability.policy.") +
policyName +
NS_LITERAL_CSTRING(".sites");
auto siteList = Preferences::GetCString(domainPrefName.get());
AddSitesToFileURIWhitelist(siteList);
}
return mFileURIWhitelist.ref();
}

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

@ -124,10 +124,18 @@ private:
CheckLoadURIFlags(nsIURI* aSourceURI, nsIURI* aTargetURI, nsIURI* aSourceBaseURI, CheckLoadURIFlags(nsIURI* aSourceURI, nsIURI* aTargetURI, nsIURI* aSourceBaseURI,
nsIURI* aTargetBaseURI, uint32_t aFlags); nsIURI* aTargetBaseURI, uint32_t aFlags);
// Returns the file URI whitelist, initializing it if it has not been
// initialized.
const nsTArray<nsCOMPtr<nsIURI>>& EnsureFileURIWhitelist();
nsCOMPtr<nsIPrincipal> mSystemPrincipal; nsCOMPtr<nsIPrincipal> mSystemPrincipal;
bool mPrefInitialized; bool mPrefInitialized;
bool mIsJavaScriptEnabled; bool mIsJavaScriptEnabled;
nsTArray<nsCOMPtr<nsIURI>> mFileURIWhitelist;
// List of URIs whose domains and sub-domains are whitelisted to allow
// access to file: URIs. Lazily initialized; isNothing() when not yet
// initialized.
mozilla::Maybe<nsTArray<nsCOMPtr<nsIURI>>> mFileURIWhitelist;
// This machinery controls new-style domain policies. The old-style // This machinery controls new-style domain policies. The old-style
// policy machinery will be removed soon. // policy machinery will be removed soon.

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

@ -95,22 +95,6 @@ cppunittests-remote:
endif # COMPILE_ENVIRONMENT endif # COMPILE_ENVIRONMENT
endif # CPP_UNIT_TESTS endif # CPP_UNIT_TESTS
.PHONY: check
ifdef PYTHON_UNIT_TESTS
RUN_PYTHON_UNIT_TESTS := $(addsuffix -run,$(PYTHON_UNIT_TESTS))
.PHONY: $(RUN_PYTHON_UNIT_TESTS)
check:: $(RUN_PYTHON_UNIT_TESTS)
$(RUN_PYTHON_UNIT_TESTS): %-run: %
@PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $<
endif # PYTHON_UNIT_TESTS
endif # ENABLE_TESTS endif # ENABLE_TESTS

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

@ -15,6 +15,7 @@ button {
padding-left: 20px; padding-left: 20px;
padding-right: 20px; padding-right: 20px;
min-width: 100px; min-width: 100px;
margin: 0 4px;
} }
/* Category panels */ /* Category panels */
@ -60,14 +61,12 @@ button {
min-height: 34px; min-height: 34px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: baseline; align-items: self-start;
} }
.target-icon { .target-icon {
height: 24px; height: 24px;
margin: 6px 5px 0 0; margin: 0 5px 0 0;
/* Override the icon alignment and center it using margin-top. */
align-self: flex-start;
} }
.target-icon:not([src]) { .target-icon:not([src]) {
@ -80,6 +79,7 @@ button {
.target { .target {
flex: 1; flex: 1;
margin-top: 2px;
/* This is silly: https://bugzilla.mozilla.org/show_bug.cgi?id=1086218#c4. */ /* This is silly: https://bugzilla.mozilla.org/show_bug.cgi?id=1086218#c4. */
min-width: 0; min-width: 0;
} }
@ -117,6 +117,37 @@ button {
margin-left: 8px; margin-left: 8px;
} }
.target-status {
box-sizing: border-box;
display: inline-block;
min-width: 50px;
margin: 4px 5px 0 0;
padding: 2px;
border-width: 1px;
border-style: solid;
font-size: 0.6em;
text-align: center;
}
.target-status-stopped {
border-color: grey;
background-color: lightgrey;
}
.target-status-running {
border-color: limegreen;
background-color: palegreen;
}
.target-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.addons-controls { .addons-controls {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

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

@ -47,7 +47,7 @@ module.exports = createClass({
src: target.icon src: target.icon
}), }),
dom.div({ className: "target" }, dom.div({ className: "target" },
dom.div({ className: "target-name" }, target.name) dom.div({ className: "target-name", title: target.name }, target.name)
), ),
dom.button({ dom.button({
className: "debug-button", className: "debug-button",

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

@ -42,6 +42,8 @@ module.exports = createClass({
client.addListener("workerListChanged", this.update); client.addListener("workerListChanged", this.update);
client.addListener("serviceWorkerRegistrationListChanged", this.update); client.addListener("serviceWorkerRegistrationListChanged", this.update);
client.addListener("processListChanged", this.update); client.addListener("processListChanged", this.update);
client.addListener("registration-changed", this.update);
this.update(); this.update();
}, },
@ -50,6 +52,7 @@ module.exports = createClass({
client.removeListener("processListChanged", this.update); client.removeListener("processListChanged", this.update);
client.removeListener("serviceWorkerRegistrationListChanged", this.update); client.removeListener("serviceWorkerRegistrationListChanged", this.update);
client.removeListener("workerListChanged", this.update); client.removeListener("workerListChanged", this.update);
client.removeListener("registration-changed", this.update);
}, },
update() { update() {
@ -62,7 +65,8 @@ module.exports = createClass({
name: form.url, name: form.url,
url: form.url, url: form.url,
scope: form.scope, scope: form.scope,
registrationActor: form.actor registrationActor: form.actor,
active: form.active
}); });
}); });
@ -75,16 +79,22 @@ module.exports = createClass({
}; };
switch (form.type) { switch (form.type) {
case Ci.nsIWorkerDebugger.TYPE_SERVICE: case Ci.nsIWorkerDebugger.TYPE_SERVICE:
for (let registration of workers.service) { let registration = this.getRegistrationForWorker(form, workers.service);
if (registration.scope === form.scope) { if (registration) {
// XXX: Race, sometimes a ServiceWorkerRegistrationInfo doesn't // XXX: Race, sometimes a ServiceWorkerRegistrationInfo doesn't
// have a scriptSpec, but its associated WorkerDebugger does. // have a scriptSpec, but its associated WorkerDebugger does.
if (!registration.url) { if (!registration.url) {
registration.name = registration.url = form.url; registration.name = registration.url = form.url;
}
registration.workerActor = form.actor;
break;
} }
registration.workerActor = form.actor;
} else {
// If a service worker registration could not be found, this means we are in
// e10s, and registrations are not forwarded to other processes until they
// reach the activated state. Augment the worker as a registration worker to
// display it in aboutdebugging.
worker.scope = form.scope;
worker.active = false;
workers.service.push(worker);
} }
break; break;
case Ci.nsIWorkerDebugger.TYPE_SHARED: case Ci.nsIWorkerDebugger.TYPE_SHARED:
@ -103,6 +113,15 @@ module.exports = createClass({
}); });
}, },
getRegistrationForWorker(form, registrations) {
for (let registration of registrations) {
if (registration.scope === form.scope) {
return registration;
}
}
return null;
},
render() { render() {
let { client, id } = this.props; let { client, id } = this.props;
let { workers } = this.state; let { workers } = this.state;

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

@ -25,15 +25,23 @@ module.exports = createClass({
componentDidMount() { componentDidMount() {
let { client } = this.props; let { client } = this.props;
client.addListener("push-subscription-modified", client.addListener("push-subscription-modified", this.onPushSubscriptionModified);
this.onPushSubscriptionModified);
this.updatePushSubscription(); this.updatePushSubscription();
}, },
componentDidUpdate(oldProps, oldState) {
let wasActive = oldProps.target.active;
if (!wasActive && this.isActive()) {
// While the service worker isn't active, any calls to `updatePushSubscription`
// won't succeed. If we just became active, make sure we didn't miss a push
// subscription change by updating it now.
this.updatePushSubscription();
}
},
componentWillUnmount() { componentWillUnmount() {
let { client } = this.props; let { client } = this.props;
client.removeListener("push-subscription-modified", client.removeListener("push-subscription-modified", this.onPushSubscriptionModified);
this.onPushSubscriptionModified);
}, },
debug() { debug() {
@ -47,8 +55,10 @@ module.exports = createClass({
}, },
push() { push() {
if (!this.isRunning()) { if (!this.isActive() || !this.isRunning()) {
// If the worker is not running, we can't push to it. // If the worker is not running, we can't push to it.
// If the worker is not active, the registration might be unavailable and the
// push will not succeed.
return; return;
} }
@ -60,8 +70,8 @@ module.exports = createClass({
}, },
start() { start() {
if (this.isRunning()) { if (!this.isActive() || this.isRunning()) {
// If the worker is already running, we can't start it. // If the worker is not active or if it is already running, we can't start it.
return; return;
} }
@ -88,6 +98,11 @@ module.exports = createClass({
}, },
updatePushSubscription() { updatePushSubscription() {
if (!this.props.target.registrationActor) {
// A valid registrationActor is needed to retrieve the push subscription.
return;
}
let { client, target } = this.props; let { client, target } = this.props;
client.request({ client.request({
to: target.registrationActor, to: target.registrationActor,
@ -102,10 +117,65 @@ module.exports = createClass({
return !!this.props.target.workerActor; return !!this.props.target.workerActor;
}, },
isActive() {
return this.props.target.active;
},
getServiceWorkerStatus() {
if (this.isActive() && this.isRunning()) {
return "running";
} else if (this.isActive()) {
return "stopped";
}
// We cannot get service worker registrations unless the registration is in
// ACTIVE state. Unable to know the actual state ("installing", "waiting"), we
// display a custom state "registering" for now. See Bug 1153292.
return "registering";
},
renderButtons() {
let pushButton = dom.button({
className: "push-button",
onClick: this.push
}, Strings.GetStringFromName("push"));
let debugButton = dom.button({
className: "debug-button",
onClick: this.debug,
disabled: this.props.debugDisabled
}, Strings.GetStringFromName("debug"));
let startButton = dom.button({
className: "start-button",
onClick: this.start,
}, Strings.GetStringFromName("start"));
if (this.isRunning()) {
if (this.isActive()) {
return [pushButton, debugButton];
}
// Only debug button is available if the service worker is not active.
return debugButton;
}
return startButton;
},
renderUnregisterLink() {
if (!this.isActive()) {
// If not active, there might be no registrationActor available.
return null;
}
return dom.a({
onClick: this.unregister,
className: "unregister-link"
}, Strings.GetStringFromName("unregister"));
},
render() { render() {
let { target, debugDisabled } = this.props; let { target } = this.props;
let { pushSubscription } = this.state; let { pushSubscription } = this.state;
let isRunning = this.isRunning(); let status = this.getServiceWorkerStatus();
return dom.div({ className: "target-container" }, return dom.div({ className: "target-container" },
dom.img({ dom.img({
@ -113,43 +183,31 @@ module.exports = createClass({
role: "presentation", role: "presentation",
src: target.icon src: target.icon
}), }),
dom.span({ className: `target-status target-status-${status}` },
Strings.GetStringFromName(status)),
dom.div({ className: "target" }, dom.div({ className: "target" },
dom.div({ className: "target-name" }, target.name), dom.div({ className: "target-name", title: target.name }, target.name),
dom.ul({ className: "target-details" }, dom.ul({ className: "target-details" },
(pushSubscription ? (pushSubscription ?
dom.li({ className: "target-detail" }, dom.li({ className: "target-detail" },
dom.strong(null, Strings.GetStringFromName("pushService")), dom.strong(null, Strings.GetStringFromName("pushService")),
dom.span({ className: "service-worker-push-url" }, dom.span({
pushSubscription.endpoint)) : className: "service-worker-push-url",
title: pushSubscription.endpoint
}, pushSubscription.endpoint)) :
null null
), ),
dom.li({ className: "target-detail" }, dom.li({ className: "target-detail" },
dom.strong(null, Strings.GetStringFromName("scope")), dom.strong(null, Strings.GetStringFromName("scope")),
dom.span({ className: "service-worker-scope" }, target.scope), dom.span({
dom.a({ className: "service-worker-scope",
onClick: this.unregister, title: target.scope
className: "unregister-link" }, target.scope),
}, Strings.GetStringFromName("unregister")) this.renderUnregisterLink()
) )
) )
), ),
(isRunning ? this.renderButtons()
[
dom.button({
className: "push-button",
onClick: this.push
}, Strings.GetStringFromName("push")),
dom.button({
className: "debug-button",
onClick: this.debug,
disabled: debugDisabled
}, Strings.GetStringFromName("debug"))
] :
dom.button({
className: "start-button",
onClick: this.start
}, Strings.GetStringFromName("start"))
)
); );
} }
}); });

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

@ -32,7 +32,7 @@ module.exports = createClass({
src: target.icon src: target.icon
}), }),
dom.div({ className: "target" }, dom.div({ className: "target" },
dom.div({ className: "target-name" }, target.name) dom.div({ className: "target-name", title: target.name }, target.name)
), ),
dom.button({ dom.button({
className: "debug-button", className: "debug-button",

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

@ -9,6 +9,8 @@ support-files =
addons/bug1273184.xpi addons/bug1273184.xpi
addons/test-devtools-webextension/* addons/test-devtools-webextension/*
addons/test-devtools-webextension-nobg/* addons/test-devtools-webextension-nobg/*
service-workers/delay-sw.html
service-workers/delay-sw.js
service-workers/empty-sw.html service-workers/empty-sw.html
service-workers/empty-sw.js service-workers/empty-sw.js
service-workers/push-sw.html service-workers/push-sw.html
@ -34,6 +36,7 @@ tags = webextensions
[browser_service_workers_push.js] [browser_service_workers_push.js]
[browser_service_workers_push_service.js] [browser_service_workers_push_service.js]
[browser_service_workers_start.js] [browser_service_workers_start.js]
[browser_service_workers_status.js]
[browser_service_workers_timeout.js] [browser_service_workers_timeout.js]
skip-if = true # Bug 1232931 skip-if = true # Bug 1232931
[browser_service_workers_unregister.js] [browser_service_workers_unregister.js]

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

@ -31,19 +31,13 @@ add_task(function* () {
ok(names.includes(SERVICE_WORKER), ok(names.includes(SERVICE_WORKER),
"The service worker url appears in the list: " + names); "The service worker url appears in the list: " + names);
// Finally, unregister the service worker itself
let aboutDebuggingUpdate = waitForMutation(serviceWorkersElement,
{ childList: true });
try { try {
yield unregisterServiceWorker(swTab); yield unregisterServiceWorker(swTab, serviceWorkersElement);
ok(true, "Service worker registration unregistered"); ok(true, "Service worker registration unregistered");
} catch (e) { } catch (e) {
ok(false, "SW not unregistered; " + e); ok(false, "SW not unregistered; " + e);
} }
yield aboutDebuggingUpdate;
// Check that the service worker disappeared from the UI // Check that the service worker disappeared from the UI
names = [...document.querySelectorAll("#service-workers .target-name")]; names = [...document.querySelectorAll("#service-workers .target-name")];
names = names.map(element => element.textContent); names = names.map(element => element.textContent);

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

@ -62,11 +62,15 @@ add_task(function* () {
yield waitForServiceWorkerRegistered(swTab); yield waitForServiceWorkerRegistered(swTab);
ok(true, "Service worker registration resolved"); ok(true, "Service worker registration resolved");
yield waitForServiceWorkerActivation(SERVICE_WORKER, document);
// Retrieve the Push button for the worker. // Retrieve the Push button for the worker.
let names = [...document.querySelectorAll("#service-workers .target-name")]; let names = [...document.querySelectorAll("#service-workers .target-name")];
let name = names.filter(element => element.textContent === SERVICE_WORKER)[0]; let name = names.filter(element => element.textContent === SERVICE_WORKER)[0];
ok(name, "Found the service worker in the list"); ok(name, "Found the service worker in the list");
let targetElement = name.parentNode.parentNode; let targetElement = name.parentNode.parentNode;
let pushBtn = targetElement.querySelector(".push-button"); let pushBtn = targetElement.querySelector(".push-button");
ok(pushBtn, "Found its push button"); ok(pushBtn, "Found its push button");
@ -88,7 +92,7 @@ add_task(function* () {
// Finally, unregister the service worker itself. // Finally, unregister the service worker itself.
try { try {
yield unregisterServiceWorker(swTab); yield unregisterServiceWorker(swTab, serviceWorkersElement);
ok(true, "Service worker registration unregistered"); ok(true, "Service worker registration unregistered");
} catch (e) { } catch (e) {
ok(false, "SW not unregistered; " + e); ok(false, "SW not unregistered; " + e);

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

@ -72,16 +72,23 @@ add_task(function* () {
// Check that the service worker appears in the UI. // Check that the service worker appears in the UI.
assertHasTarget(true, document, "service-workers", SERVICE_WORKER); assertHasTarget(true, document, "service-workers", SERVICE_WORKER);
yield waitForServiceWorkerActivation(SERVICE_WORKER, document);
// Wait for the service worker details to update. // Wait for the service worker details to update.
let names = [...document.querySelectorAll("#service-workers .target-name")]; let names = [...document.querySelectorAll("#service-workers .target-name")];
let name = names.filter(element => element.textContent === SERVICE_WORKER)[0]; let name = names.filter(element => element.textContent === SERVICE_WORKER)[0];
ok(name, "Found the service worker in the list"); ok(name, "Found the service worker in the list");
let targetContainer = name.parentNode.parentNode; let targetContainer = name.parentNode.parentNode;
let targetDetailsElement = targetContainer.querySelector(".target-details"); let targetDetailsElement = targetContainer.querySelector(".target-details");
yield waitForMutation(targetDetailsElement, { childList: true });
// Retrieve the push subscription endpoint URL, and verify it looks good. // Retrieve the push subscription endpoint URL, and verify it looks good.
let pushURL = targetContainer.querySelector(".service-worker-push-url"); let pushURL = targetContainer.querySelector(".service-worker-push-url");
if (!pushURL) {
yield waitForMutation(targetDetailsElement, { childList: true });
pushURL = targetContainer.querySelector(".service-worker-push-url");
}
ok(pushURL, "Found the push service URL in the service worker details"); ok(pushURL, "Found the push service URL in the service worker details");
is(pushURL.textContent, FAKE_ENDPOINT, "The push service URL looks correct"); is(pushURL.textContent, FAKE_ENDPOINT, "The push service URL looks correct");
@ -97,11 +104,12 @@ add_task(function* () {
"The push service URL should be removed"); "The push service URL should be removed");
// Finally, unregister the service worker itself. // Finally, unregister the service worker itself.
yield unregisterServiceWorker(swTab).then(() => { try {
yield unregisterServiceWorker(swTab, serviceWorkersElement);
ok(true, "Service worker registration unregistered"); ok(true, "Service worker registration unregistered");
}).catch(function (e) { } catch (e) {
ok(false, "Service worker not unregistered; " + e); ok(false, "SW not unregistered; " + e);
}); }
info("Unmock the push service"); info("Unmock the push service");
PushService.service = null; PushService.service = null;

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

@ -47,6 +47,8 @@ add_task(function* () {
yield waitForServiceWorkerRegistered(swTab); yield waitForServiceWorkerRegistered(swTab);
ok(true, "Service worker registration resolved"); ok(true, "Service worker registration resolved");
yield waitForServiceWorkerActivation(SERVICE_WORKER, document);
// Retrieve the Target element corresponding to the service worker. // Retrieve the Target element corresponding to the service worker.
let names = [...document.querySelectorAll("#service-workers .target-name")]; let names = [...document.querySelectorAll("#service-workers .target-name")];
let name = names.filter(element => element.textContent === SERVICE_WORKER)[0]; let name = names.filter(element => element.textContent === SERVICE_WORKER)[0];
@ -82,7 +84,7 @@ add_task(function* () {
// Finally, unregister the service worker itself. // Finally, unregister the service worker itself.
try { try {
yield unregisterServiceWorker(swTab); yield unregisterServiceWorker(swTab, serviceWorkersElement);
ok(true, "Service worker registration unregistered"); ok(true, "Service worker registration unregistered");
} catch (e) { } catch (e) {
ok(false, "SW not unregistered; " + e); ok(false, "SW not unregistered; " + e);

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

@ -0,0 +1,67 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Service workers can't be loaded from chrome://,
// but http:// is ok with dom.serviceWorkers.testing.enabled turned on.
const SERVICE_WORKER = URL_ROOT + "service-workers/delay-sw.js";
const TAB_URL = URL_ROOT + "service-workers/delay-sw.html";
const SW_TIMEOUT = 2000;
requestLongerTimeout(2);
add_task(function* () {
yield SpecialPowers.pushPrefEnv({
"set": [
// Accept workers from mochitest's http.
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.idle_timeout", SW_TIMEOUT],
["dom.serviceWorkers.idle_extended_timeout", SW_TIMEOUT],
]
});
let { tab, document } = yield openAboutDebugging("workers");
// Listen for mutations in the service-workers list.
let serviceWorkersElement = getServiceWorkerList(document);
let onMutation = waitForMutation(serviceWorkersElement, { childList: true });
let swTab = yield addTab(TAB_URL);
info("Make the test page notify us when the service worker sends a message.");
// Wait for the service-workers list to update.
yield onMutation;
// Check that the service worker appears in the UI
let names = [...document.querySelectorAll("#service-workers .target-name")];
let name = names.filter(element => element.textContent === SERVICE_WORKER)[0];
ok(name, "Found the service worker in the list");
let targetElement = name.parentNode.parentNode;
let status = targetElement.querySelector(".target-status");
is(status.textContent, "Registering", "Service worker is currently registering");
yield waitForMutation(serviceWorkersElement, { childList: true, subtree: true });
is(status.textContent, "Running", "Service worker is currently running");
yield waitForMutation(serviceWorkersElement, { attributes: true, subtree: true });
is(status.textContent, "Stopped", "Service worker is currently stopped");
try {
yield unregisterServiceWorker(swTab, serviceWorkersElement);
ok(true, "Service worker unregistered");
} catch (e) {
ok(false, "Service worker not unregistered; " + e);
}
// Check that the service worker disappeared from the UI
names = [...document.querySelectorAll("#service-workers .target-name")];
names = names.map(element => element.textContent);
ok(!names.includes(SERVICE_WORKER),
"The service worker url is no longer in the list: " + names);
yield removeTab(swTab);
yield closeAboutDebugging(tab);
});

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

@ -77,15 +77,12 @@ add_task(function* () {
// Finally, unregister the service worker itself. // Finally, unregister the service worker itself.
try { try {
yield unregisterServiceWorker(swTab); yield unregisterServiceWorker(swTab, serviceWorkersElement);
ok(true, "Service worker registration unregistered"); ok(true, "Service worker registration unregistered");
} catch (e) { } catch (e) {
ok(false, "SW not unregistered; " + e); ok(false, "SW not unregistered; " + e);
} }
// Now ensure that the worker registration is correctly removed.
// The list should update once the registration is destroyed.
yield waitForMutation(serviceWorkersElement, { childList: true });
assertHasTarget(false, document, "service-workers", SERVICE_WORKER); assertHasTarget(false, document, "service-workers", SERVICE_WORKER);
yield removeTab(swTab); yield removeTab(swTab);

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

@ -39,6 +39,8 @@ add_task(function* () {
// Check that the service worker appears in the UI. // Check that the service worker appears in the UI.
assertHasTarget(true, document, "service-workers", SERVICE_WORKER); assertHasTarget(true, document, "service-workers", SERVICE_WORKER);
yield waitForServiceWorkerActivation(SERVICE_WORKER, document);
info("Ensure that the registration resolved before trying to interact with " + info("Ensure that the registration resolved before trying to interact with " +
"the service worker."); "the service worker.");
yield waitForServiceWorkerRegistered(swTab); yield waitForServiceWorkerRegistered(swTab);

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

@ -6,7 +6,8 @@
installAddon, uninstallAddon, waitForMutation, assertHasTarget, installAddon, uninstallAddon, waitForMutation, assertHasTarget,
getServiceWorkerList, getTabList, openPanel, waitForInitialAddonList, getServiceWorkerList, getTabList, openPanel, waitForInitialAddonList,
waitForServiceWorkerRegistered, unregisterServiceWorker, waitForServiceWorkerRegistered, unregisterServiceWorker,
waitForDelayedStartupFinished, setupTestAboutDebuggingWebExtension */ waitForDelayedStartupFinished, setupTestAboutDebuggingWebExtension,
waitForServiceWorkerActivation */
/* import-globals-from ../../framework/test/shared-head.js */ /* import-globals-from ../../framework/test/shared-head.js */
"use strict"; "use strict";
@ -259,17 +260,22 @@ function waitForServiceWorkerRegistered(tab) {
/** /**
* Asks the service worker within the test page to unregister, and returns a * Asks the service worker within the test page to unregister, and returns a
* promise that will resolve when it has successfully unregistered itself. * promise that will resolve when it has successfully unregistered itself and the
* about:debugging UI has fully processed this update.
*
* @param {Tab} tab * @param {Tab} tab
* @param {Node} serviceWorkersElement
* @return {Promise} Resolves when the service worker is unregistered. * @return {Promise} Resolves when the service worker is unregistered.
*/ */
function unregisterServiceWorker(tab) { function* unregisterServiceWorker(tab, serviceWorkersElement) {
return ContentTask.spawn(tab.linkedBrowser, {}, function* () { let onMutation = waitForMutation(serviceWorkersElement, { childList: true });
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
// Retrieve the `sw` promise created in the html page // Retrieve the `sw` promise created in the html page
let { sw } = content.wrappedJSObject; let { sw } = content.wrappedJSObject;
let registration = yield sw; let registration = yield sw;
yield registration.unregister(); yield registration.unregister();
}); });
return onMutation;
} }
/** /**
@ -326,3 +332,20 @@ function* setupTestAboutDebuggingWebExtension(name, path) {
return { tab, document, debugBtn }; return { tab, document, debugBtn };
} }
/**
* Wait for aboutdebugging to be notified about the activation of the service worker
* corresponding to the provided service worker url.
*/
function* waitForServiceWorkerActivation(swUrl, document) {
let serviceWorkersElement = getServiceWorkerList(document);
let names = serviceWorkersElement.querySelectorAll(".target-name");
let name = [...names].filter(element => element.textContent === swUrl)[0];
let targetElement = name.parentNode.parentNode;
let targetStatus = targetElement.querySelector(".target-status");
while (targetStatus.textContent === "Registering") {
// Wait for the status to leave the "registering" stage.
yield waitForMutation(serviceWorkersElement, { childList: true, subtree: true });
}
}

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

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Service worker test</title>
</head>
<body>
<script type="text/javascript">
"use strict";
var sw = navigator.serviceWorker.register("delay-sw.js");
sw.then(
function () {
dump("SW registered\n");
},
function (e) {
dump("SW not registered: " + e + "\n");
}
);
</script>
</body>
</html>

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

@ -0,0 +1,17 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env worker */
"use strict";
function wait(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
// Wait for one second to switch from installing to installed.
self.addEventListener("install", function (event) {
event.waitUntil(wait(1000));
});

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

@ -71,6 +71,20 @@ serviceWorkers = Service Workers
sharedWorkers = Shared Workers sharedWorkers = Shared Workers
otherWorkers = Other Workers otherWorkers = Other Workers
# LOCALIZATION NOTE (running):
# This string is displayed as the state of a service worker in RUNNING state.
running = Running
# LOCALIZATION NOTE (stopped):
# This string is displayed as the state of a service worker in STOPPED state.
stopped = Stopped
# LOCALIZATION NOTE (registering):
# This string is displayed as the state of a service worker for which no service worker
# registration could be found yet. Only active registrations are visible from
# about:debugging, so such service workers are considered as registering.
registering = Registering
# LOCALIZATION NOTE (tabs): # LOCALIZATION NOTE (tabs):
# This string is displayed as a header of the about:debugging#tabs page. # This string is displayed as a header of the about:debugging#tabs page.
tabs = Tabs tabs = Tabs

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

@ -10,6 +10,7 @@ support-files =
browser_devices.json browser_devices.json
doc_options-view.xul doc_options-view.xul
head.js head.js
helper_color_data.js
helper_html_tooltip.js helper_html_tooltip.js
helper_inplace_editor.js helper_inplace_editor.js
html-mdn-css-basic-testing.html html-mdn-css-basic-testing.html

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

@ -3,6 +3,9 @@
const TEST_URI = "data:text/html;charset=utf-8,browser_css_color.js"; const TEST_URI = "data:text/html;charset=utf-8,browser_css_color.js";
var {colorUtils} = require("devtools/shared/css/color"); var {colorUtils} = require("devtools/shared/css/color");
/* global getFixtureColorData */
loadHelperScript("helper_color_data.js");
var origColorUnit; var origColorUnit;
add_task(function* () { add_task(function* () {
@ -26,7 +29,7 @@ function createTestCanvas(doc) {
} }
function testColorUtils(canvas) { function testColorUtils(canvas) {
let data = getTestData(); let data = getFixtureColorData();
for (let {authored, name, hex, hsl, rgb} of data) { for (let {authored, name, hex, hsl, rgb} of data) {
let color = new colorUtils.CssColor(authored); let color = new colorUtils.CssColor(authored);
@ -111,8 +114,8 @@ function testSetAlpha() {
["hex", "#f0f", 0.2, "rgba(255, 0, 255, 0.2)"], ["hex", "#f0f", 0.2, "rgba(255, 0, 255, 0.2)"],
["rgba", "rgba(120, 34, 23, 1)", 0.25, "rgba(120, 34, 23, 0.25)"], ["rgba", "rgba(120, 34, 23, 1)", 0.25, "rgba(120, 34, 23, 0.25)"],
["rgb", "rgb(120, 34, 23)", 0.25, "rgba(120, 34, 23, 0.25)"], ["rgb", "rgb(120, 34, 23)", 0.25, "rgba(120, 34, 23, 0.25)"],
["hsl", "hsl(208, 100%, 97%)", 0.75, "rgba(239, 247, 255, 0.75)"], ["hsl", "hsl(208, 100%, 97%)", 0.75, "rgba(240, 248, 255, 0.75)"],
["hsla", "hsla(208, 100%, 97%, 1)", 0.75, "rgba(239, 247, 255, 0.75)"], ["hsla", "hsla(208, 100%, 97%, 1)", 0.75, "rgba(240, 248, 255, 0.75)"],
["alphahex", "#f08f", 0.6, "rgba(255, 0, 136, 0.6)"], ["alphahex", "#f08f", 0.6, "rgba(255, 0, 136, 0.6)"],
["longalphahex", "#00ff80ff", 0.2, "rgba(0, 255, 128, 0.2)"] ["longalphahex", "#00ff80ff", 0.2, "rgba(0, 255, 128, 0.2)"]
]; ];
@ -129,170 +132,3 @@ function testSetAlpha() {
is(colorUtils.setAlpha("#fff"), "rgba(255, 255, 255, 1)", "sets alpha to 1 if invalid."); is(colorUtils.setAlpha("#fff"), "rgba(255, 255, 255, 1)", "sets alpha to 1 if invalid.");
} }
function getTestData() {
return [
{authored: "aliceblue", name: "aliceblue", hex: "#f0f8ff", hsl: "hsl(208, 100%, 97%)", rgb: "rgb(240, 248, 255)"},
{authored: "antiquewhite", name: "antiquewhite", hex: "#faebd7", hsl: "hsl(34, 78%, 91%)", rgb: "rgb(250, 235, 215)"},
{authored: "aqua", name: "aqua", hex: "#0ff", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)"},
{authored: "aquamarine", name: "aquamarine", hex: "#7fffd4", hsl: "hsl(160, 100%, 75%)", rgb: "rgb(127, 255, 212)"},
{authored: "azure", name: "azure", hex: "#f0ffff", hsl: "hsl(180, 100%, 97%)", rgb: "rgb(240, 255, 255)"},
{authored: "beige", name: "beige", hex: "#f5f5dc", hsl: "hsl(60, 56%, 91%)", rgb: "rgb(245, 245, 220)"},
{authored: "bisque", name: "bisque", hex: "#ffe4c4", hsl: "hsl(33, 100%, 88%)", rgb: "rgb(255, 228, 196)"},
{authored: "black", name: "black", hex: "#000", hsl: "hsl(0, 0%, 0%)", rgb: "rgb(0, 0, 0)"},
{authored: "blanchedalmond", name: "blanchedalmond", hex: "#ffebcd", hsl: "hsl(36, 100%, 90%)", rgb: "rgb(255, 235, 205)"},
{authored: "blue", name: "blue", hex: "#00f", hsl: "hsl(240, 100%, 50%)", rgb: "rgb(0, 0, 255)"},
{authored: "blueviolet", name: "blueviolet", hex: "#8a2be2", hsl: "hsl(271, 76%, 53%)", rgb: "rgb(138, 43, 226)"},
{authored: "brown", name: "brown", hex: "#a52a2a", hsl: "hsl(0, 59%, 41%)", rgb: "rgb(165, 42, 42)"},
{authored: "burlywood", name: "burlywood", hex: "#deb887", hsl: "hsl(34, 57%, 70%)", rgb: "rgb(222, 184, 135)"},
{authored: "cadetblue", name: "cadetblue", hex: "#5f9ea0", hsl: "hsl(182, 25%, 50%)", rgb: "rgb(95, 158, 160)"},
{authored: "chartreuse", name: "chartreuse", hex: "#7fff00", hsl: "hsl(90, 100%, 50%)", rgb: "rgb(127, 255, 0)"},
{authored: "chocolate", name: "chocolate", hex: "#d2691e", hsl: "hsl(25, 75%, 47%)", rgb: "rgb(210, 105, 30)"},
{authored: "coral", name: "coral", hex: "#ff7f50", hsl: "hsl(16, 100%, 66%)", rgb: "rgb(255, 127, 80)"},
{authored: "cornflowerblue", name: "cornflowerblue", hex: "#6495ed", hsl: "hsl(219, 79%, 66%)", rgb: "rgb(100, 149, 237)"},
{authored: "cornsilk", name: "cornsilk", hex: "#fff8dc", hsl: "hsl(48, 100%, 93%)", rgb: "rgb(255, 248, 220)"},
{authored: "crimson", name: "crimson", hex: "#dc143c", hsl: "hsl(348, 83%, 47%)", rgb: "rgb(220, 20, 60)"},
{authored: "cyan", name: "aqua", hex: "#0ff", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)"},
{authored: "darkblue", name: "darkblue", hex: "#00008b", hsl: "hsl(240, 100%, 27%)", rgb: "rgb(0, 0, 139)"},
{authored: "darkcyan", name: "darkcyan", hex: "#008b8b", hsl: "hsl(180, 100%, 27%)", rgb: "rgb(0, 139, 139)"},
{authored: "darkgoldenrod", name: "darkgoldenrod", hex: "#b8860b", hsl: "hsl(43, 89%, 38%)", rgb: "rgb(184, 134, 11)"},
{authored: "darkgray", name: "darkgray", hex: "#a9a9a9", hsl: "hsl(0, 0%, 66%)", rgb: "rgb(169, 169, 169)"},
{authored: "darkgreen", name: "darkgreen", hex: "#006400", hsl: "hsl(120, 100%, 20%)", rgb: "rgb(0, 100, 0)"},
{authored: "darkgrey", name: "darkgray", hex: "#a9a9a9", hsl: "hsl(0, 0%, 66%)", rgb: "rgb(169, 169, 169)"},
{authored: "darkkhaki", name: "darkkhaki", hex: "#bdb76b", hsl: "hsl(56, 38%, 58%)", rgb: "rgb(189, 183, 107)"},
{authored: "darkmagenta", name: "darkmagenta", hex: "#8b008b", hsl: "hsl(300, 100%, 27%)", rgb: "rgb(139, 0, 139)"},
{authored: "darkolivegreen", name: "darkolivegreen", hex: "#556b2f", hsl: "hsl(82, 39%, 30%)", rgb: "rgb(85, 107, 47)"},
{authored: "darkorange", name: "darkorange", hex: "#ff8c00", hsl: "hsl(33, 100%, 50%)", rgb: "rgb(255, 140, 0)"},
{authored: "darkorchid", name: "darkorchid", hex: "#9932cc", hsl: "hsl(280, 61%, 50%)", rgb: "rgb(153, 50, 204)"},
{authored: "darkred", name: "darkred", hex: "#8b0000", hsl: "hsl(0, 100%, 27%)", rgb: "rgb(139, 0, 0)"},
{authored: "darksalmon", name: "darksalmon", hex: "#e9967a", hsl: "hsl(15, 72%, 70%)", rgb: "rgb(233, 150, 122)"},
{authored: "darkseagreen", name: "darkseagreen", hex: "#8fbc8f", hsl: "hsl(120, 25%, 65%)", rgb: "rgb(143, 188, 143)"},
{authored: "darkslateblue", name: "darkslateblue", hex: "#483d8b", hsl: "hsl(248, 39%, 39%)", rgb: "rgb(72, 61, 139)"},
{authored: "darkslategray", name: "darkslategray", hex: "#2f4f4f", hsl: "hsl(180, 25%, 25%)", rgb: "rgb(47, 79, 79)"},
{authored: "darkslategrey", name: "darkslategray", hex: "#2f4f4f", hsl: "hsl(180, 25%, 25%)", rgb: "rgb(47, 79, 79)"},
{authored: "darkturquoise", name: "darkturquoise", hex: "#00ced1", hsl: "hsl(181, 100%, 41%)", rgb: "rgb(0, 206, 209)"},
{authored: "darkviolet", name: "darkviolet", hex: "#9400d3", hsl: "hsl(282, 100%, 41%)", rgb: "rgb(148, 0, 211)"},
{authored: "deeppink", name: "deeppink", hex: "#ff1493", hsl: "hsl(328, 100%, 54%)", rgb: "rgb(255, 20, 147)"},
{authored: "deepskyblue", name: "deepskyblue", hex: "#00bfff", hsl: "hsl(195, 100%, 50%)", rgb: "rgb(0, 191, 255)"},
{authored: "dimgray", name: "dimgray", hex: "#696969", hsl: "hsl(0, 0%, 41%)", rgb: "rgb(105, 105, 105)"},
{authored: "dodgerblue", name: "dodgerblue", hex: "#1e90ff", hsl: "hsl(210, 100%, 56%)", rgb: "rgb(30, 144, 255)"},
{authored: "firebrick", name: "firebrick", hex: "#b22222", hsl: "hsl(0, 68%, 42%)", rgb: "rgb(178, 34, 34)"},
{authored: "floralwhite", name: "floralwhite", hex: "#fffaf0", hsl: "hsl(40, 100%, 97%)", rgb: "rgb(255, 250, 240)"},
{authored: "forestgreen", name: "forestgreen", hex: "#228b22", hsl: "hsl(120, 61%, 34%)", rgb: "rgb(34, 139, 34)"},
{authored: "fuchsia", name: "fuchsia", hex: "#f0f", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)"},
{authored: "gainsboro", name: "gainsboro", hex: "#dcdcdc", hsl: "hsl(0, 0%, 86%)", rgb: "rgb(220, 220, 220)"},
{authored: "ghostwhite", name: "ghostwhite", hex: "#f8f8ff", hsl: "hsl(240, 100%, 99%)", rgb: "rgb(248, 248, 255)"},
{authored: "gold", name: "gold", hex: "#ffd700", hsl: "hsl(51, 100%, 50%)", rgb: "rgb(255, 215, 0)"},
{authored: "goldenrod", name: "goldenrod", hex: "#daa520", hsl: "hsl(43, 74%, 49%)", rgb: "rgb(218, 165, 32)"},
{authored: "gray", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50%)", rgb: "rgb(128, 128, 128)"},
{authored: "green", name: "green", hex: "#008000", hsl: "hsl(120, 100%, 25%)", rgb: "rgb(0, 128, 0)"},
{authored: "greenyellow", name: "greenyellow", hex: "#adff2f", hsl: "hsl(84, 100%, 59%)", rgb: "rgb(173, 255, 47)"},
{authored: "grey", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50%)", rgb: "rgb(128, 128, 128)"},
{authored: "honeydew", name: "honeydew", hex: "#f0fff0", hsl: "hsl(120, 100%, 97%)", rgb: "rgb(240, 255, 240)"},
{authored: "hotpink", name: "hotpink", hex: "#ff69b4", hsl: "hsl(330, 100%, 71%)", rgb: "rgb(255, 105, 180)"},
{authored: "indianred", name: "indianred", hex: "#cd5c5c", hsl: "hsl(0, 53%, 58%)", rgb: "rgb(205, 92, 92)"},
{authored: "indigo", name: "indigo", hex: "#4b0082", hsl: "hsl(275, 100%, 25%)", rgb: "rgb(75, 0, 130)"},
{authored: "ivory", name: "ivory", hex: "#fffff0", hsl: "hsl(60, 100%, 97%)", rgb: "rgb(255, 255, 240)"},
{authored: "khaki", name: "khaki", hex: "#f0e68c", hsl: "hsl(54, 77%, 75%)", rgb: "rgb(240, 230, 140)"},
{authored: "lavender", name: "lavender", hex: "#e6e6fa", hsl: "hsl(240, 67%, 94%)", rgb: "rgb(230, 230, 250)"},
{authored: "lavenderblush", name: "lavenderblush", hex: "#fff0f5", hsl: "hsl(340, 100%, 97%)", rgb: "rgb(255, 240, 245)"},
{authored: "lawngreen", name: "lawngreen", hex: "#7cfc00", hsl: "hsl(90, 100%, 49%)", rgb: "rgb(124, 252, 0)"},
{authored: "lemonchiffon", name: "lemonchiffon", hex: "#fffacd", hsl: "hsl(54, 100%, 90%)", rgb: "rgb(255, 250, 205)"},
{authored: "lightblue", name: "lightblue", hex: "#add8e6", hsl: "hsl(195, 53%, 79%)", rgb: "rgb(173, 216, 230)"},
{authored: "lightcoral", name: "lightcoral", hex: "#f08080", hsl: "hsl(0, 79%, 72%)", rgb: "rgb(240, 128, 128)"},
{authored: "lightcyan", name: "lightcyan", hex: "#e0ffff", hsl: "hsl(180, 100%, 94%)", rgb: "rgb(224, 255, 255)"},
{authored: "lightgoldenrodyellow", name: "lightgoldenrodyellow", hex: "#fafad2", hsl: "hsl(60, 80%, 90%)", rgb: "rgb(250, 250, 210)"},
{authored: "lightgray", name: "lightgray", hex: "#d3d3d3", hsl: "hsl(0, 0%, 83%)", rgb: "rgb(211, 211, 211)"},
{authored: "lightgreen", name: "lightgreen", hex: "#90ee90", hsl: "hsl(120, 73%, 75%)", rgb: "rgb(144, 238, 144)"},
{authored: "lightgrey", name: "lightgray", hex: "#d3d3d3", hsl: "hsl(0, 0%, 83%)", rgb: "rgb(211, 211, 211)"},
{authored: "lightpink", name: "lightpink", hex: "#ffb6c1", hsl: "hsl(351, 100%, 86%)", rgb: "rgb(255, 182, 193)"},
{authored: "lightsalmon", name: "lightsalmon", hex: "#ffa07a", hsl: "hsl(17, 100%, 74%)", rgb: "rgb(255, 160, 122)"},
{authored: "lightseagreen", name: "lightseagreen", hex: "#20b2aa", hsl: "hsl(177, 70%, 41%)", rgb: "rgb(32, 178, 170)"},
{authored: "lightskyblue", name: "lightskyblue", hex: "#87cefa", hsl: "hsl(203, 92%, 75%)", rgb: "rgb(135, 206, 250)"},
{authored: "lightslategray", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14%, 53%)", rgb: "rgb(119, 136, 153)"},
{authored: "lightslategrey", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14%, 53%)", rgb: "rgb(119, 136, 153)"},
{authored: "lightsteelblue", name: "lightsteelblue", hex: "#b0c4de", hsl: "hsl(214, 41%, 78%)", rgb: "rgb(176, 196, 222)"},
{authored: "lightyellow", name: "lightyellow", hex: "#ffffe0", hsl: "hsl(60, 100%, 94%)", rgb: "rgb(255, 255, 224)"},
{authored: "lime", name: "lime", hex: "#0f0", hsl: "hsl(120, 100%, 50%)", rgb: "rgb(0, 255, 0)"},
{authored: "limegreen", name: "limegreen", hex: "#32cd32", hsl: "hsl(120, 61%, 50%)", rgb: "rgb(50, 205, 50)"},
{authored: "linen", name: "linen", hex: "#faf0e6", hsl: "hsl(30, 67%, 94%)", rgb: "rgb(250, 240, 230)"},
{authored: "magenta", name: "fuchsia", hex: "#f0f", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)"},
{authored: "maroon", name: "maroon", hex: "#800000", hsl: "hsl(0, 100%, 25%)", rgb: "rgb(128, 0, 0)"},
{authored: "mediumaquamarine", name: "mediumaquamarine", hex: "#66cdaa", hsl: "hsl(160, 51%, 60%)", rgb: "rgb(102, 205, 170)"},
{authored: "mediumblue", name: "mediumblue", hex: "#0000cd", hsl: "hsl(240, 100%, 40%)", rgb: "rgb(0, 0, 205)"},
{authored: "mediumorchid", name: "mediumorchid", hex: "#ba55d3", hsl: "hsl(288, 59%, 58%)", rgb: "rgb(186, 85, 211)"},
{authored: "mediumpurple", name: "mediumpurple", hex: "#9370db", hsl: "hsl(260, 60%, 65%)", rgb: "rgb(147, 112, 219)"},
{authored: "mediumseagreen", name: "mediumseagreen", hex: "#3cb371", hsl: "hsl(147, 50%, 47%)", rgb: "rgb(60, 179, 113)"},
{authored: "mediumslateblue", name: "mediumslateblue", hex: "#7b68ee", hsl: "hsl(249, 80%, 67%)", rgb: "rgb(123, 104, 238)"},
{authored: "mediumspringgreen", name: "mediumspringgreen", hex: "#00fa9a", hsl: "hsl(157, 100%, 49%)", rgb: "rgb(0, 250, 154)"},
{authored: "mediumturquoise", name: "mediumturquoise", hex: "#48d1cc", hsl: "hsl(178, 60%, 55%)", rgb: "rgb(72, 209, 204)"},
{authored: "mediumvioletred", name: "mediumvioletred", hex: "#c71585", hsl: "hsl(322, 81%, 43%)", rgb: "rgb(199, 21, 133)"},
{authored: "midnightblue", name: "midnightblue", hex: "#191970", hsl: "hsl(240, 64%, 27%)", rgb: "rgb(25, 25, 112)"},
{authored: "mintcream", name: "mintcream", hex: "#f5fffa", hsl: "hsl(150, 100%, 98%)", rgb: "rgb(245, 255, 250)"},
{authored: "mistyrose", name: "mistyrose", hex: "#ffe4e1", hsl: "hsl(6, 100%, 94%)", rgb: "rgb(255, 228, 225)"},
{authored: "moccasin", name: "moccasin", hex: "#ffe4b5", hsl: "hsl(38, 100%, 85%)", rgb: "rgb(255, 228, 181)"},
{authored: "navajowhite", name: "navajowhite", hex: "#ffdead", hsl: "hsl(36, 100%, 84%)", rgb: "rgb(255, 222, 173)"},
{authored: "navy", name: "navy", hex: "#000080", hsl: "hsl(240, 100%, 25%)", rgb: "rgb(0, 0, 128)"},
{authored: "oldlace", name: "oldlace", hex: "#fdf5e6", hsl: "hsl(39, 85%, 95%)", rgb: "rgb(253, 245, 230)"},
{authored: "olive", name: "olive", hex: "#808000", hsl: "hsl(60, 100%, 25%)", rgb: "rgb(128, 128, 0)"},
{authored: "olivedrab", name: "olivedrab", hex: "#6b8e23", hsl: "hsl(80, 60%, 35%)", rgb: "rgb(107, 142, 35)"},
{authored: "orange", name: "orange", hex: "#ffa500", hsl: "hsl(39, 100%, 50%)", rgb: "rgb(255, 165, 0)"},
{authored: "orangered", name: "orangered", hex: "#ff4500", hsl: "hsl(16, 100%, 50%)", rgb: "rgb(255, 69, 0)"},
{authored: "orchid", name: "orchid", hex: "#da70d6", hsl: "hsl(302, 59%, 65%)", rgb: "rgb(218, 112, 214)"},
{authored: "palegoldenrod", name: "palegoldenrod", hex: "#eee8aa", hsl: "hsl(55, 67%, 80%)", rgb: "rgb(238, 232, 170)"},
{authored: "palegreen", name: "palegreen", hex: "#98fb98", hsl: "hsl(120, 93%, 79%)", rgb: "rgb(152, 251, 152)"},
{authored: "paleturquoise", name: "paleturquoise", hex: "#afeeee", hsl: "hsl(180, 65%, 81%)", rgb: "rgb(175, 238, 238)"},
{authored: "palevioletred", name: "palevioletred", hex: "#db7093", hsl: "hsl(340, 60%, 65%)", rgb: "rgb(219, 112, 147)"},
{authored: "papayawhip", name: "papayawhip", hex: "#ffefd5", hsl: "hsl(37, 100%, 92%)", rgb: "rgb(255, 239, 213)"},
{authored: "peachpuff", name: "peachpuff", hex: "#ffdab9", hsl: "hsl(28, 100%, 86%)", rgb: "rgb(255, 218, 185)"},
{authored: "peru", name: "peru", hex: "#cd853f", hsl: "hsl(30, 59%, 53%)", rgb: "rgb(205, 133, 63)"},
{authored: "pink", name: "pink", hex: "#ffc0cb", hsl: "hsl(350, 100%, 88%)", rgb: "rgb(255, 192, 203)"},
{authored: "plum", name: "plum", hex: "#dda0dd", hsl: "hsl(300, 47%, 75%)", rgb: "rgb(221, 160, 221)"},
{authored: "powderblue", name: "powderblue", hex: "#b0e0e6", hsl: "hsl(187, 52%, 80%)", rgb: "rgb(176, 224, 230)"},
{authored: "purple", name: "purple", hex: "#800080", hsl: "hsl(300, 100%, 25%)", rgb: "rgb(128, 0, 128)"},
{authored: "rebeccapurple", name: "rebeccapurple", hex: "#639", hsl: "hsl(270, 50%, 40%)", rgb: "rgb(102, 51, 153)"},
{authored: "red", name: "red", hex: "#f00", hsl: "hsl(0, 100%, 50%)", rgb: "rgb(255, 0, 0)"},
{authored: "rosybrown", name: "rosybrown", hex: "#bc8f8f", hsl: "hsl(0, 25%, 65%)", rgb: "rgb(188, 143, 143)"},
{authored: "royalblue", name: "royalblue", hex: "#4169e1", hsl: "hsl(225, 73%, 57%)", rgb: "rgb(65, 105, 225)"},
{authored: "saddlebrown", name: "saddlebrown", hex: "#8b4513", hsl: "hsl(25, 76%, 31%)", rgb: "rgb(139, 69, 19)"},
{authored: "salmon", name: "salmon", hex: "#fa8072", hsl: "hsl(6, 93%, 71%)", rgb: "rgb(250, 128, 114)"},
{authored: "sandybrown", name: "sandybrown", hex: "#f4a460", hsl: "hsl(28, 87%, 67%)", rgb: "rgb(244, 164, 96)"},
{authored: "seagreen", name: "seagreen", hex: "#2e8b57", hsl: "hsl(146, 50%, 36%)", rgb: "rgb(46, 139, 87)"},
{authored: "seashell", name: "seashell", hex: "#fff5ee", hsl: "hsl(25, 100%, 97%)", rgb: "rgb(255, 245, 238)"},
{authored: "sienna", name: "sienna", hex: "#a0522d", hsl: "hsl(19, 56%, 40%)", rgb: "rgb(160, 82, 45)"},
{authored: "silver", name: "silver", hex: "#c0c0c0", hsl: "hsl(0, 0%, 75%)", rgb: "rgb(192, 192, 192)"},
{authored: "skyblue", name: "skyblue", hex: "#87ceeb", hsl: "hsl(197, 71%, 73%)", rgb: "rgb(135, 206, 235)"},
{authored: "slateblue", name: "slateblue", hex: "#6a5acd", hsl: "hsl(248, 53%, 58%)", rgb: "rgb(106, 90, 205)"},
{authored: "slategray", name: "slategray", hex: "#708090", hsl: "hsl(210, 13%, 50%)", rgb: "rgb(112, 128, 144)"},
{authored: "slategrey", name: "slategray", hex: "#708090", hsl: "hsl(210, 13%, 50%)", rgb: "rgb(112, 128, 144)"},
{authored: "snow", name: "snow", hex: "#fffafa", hsl: "hsl(0, 100%, 99%)", rgb: "rgb(255, 250, 250)"},
{authored: "springgreen", name: "springgreen", hex: "#00ff7f", hsl: "hsl(150, 100%, 50%)", rgb: "rgb(0, 255, 127)"},
{authored: "steelblue", name: "steelblue", hex: "#4682b4", hsl: "hsl(207, 44%, 49%)", rgb: "rgb(70, 130, 180)"},
{authored: "tan", name: "tan", hex: "#d2b48c", hsl: "hsl(34, 44%, 69%)", rgb: "rgb(210, 180, 140)"},
{authored: "teal", name: "teal", hex: "#008080", hsl: "hsl(180, 100%, 25%)", rgb: "rgb(0, 128, 128)"},
{authored: "thistle", name: "thistle", hex: "#d8bfd8", hsl: "hsl(300, 24%, 80%)", rgb: "rgb(216, 191, 216)"},
{authored: "tomato", name: "tomato", hex: "#ff6347", hsl: "hsl(9, 100%, 64%)", rgb: "rgb(255, 99, 71)"},
{authored: "turquoise", name: "turquoise", hex: "#40e0d0", hsl: "hsl(174, 72%, 56%)", rgb: "rgb(64, 224, 208)"},
{authored: "violet", name: "violet", hex: "#ee82ee", hsl: "hsl(300, 76%, 72%)", rgb: "rgb(238, 130, 238)"},
{authored: "wheat", name: "wheat", hex: "#f5deb3", hsl: "hsl(39, 77%, 83%)", rgb: "rgb(245, 222, 179)"},
{authored: "white", name: "white", hex: "#fff", hsl: "hsl(0, 0%, 100%)", rgb: "rgb(255, 255, 255)"},
{authored: "whitesmoke", name: "whitesmoke", hex: "#f5f5f5", hsl: "hsl(0, 0%, 96%)", rgb: "rgb(245, 245, 245)"},
{authored: "yellow", name: "yellow", hex: "#ff0", hsl: "hsl(60, 100%, 50%)", rgb: "rgb(255, 255, 0)"},
{authored: "yellowgreen", name: "yellowgreen", hex: "#9acd32", hsl: "hsl(80, 61%, 50%)", rgb: "rgb(154, 205, 50)"},
{authored: "rgba(0, 0, 0, 0)", name: "#0000", hex: "#0000", hsl: "hsla(0, 0%, 0%, 0)", rgb: "rgba(0, 0, 0, 0)"},
{authored: "hsla(0, 0%, 0%, 0)", name: "#0000", hex: "#0000", hsl: "hsla(0, 0%, 0%, 0)", rgb: "rgba(0, 0, 0, 0)"},
{authored: "rgba(50, 60, 70, 0.5)", name: "#323c4680", hex: "#323c4680", hsl: "hsla(210, 17%, 24%, 0.5)", rgb: "rgba(50, 60, 70, 0.5)"},
{authored: "rgba(0, 0, 0, 0.3)", name: "#0000004d", hex: "#0000004d", hsl: "hsla(0, 0%, 0%, 0.3)", rgb: "rgba(0, 0, 0, 0.3)"},
{authored: "rgba(255, 255, 255, 0.6)", name: "#fff9", hex: "#fff9", hsl: "hsla(0, 0%, 100%, 0.6)", rgb: "rgba(255, 255, 255, 0.6)"},
{authored: "rgba(127, 89, 45, 1)", name: "#7f592d", hex: "#7f592d", hsl: "hsl(32, 48%, 34%)", rgb: "rgb(127, 89, 45)"},
{authored: "hsla(19.304, 56%, 40%, 1)", name: "#9f512c", hex: "#9f512c", hsl: "hsl(19, 57%, 40%)", rgb: "rgb(159, 81, 44)"},
{authored: "#f089", name: "#f089", hex: "#f089", hsl: "hsla(328, 100%, 50%, 0.6)", rgb: "rgba(255, 0, 136, 0.6)"},
{authored: "#00ff8080", name: "#00ff8080", hex: "#00ff8080", hsl: "hsla(150, 100%, 50%, 0.5)", rgb: "rgba(0, 255, 128, 0.5)"},
{authored: "currentcolor", name: "currentcolor", hex: "currentcolor", hsl: "currentcolor", rgb: "currentcolor"},
{authored: "inherit", name: "inherit", hex: "inherit", hsl: "inherit", rgb: "inherit"},
{authored: "initial", name: "initial", hex: "initial", hsl: "initial", rgb: "initial"},
{authored: "invalidColor", name: "", hex: "", hsl: "", rgb: ""},
{authored: "transparent", name: "transparent", hex: "transparent", hsl: "transparent", rgb: "transparent"},
{authored: "unset", name: "unset", hex: "unset", hsl: "unset", rgb: "unset"}
];
}

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

@ -0,0 +1,171 @@
function getFixtureColorData() {
return [
{authored: "aliceblue", name: "aliceblue", hex: "#f0f8ff", hsl: "hsl(208, 100%, 97.1%)", rgb: "rgb(240, 248, 255)", cycle: 4},
{authored: "antiquewhite", name: "antiquewhite", hex: "#faebd7", hsl: "hsl(34.3, 77.8%, 91.2%)", rgb: "rgb(250, 235, 215)", cycle: 4},
{authored: "aqua", name: "aqua", hex: "#0ff", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)", cycle: 4},
{authored: "aquamarine", name: "aquamarine", hex: "#7fffd4", hsl: "hsl(159.8, 100%, 74.9%)", rgb: "rgb(127, 255, 212)", cycle: 4},
{authored: "azure", name: "azure", hex: "#f0ffff", hsl: "hsl(180, 100%, 97.1%)", rgb: "rgb(240, 255, 255)", cycle: 4},
{authored: "beige", name: "beige", hex: "#f5f5dc", hsl: "hsl(60, 55.6%, 91.2%)", rgb: "rgb(245, 245, 220)", cycle: 4},
{authored: "bisque", name: "bisque", hex: "#ffe4c4", hsl: "hsl(32.5, 100%, 88.4%)", rgb: "rgb(255, 228, 196)", cycle: 4},
{authored: "black", name: "black", hex: "#000", hsl: "hsl(0, 0%, 0%)", rgb: "rgb(0, 0, 0)", cycle: 4},
{authored: "blanchedalmond", name: "blanchedalmond", hex: "#ffebcd", hsl: "hsl(36, 100%, 90.2%)", rgb: "rgb(255, 235, 205)", cycle: 4},
{authored: "blue", name: "blue", hex: "#00f", hsl: "hsl(240, 100%, 50%)", rgb: "rgb(0, 0, 255)", cycle: 4},
{authored: "blueviolet", name: "blueviolet", hex: "#8a2be2", hsl: "hsl(271.1, 75.9%, 52.7%)", rgb: "rgb(138, 43, 226)", cycle: 4},
{authored: "brown", name: "brown", hex: "#a52a2a", hsl: "hsl(0, 59.4%, 40.6%)", rgb: "rgb(165, 42, 42)", cycle: 4},
{authored: "burlywood", name: "burlywood", hex: "#deb887", hsl: "hsl(33.8, 56.9%, 70%)", rgb: "rgb(222, 184, 135)", cycle: 4},
{authored: "cadetblue", name: "cadetblue", hex: "#5f9ea0", hsl: "hsl(181.8, 25.5%, 50%)", rgb: "rgb(95, 158, 160)", cycle: 4},
{authored: "chartreuse", name: "chartreuse", hex: "#7fff00", hsl: "hsl(90.1, 100%, 50%)", rgb: "rgb(127, 255, 0)", cycle: 4},
{authored: "chocolate", name: "chocolate", hex: "#d2691e", hsl: "hsl(25, 75%, 47.1%)", rgb: "rgb(210, 105, 30)", cycle: 4},
{authored: "coral", name: "coral", hex: "#ff7f50", hsl: "hsl(16.1, 100%, 65.7%)", rgb: "rgb(255, 127, 80)", cycle: 4},
{authored: "cornflowerblue", name: "cornflowerblue", hex: "#6495ed", hsl: "hsl(218.5, 79.2%, 66.1%)", rgb: "rgb(100, 149, 237)", cycle: 4},
{authored: "cornsilk", name: "cornsilk", hex: "#fff8dc", hsl: "hsl(48, 100%, 93.1%)", rgb: "rgb(255, 248, 220)", cycle: 4},
{authored: "crimson", name: "crimson", hex: "#dc143c", hsl: "hsl(348, 83.3%, 47.1%)", rgb: "rgb(220, 20, 60)", cycle: 4},
{authored: "cyan", name: "aqua", hex: "#0ff", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)", cycle: 4},
{authored: "darkblue", name: "darkblue", hex: "#00008b", hsl: "hsl(240, 100%, 27.3%)", rgb: "rgb(0, 0, 139)", cycle: 4},
{authored: "darkcyan", name: "darkcyan", hex: "#008b8b", hsl: "hsl(180, 100%, 27.3%)", rgb: "rgb(0, 139, 139)", cycle: 4},
{authored: "darkgoldenrod", name: "darkgoldenrod", hex: "#b8860b", hsl: "hsl(42.7, 88.7%, 38.2%)", rgb: "rgb(184, 134, 11)", cycle: 4},
{authored: "darkgray", name: "darkgray", hex: "#a9a9a9", hsl: "hsl(0, 0%, 66.3%)", rgb: "rgb(169, 169, 169)", cycle: 4},
{authored: "darkgreen", name: "darkgreen", hex: "#006400", hsl: "hsl(120, 100%, 19.6%)", rgb: "rgb(0, 100, 0)", cycle: 4},
{authored: "darkgrey", name: "darkgray", hex: "#a9a9a9", hsl: "hsl(0, 0%, 66.3%)", rgb: "rgb(169, 169, 169)", cycle: 4},
{authored: "darkkhaki", name: "darkkhaki", hex: "#bdb76b", hsl: "hsl(55.6, 38.3%, 58%)", rgb: "rgb(189, 183, 107)", cycle: 4},
{authored: "darkmagenta", name: "darkmagenta", hex: "#8b008b", hsl: "hsl(300, 100%, 27.3%)", rgb: "rgb(139, 0, 139)", cycle: 4},
{authored: "darkolivegreen", name: "darkolivegreen", hex: "#556b2f", hsl: "hsl(82, 39%, 30.2%)", rgb: "rgb(85, 107, 47)", cycle: 4},
{authored: "darkorange", name: "darkorange", hex: "#ff8c00", hsl: "hsl(32.9, 100%, 50%)", rgb: "rgb(255, 140, 0)", cycle: 4},
{authored: "darkorchid", name: "darkorchid", hex: "#9932cc", hsl: "hsl(280.1, 60.6%, 49.8%)", rgb: "rgb(153, 50, 204)", cycle: 4},
{authored: "darkred", name: "darkred", hex: "#8b0000", hsl: "hsl(0, 100%, 27.3%)", rgb: "rgb(139, 0, 0)", cycle: 4},
{authored: "darksalmon", name: "darksalmon", hex: "#e9967a", hsl: "hsl(15.1, 71.6%, 69.6%)", rgb: "rgb(233, 150, 122)", cycle: 4},
{authored: "darkseagreen", name: "darkseagreen", hex: "#8fbc8f", hsl: "hsl(120, 25.1%, 64.9%)", rgb: "rgb(143, 188, 143)", cycle: 4},
{authored: "darkslateblue", name: "darkslateblue", hex: "#483d8b", hsl: "hsl(248.5, 39%, 39.2%)", rgb: "rgb(72, 61, 139)", cycle: 4},
{authored: "darkslategray", name: "darkslategray", hex: "#2f4f4f", hsl: "hsl(180, 25.4%, 24.7%)", rgb: "rgb(47, 79, 79)", cycle: 4},
{authored: "darkslategrey", name: "darkslategray", hex: "#2f4f4f", hsl: "hsl(180, 25.4%, 24.7%)", rgb: "rgb(47, 79, 79)", cycle: 4},
{authored: "darkturquoise", name: "darkturquoise", hex: "#00ced1", hsl: "hsl(180.9, 100%, 41%)", rgb: "rgb(0, 206, 209)", cycle: 4},
{authored: "darkviolet", name: "darkviolet", hex: "#9400d3", hsl: "hsl(282.1, 100%, 41.4%)", rgb: "rgb(148, 0, 211)", cycle: 4},
{authored: "deeppink", name: "deeppink", hex: "#ff1493", hsl: "hsl(327.6, 100%, 53.9%)", rgb: "rgb(255, 20, 147)", cycle: 4},
{authored: "deepskyblue", name: "deepskyblue", hex: "#00bfff", hsl: "hsl(195.1, 100%, 50%)", rgb: "rgb(0, 191, 255)", cycle: 4},
{authored: "dimgray", name: "dimgray", hex: "#696969", hsl: "hsl(0, 0%, 41.2%)", rgb: "rgb(105, 105, 105)", cycle: 4},
{authored: "dodgerblue", name: "dodgerblue", hex: "#1e90ff", hsl: "hsl(209.6, 100%, 55.9%)", rgb: "rgb(30, 144, 255)", cycle: 4},
{authored: "firebrick", name: "firebrick", hex: "#b22222", hsl: "hsl(0, 67.9%, 41.6%)", rgb: "rgb(178, 34, 34)", cycle: 4},
{authored: "floralwhite", name: "floralwhite", hex: "#fffaf0", hsl: "hsl(40, 100%, 97.1%)", rgb: "rgb(255, 250, 240)", cycle: 4},
{authored: "forestgreen", name: "forestgreen", hex: "#228b22", hsl: "hsl(120, 60.7%, 33.9%)", rgb: "rgb(34, 139, 34)", cycle: 4},
{authored: "fuchsia", name: "fuchsia", hex: "#f0f", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)", cycle: 4},
{authored: "gainsboro", name: "gainsboro", hex: "#dcdcdc", hsl: "hsl(0, 0%, 86.3%)", rgb: "rgb(220, 220, 220)", cycle: 4},
{authored: "ghostwhite", name: "ghostwhite", hex: "#f8f8ff", hsl: "hsl(240, 100%, 98.6%)", rgb: "rgb(248, 248, 255)", cycle: 4},
{authored: "gold", name: "gold", hex: "#ffd700", hsl: "hsl(50.6, 100%, 50%)", rgb: "rgb(255, 215, 0)", cycle: 4},
{authored: "goldenrod", name: "goldenrod", hex: "#daa520", hsl: "hsl(42.9, 74.4%, 49%)", rgb: "rgb(218, 165, 32)", cycle: 4},
{authored: "gray", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50.2%)", rgb: "rgb(128, 128, 128)", cycle: 4},
{authored: "green", name: "green", hex: "#008000", hsl: "hsl(120, 100%, 25.1%)", rgb: "rgb(0, 128, 0)", cycle: 4},
{authored: "greenyellow", name: "greenyellow", hex: "#adff2f", hsl: "hsl(83.7, 100%, 59.2%)", rgb: "rgb(173, 255, 47)", cycle: 4},
{authored: "grey", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50.2%)", rgb: "rgb(128, 128, 128)", cycle: 4},
{authored: "honeydew", name: "honeydew", hex: "#f0fff0", hsl: "hsl(120, 100%, 97.1%)", rgb: "rgb(240, 255, 240)", cycle: 4},
{authored: "hotpink", name: "hotpink", hex: "#ff69b4", hsl: "hsl(330, 100%, 70.6%)", rgb: "rgb(255, 105, 180)", cycle: 4},
{authored: "indianred", name: "indianred", hex: "#cd5c5c", hsl: "hsl(0, 53.1%, 58.2%)", rgb: "rgb(205, 92, 92)", cycle: 4},
{authored: "indigo", name: "indigo", hex: "#4b0082", hsl: "hsl(274.6, 100%, 25.5%)", rgb: "rgb(75, 0, 130)", cycle: 4},
{authored: "ivory", name: "ivory", hex: "#fffff0", hsl: "hsl(60, 100%, 97.1%)", rgb: "rgb(255, 255, 240)", cycle: 4},
{authored: "khaki", name: "khaki", hex: "#f0e68c", hsl: "hsl(54, 76.9%, 74.5%)", rgb: "rgb(240, 230, 140)", cycle: 4},
{authored: "lavender", name: "lavender", hex: "#e6e6fa", hsl: "hsl(240, 66.7%, 94.1%)", rgb: "rgb(230, 230, 250)", cycle: 4},
{authored: "lavenderblush", name: "lavenderblush", hex: "#fff0f5", hsl: "hsl(340, 100%, 97.1%)", rgb: "rgb(255, 240, 245)", cycle: 4},
{authored: "lawngreen", name: "lawngreen", hex: "#7cfc00", hsl: "hsl(90.5, 100%, 49.4%)", rgb: "rgb(124, 252, 0)", cycle: 4},
{authored: "lemonchiffon", name: "lemonchiffon", hex: "#fffacd", hsl: "hsl(54, 100%, 90.2%)", rgb: "rgb(255, 250, 205)", cycle: 4},
{authored: "lightblue", name: "lightblue", hex: "#add8e6", hsl: "hsl(194.7, 53.3%, 79%)", rgb: "rgb(173, 216, 230)", cycle: 4},
{authored: "lightcoral", name: "lightcoral", hex: "#f08080", hsl: "hsl(0, 78.9%, 72.2%)", rgb: "rgb(240, 128, 128)", cycle: 4},
{authored: "lightcyan", name: "lightcyan", hex: "#e0ffff", hsl: "hsl(180, 100%, 93.9%)", rgb: "rgb(224, 255, 255)", cycle: 4},
{authored: "lightgoldenrodyellow", name: "lightgoldenrodyellow", hex: "#fafad2", hsl: "hsl(60, 80%, 90.2%)", rgb: "rgb(250, 250, 210)", cycle: 4},
{authored: "lightgray", name: "lightgray", hex: "#d3d3d3", hsl: "hsl(0, 0%, 82.7%)", rgb: "rgb(211, 211, 211)", cycle: 4},
{authored: "lightgreen", name: "lightgreen", hex: "#90ee90", hsl: "hsl(120, 73.4%, 74.9%)", rgb: "rgb(144, 238, 144)", cycle: 4},
{authored: "lightgrey", name: "lightgray", hex: "#d3d3d3", hsl: "hsl(0, 0%, 82.7%)", rgb: "rgb(211, 211, 211)", cycle: 4},
{authored: "lightpink", name: "lightpink", hex: "#ffb6c1", hsl: "hsl(351, 100%, 85.7%)", rgb: "rgb(255, 182, 193)", cycle: 4},
{authored: "lightsalmon", name: "lightsalmon", hex: "#ffa07a", hsl: "hsl(17.1, 100%, 73.9%)", rgb: "rgb(255, 160, 122)", cycle: 4},
{authored: "lightseagreen", name: "lightseagreen", hex: "#20b2aa", hsl: "hsl(176.7, 69.5%, 41.2%)", rgb: "rgb(32, 178, 170)", cycle: 4},
{authored: "lightskyblue", name: "lightskyblue", hex: "#87cefa", hsl: "hsl(203, 92%, 75.5%)", rgb: "rgb(135, 206, 250)", cycle: 4},
{authored: "lightslategray", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14.3%, 53.3%)", rgb: "rgb(119, 136, 153)", cycle: 4},
{authored: "lightslategrey", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14.3%, 53.3%)", rgb: "rgb(119, 136, 153)", cycle: 4},
{authored: "lightsteelblue", name: "lightsteelblue", hex: "#b0c4de", hsl: "hsl(213.9, 41.1%, 78%)", rgb: "rgb(176, 196, 222)", cycle: 4},
{authored: "lightyellow", name: "lightyellow", hex: "#ffffe0", hsl: "hsl(60, 100%, 93.9%)", rgb: "rgb(255, 255, 224)", cycle: 4},
{authored: "lime", name: "lime", hex: "#0f0", hsl: "hsl(120, 100%, 50%)", rgb: "rgb(0, 255, 0)", cycle: 4},
{authored: "limegreen", name: "limegreen", hex: "#32cd32", hsl: "hsl(120, 60.8%, 50%)", rgb: "rgb(50, 205, 50)", cycle: 4},
{authored: "linen", name: "linen", hex: "#faf0e6", hsl: "hsl(30, 66.7%, 94.1%)", rgb: "rgb(250, 240, 230)", cycle: 4},
{authored: "magenta", name: "fuchsia", hex: "#f0f", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)", cycle: 4},
{authored: "maroon", name: "maroon", hex: "#800000", hsl: "hsl(0, 100%, 25.1%)", rgb: "rgb(128, 0, 0)", cycle: 4},
{authored: "mediumaquamarine", name: "mediumaquamarine", hex: "#66cdaa", hsl: "hsl(159.6, 50.7%, 60.2%)", rgb: "rgb(102, 205, 170)", cycle: 4},
{authored: "mediumblue", name: "mediumblue", hex: "#0000cd", hsl: "hsl(240, 100%, 40.2%)", rgb: "rgb(0, 0, 205)", cycle: 4},
{authored: "mediumorchid", name: "mediumorchid", hex: "#ba55d3", hsl: "hsl(288.1, 58.9%, 58%)", rgb: "rgb(186, 85, 211)", cycle: 4},
{authored: "mediumpurple", name: "mediumpurple", hex: "#9370db", hsl: "hsl(259.6, 59.8%, 64.9%)", rgb: "rgb(147, 112, 219)", cycle: 4},
{authored: "mediumseagreen", name: "mediumseagreen", hex: "#3cb371", hsl: "hsl(146.7, 49.8%, 46.9%)", rgb: "rgb(60, 179, 113)", cycle: 4},
{authored: "mediumslateblue", name: "mediumslateblue", hex: "#7b68ee", hsl: "hsl(248.5, 79.8%, 67.1%)", rgb: "rgb(123, 104, 238)", cycle: 4},
{authored: "mediumspringgreen", name: "mediumspringgreen", hex: "#00fa9a", hsl: "hsl(157, 100%, 49%)", rgb: "rgb(0, 250, 154)", cycle: 4},
{authored: "mediumturquoise", name: "mediumturquoise", hex: "#48d1cc", hsl: "hsl(177.8, 59.8%, 55.1%)", rgb: "rgb(72, 209, 204)", cycle: 4},
{authored: "mediumvioletred", name: "mediumvioletred", hex: "#c71585", hsl: "hsl(322.2, 80.9%, 43.1%)", rgb: "rgb(199, 21, 133)", cycle: 4},
{authored: "midnightblue", name: "midnightblue", hex: "#191970", hsl: "hsl(240, 63.5%, 26.9%)", rgb: "rgb(25, 25, 112)", cycle: 4},
{authored: "mintcream", name: "mintcream", hex: "#f5fffa", hsl: "hsl(150, 100%, 98%)", rgb: "rgb(245, 255, 250)", cycle: 4},
{authored: "mistyrose", name: "mistyrose", hex: "#ffe4e1", hsl: "hsl(6, 100%, 94.1%)", rgb: "rgb(255, 228, 225)", cycle: 4},
{authored: "moccasin", name: "moccasin", hex: "#ffe4b5", hsl: "hsl(38.1, 100%, 85.5%)", rgb: "rgb(255, 228, 181)", cycle: 4},
{authored: "navajowhite", name: "navajowhite", hex: "#ffdead", hsl: "hsl(35.9, 100%, 83.9%)", rgb: "rgb(255, 222, 173)", cycle: 4},
{authored: "navy", name: "navy", hex: "#000080", hsl: "hsl(240, 100%, 25.1%)", rgb: "rgb(0, 0, 128)", cycle: 4},
{authored: "oldlace", name: "oldlace", hex: "#fdf5e6", hsl: "hsl(39.1, 85.2%, 94.7%)", rgb: "rgb(253, 245, 230)", cycle: 4},
{authored: "olive", name: "olive", hex: "#808000", hsl: "hsl(60, 100%, 25.1%)", rgb: "rgb(128, 128, 0)", cycle: 4},
{authored: "olivedrab", name: "olivedrab", hex: "#6b8e23", hsl: "hsl(79.6, 60.5%, 34.7%)", rgb: "rgb(107, 142, 35)", cycle: 4},
{authored: "orange", name: "orange", hex: "#ffa500", hsl: "hsl(38.8, 100%, 50%)", rgb: "rgb(255, 165, 0)", cycle: 4},
{authored: "orangered", name: "orangered", hex: "#ff4500", hsl: "hsl(16.2, 100%, 50%)", rgb: "rgb(255, 69, 0)", cycle: 4},
{authored: "orchid", name: "orchid", hex: "#da70d6", hsl: "hsl(302.3, 58.9%, 64.7%)", rgb: "rgb(218, 112, 214)", cycle: 4},
{authored: "palegoldenrod", name: "palegoldenrod", hex: "#eee8aa", hsl: "hsl(54.7, 66.7%, 80%)", rgb: "rgb(238, 232, 170)", cycle: 4},
{authored: "palegreen", name: "palegreen", hex: "#98fb98", hsl: "hsl(120, 92.5%, 79%)", rgb: "rgb(152, 251, 152)", cycle: 4},
{authored: "paleturquoise", name: "paleturquoise", hex: "#afeeee", hsl: "hsl(180, 64.9%, 81%)", rgb: "rgb(175, 238, 238)", cycle: 4},
{authored: "palevioletred", name: "palevioletred", hex: "#db7093", hsl: "hsl(340.4, 59.8%, 64.9%)", rgb: "rgb(219, 112, 147)", cycle: 4},
{authored: "papayawhip", name: "papayawhip", hex: "#ffefd5", hsl: "hsl(37.1, 100%, 91.8%)", rgb: "rgb(255, 239, 213)", cycle: 4},
{authored: "peachpuff", name: "peachpuff", hex: "#ffdab9", hsl: "hsl(28.3, 100%, 86.3%)", rgb: "rgb(255, 218, 185)", cycle: 4},
{authored: "peru", name: "peru", hex: "#cd853f", hsl: "hsl(29.6, 58.7%, 52.5%)", rgb: "rgb(205, 133, 63)", cycle: 4},
{authored: "pink", name: "pink", hex: "#ffc0cb", hsl: "hsl(349.5, 100%, 87.6%)", rgb: "rgb(255, 192, 203)", cycle: 4},
{authored: "plum", name: "plum", hex: "#dda0dd", hsl: "hsl(300, 47.3%, 74.7%)", rgb: "rgb(221, 160, 221)", cycle: 4},
{authored: "powderblue", name: "powderblue", hex: "#b0e0e6", hsl: "hsl(186.7, 51.9%, 79.6%)", rgb: "rgb(176, 224, 230)", cycle: 4},
{authored: "purple", name: "purple", hex: "#800080", hsl: "hsl(300, 100%, 25.1%)", rgb: "rgb(128, 0, 128)", cycle: 4},
{authored: "rebeccapurple", name: "rebeccapurple", hex: "#639", hsl: "hsl(270, 50%, 40%)", rgb: "rgb(102, 51, 153)", cycle: 4},
{authored: "red", name: "red", hex: "#f00", hsl: "hsl(0, 100%, 50%)", rgb: "rgb(255, 0, 0)", cycle: 4},
{authored: "rosybrown", name: "rosybrown", hex: "#bc8f8f", hsl: "hsl(0, 25.1%, 64.9%)", rgb: "rgb(188, 143, 143)", cycle: 4},
{authored: "royalblue", name: "royalblue", hex: "#4169e1", hsl: "hsl(225, 72.7%, 56.9%)", rgb: "rgb(65, 105, 225)", cycle: 4},
{authored: "saddlebrown", name: "saddlebrown", hex: "#8b4513", hsl: "hsl(25, 75.9%, 31%)", rgb: "rgb(139, 69, 19)", cycle: 4},
{authored: "salmon", name: "salmon", hex: "#fa8072", hsl: "hsl(6.2, 93.2%, 71.4%)", rgb: "rgb(250, 128, 114)", cycle: 4},
{authored: "sandybrown", name: "sandybrown", hex: "#f4a460", hsl: "hsl(27.6, 87.1%, 66.7%)", rgb: "rgb(244, 164, 96)", cycle: 4},
{authored: "seagreen", name: "seagreen", hex: "#2e8b57", hsl: "hsl(146.5, 50.3%, 36.3%)", rgb: "rgb(46, 139, 87)", cycle: 4},
{authored: "seashell", name: "seashell", hex: "#fff5ee", hsl: "hsl(24.7, 100%, 96.7%)", rgb: "rgb(255, 245, 238)", cycle: 4},
{authored: "sienna", name: "sienna", hex: "#a0522d", hsl: "hsl(19.3, 56.1%, 40.2%)", rgb: "rgb(160, 82, 45)", cycle: 4},
{authored: "silver", name: "silver", hex: "#c0c0c0", hsl: "hsl(0, 0%, 75.3%)", rgb: "rgb(192, 192, 192)", cycle: 4},
{authored: "skyblue", name: "skyblue", hex: "#87ceeb", hsl: "hsl(197.4, 71.4%, 72.5%)", rgb: "rgb(135, 206, 235)", cycle: 4},
{authored: "slateblue", name: "slateblue", hex: "#6a5acd", hsl: "hsl(248.3, 53.5%, 57.8%)", rgb: "rgb(106, 90, 205)", cycle: 4},
{authored: "slategray", name: "slategray", hex: "#708090", hsl: "hsl(210, 12.6%, 50.2%)", rgb: "rgb(112, 128, 144)", cycle: 4},
{authored: "slategrey", name: "slategray", hex: "#708090", hsl: "hsl(210, 12.6%, 50.2%)", rgb: "rgb(112, 128, 144)", cycle: 4},
{authored: "snow", name: "snow", hex: "#fffafa", hsl: "hsl(0, 100%, 99%)", rgb: "rgb(255, 250, 250)", cycle: 4},
{authored: "springgreen", name: "springgreen", hex: "#00ff7f", hsl: "hsl(149.9, 100%, 50%)", rgb: "rgb(0, 255, 127)", cycle: 4},
{authored: "steelblue", name: "steelblue", hex: "#4682b4", hsl: "hsl(207.3, 44%, 49%)", rgb: "rgb(70, 130, 180)", cycle: 4},
{authored: "tan", name: "tan", hex: "#d2b48c", hsl: "hsl(34.3, 43.7%, 68.6%)", rgb: "rgb(210, 180, 140)", cycle: 4},
{authored: "teal", name: "teal", hex: "#008080", hsl: "hsl(180, 100%, 25.1%)", rgb: "rgb(0, 128, 128)", cycle: 4},
{authored: "thistle", name: "thistle", hex: "#d8bfd8", hsl: "hsl(300, 24.3%, 79.8%)", rgb: "rgb(216, 191, 216)", cycle: 4},
{authored: "tomato", name: "tomato", hex: "#ff6347", hsl: "hsl(9.1, 100%, 63.9%)", rgb: "rgb(255, 99, 71)", cycle: 4},
{authored: "turquoise", name: "turquoise", hex: "#40e0d0", hsl: "hsl(174, 72.1%, 56.5%)", rgb: "rgb(64, 224, 208)", cycle: 4},
{authored: "violet", name: "violet", hex: "#ee82ee", hsl: "hsl(300, 76.1%, 72.2%)", rgb: "rgb(238, 130, 238)", cycle: 4},
{authored: "wheat", name: "wheat", hex: "#f5deb3", hsl: "hsl(39.1, 76.7%, 83.1%)", rgb: "rgb(245, 222, 179)", cycle: 4},
{authored: "white", name: "white", hex: "#fff", hsl: "hsl(0, 0%, 100%)", rgb: "rgb(255, 255, 255)", cycle: 4},
{authored: "whitesmoke", name: "whitesmoke", hex: "#f5f5f5", hsl: "hsl(0, 0%, 96.1%)", rgb: "rgb(245, 245, 245)", cycle: 4},
{authored: "yellow", name: "yellow", hex: "#ff0", hsl: "hsl(60, 100%, 50%)", rgb: "rgb(255, 255, 0)", cycle: 4},
{authored: "yellowgreen", name: "yellowgreen", hex: "#9acd32", hsl: "hsl(79.7, 60.8%, 50%)", rgb: "rgb(154, 205, 50)", cycle: 4},
{authored: "rgba(0, 0, 0, 0)", name: "#0000", hex: "#0000", hsl: "hsla(0, 0%, 0%, 0)", rgb: "rgba(0, 0, 0, 0)", cycle: 3},
{authored: "hsla(0, 0%, 0%, 0)", name: "#0000", hex: "#0000", hsl: "hsla(0, 0%, 0%, 0)", rgb: "rgba(0, 0, 0, 0)", cycle: 3},
{authored: "rgba(50, 60, 70, 0.5)", name: "#323c4680", hex: "#323c4680", hsl: "hsla(210, 16.7%, 23.5%, 0.5)", rgb: "rgba(50, 60, 70, 0.5)", cycle: 3},
{authored: "rgba(0, 0, 0, 0.3)", name: "#0000004d", hex: "#0000004d", hsl: "hsla(0, 0%, 0%, 0.3)", rgb: "rgba(0, 0, 0, 0.3)", cycle: 3},
{authored: "rgba(255, 255, 255, 0.6)", name: "#fff9", hex: "#fff9", hsl: "hsla(0, 0%, 100%, 0.6)", rgb: "rgba(255, 255, 255, 0.6)", cycle: 3},
{authored: "rgba(127, 89, 45, 1)", name: "#7f592d", hex: "#7f592d", hsl: "hsl(32.2, 47.7%, 33.7%)", rgb: "rgb(127, 89, 45)", cycle: 3},
{authored: "hsla(19.304, 56%, 40%, 1)", name: "#9f522d", hex: "#9f522d", hsl: "hsl(19.5, 55.9%, 40%)", rgb: "rgb(159, 82, 45)", cycle: 3},
{authored: "#f089", name: "#f089", hex: "#f089", hsl: "hsla(328, 100%, 50%, 0.6)", rgb: "rgba(255, 0, 136, 0.6)", cycle: 3},
{authored: "#00ff8080", name: "#00ff8080", hex: "#00ff8080", hsl: "hsla(150.1, 100%, 50%, 0.5)", rgb: "rgba(0, 255, 128, 0.5)", cycle: 3},
{authored: "currentcolor", name: "currentcolor", hex: "currentcolor", hsl: "currentcolor", rgb: "currentcolor", cycle: false},
{authored: "inherit", name: "inherit", hex: "inherit", hsl: "inherit", rgb: "inherit", cycle: false},
{authored: "initial", name: "initial", hex: "initial", hsl: "initial", rgb: "initial", cycle: false},
{authored: "invalidColor", name: "", hex: "", hsl: "", rgb: "", cycle: false},
{authored: "transparent", name: "transparent", hex: "transparent", hsl: "transparent", rgb: "transparent", cycle: false},
{authored: "unset", name: "unset", hex: "unset", hsl: "unset", rgb: "unset", cycle: false},
];
}
// Allow this function to be shared on mochitests and xpcshell tests.
if (typeof module === "object") {
module.exports = getFixtureColorData;
}

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

@ -0,0 +1,45 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test color cycling regression - Bug 1303748.
*
* Values should cycle from a starting value, back to their original values. This can
* potentially be a little flaky due to the precision of different color representations.
*/
const {require} = Components.utils.import("resource://devtools/shared/Loader.jsm", {});
const {colorUtils} = require("devtools/shared/css/color");
const getFixtureColorData = require("resource://test/helper_color_data.js");
function run_test() {
getFixtureColorData().forEach(({authored, name, hex, hsl, rgb, cycle}) => {
if (cycle) {
const nameCycled = runCycle(name, cycle);
const hexCycled = runCycle(hex, cycle);
const hslCycled = runCycle(hsl, cycle);
const rgbCycled = runCycle(rgb, cycle);
// Cut down on log output by only reporting a single pass/fail for the color.
ok(nameCycled && hexCycled && hslCycled && rgbCycled,
`${authored} was able to cycle back to the original value`);
}
});
}
/**
* Test a color cycle to see if a color cycles back to its original value in a fixed
* number of steps.
*
* @param {string} value - The color value, e.g. "#000".
* @param {integer) times - The number of times it takes to cycle back to the
* original color.
*/
function runCycle(value, times) {
let color = new colorUtils.CssColor(value);
for (let i = 0; i < times; i++) {
color.nextColorUnit();
color = new colorUtils.CssColor(color.toString());
}
return color.toString() === value;
}

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

@ -5,12 +5,16 @@ tail =
firefox-appdir = browser firefox-appdir = browser
skip-if = toolkit == 'android' || toolkit == 'gonk' skip-if = toolkit == 'android' || toolkit == 'gonk'
support-files =
../helper_color_data.js
[test_advanceValidate.js] [test_advanceValidate.js]
[test_attribute-parsing-01.js] [test_attribute-parsing-01.js]
[test_attribute-parsing-02.js] [test_attribute-parsing-02.js]
[test_bezierCanvas.js] [test_bezierCanvas.js]
[test_cssAngle.js] [test_cssAngle.js]
[test_cssColor.js] [test_cssColor-01.js]
[test_cssColor-02.js]
[test_cssColorDatabase.js] [test_cssColorDatabase.js]
[test_cubicBezier.js] [test_cubicBezier.js]
[test_escapeCSSComment.js] [test_escapeCSSComment.js]

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

@ -14,6 +14,7 @@ const {
workerSpec, workerSpec,
pushSubscriptionSpec, pushSubscriptionSpec,
serviceWorkerRegistrationSpec, serviceWorkerRegistrationSpec,
serviceWorkerSpec,
} = require("devtools/shared/specs/worker"); } = require("devtools/shared/specs/worker");
loader.lazyRequireGetter(this, "ChromeUtils"); loader.lazyRequireGetter(this, "ChromeUtils");
@ -339,6 +340,29 @@ let PushSubscriptionActor = protocol.ActorClassWithSpec(pushSubscriptionSpec, {
}, },
}); });
let ServiceWorkerActor = protocol.ActorClassWithSpec(serviceWorkerSpec, {
initialize(conn, worker) {
protocol.Actor.prototype.initialize.call(this, conn);
this._worker = worker;
},
form() {
if (!this._worker) {
return null;
}
return {
url: this._worker.scriptSpec,
state: this._worker.state,
};
},
destroy() {
protocol.Actor.prototype.destroy.call(this);
this._worker = null;
},
});
// Lazily load the service-worker-child.js process script only once. // Lazily load the service-worker-child.js process script only once.
let _serviceWorkerProcessScriptLoaded = false; let _serviceWorkerProcessScriptLoaded = false;
@ -356,29 +380,70 @@ protocol.ActorClassWithSpec(serviceWorkerRegistrationSpec, {
this._conn = conn; this._conn = conn;
this._registration = registration; this._registration = registration;
this._pushSubscriptionActor = null; this._pushSubscriptionActor = null;
this._registration.addListener(this);
let {installingWorker, waitingWorker, activeWorker} = registration;
this._installingWorker = new ServiceWorkerActor(conn, installingWorker);
this._waitingWorker = new ServiceWorkerActor(conn, waitingWorker);
this._activeWorker = new ServiceWorkerActor(conn, activeWorker);
Services.obs.addObserver(this, PushService.subscriptionModifiedTopic, false); Services.obs.addObserver(this, PushService.subscriptionModifiedTopic, false);
}, },
onChange() {
this._installingWorker.destroy();
this._waitingWorker.destroy();
this._activeWorker.destroy();
let {installingWorker, waitingWorker, activeWorker} = this._registration;
this._installingWorker = new ServiceWorkerActor(this._conn, installingWorker);
this._waitingWorker = new ServiceWorkerActor(this._conn, waitingWorker);
this._activeWorker = new ServiceWorkerActor(this._conn, activeWorker);
events.emit(this, "registration-changed");
},
form(detail) { form(detail) {
if (detail === "actorid") { if (detail === "actorid") {
return this.actorID; return this.actorID;
} }
let registration = this._registration; let registration = this._registration;
let installingWorker = this._installingWorker.form();
let waitingWorker = this._waitingWorker.form();
let activeWorker = this._activeWorker.form();
let isE10s = Services.appinfo.browserTabsRemoteAutostart;
return { return {
actor: this.actorID, actor: this.actorID,
scope: registration.scope, scope: registration.scope,
url: registration.scriptSpec url: registration.scriptSpec,
installingWorker,
waitingWorker,
activeWorker,
// - In e10s: only active registrations are available.
// - In non-e10s: registrations always have at least one worker, if the worker is
// active, the registration is active.
active: isE10s ? true : !!activeWorker
}; };
}, },
destroy() { destroy() {
protocol.Actor.prototype.destroy.call(this); protocol.Actor.prototype.destroy.call(this);
Services.obs.removeObserver(this, PushService.subscriptionModifiedTopic, false); Services.obs.removeObserver(this, PushService.subscriptionModifiedTopic, false);
this._registration.removeListener(this);
this._registration = null; this._registration = null;
if (this._pushSubscriptionActor) { if (this._pushSubscriptionActor) {
this._pushSubscriptionActor.destroy(); this._pushSubscriptionActor.destroy();
} }
this._pushSubscriptionActor = null; this._pushSubscriptionActor = null;
this._installingWorker.destroy();
this._waitingWorker.destroy();
this._activeWorker.destroy();
this._installingWorker = null;
this._waitingWorker = null;
this._activeWorker = null;
}, },
disconnect() { disconnect() {

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

@ -461,7 +461,12 @@ function rgbToHsl([r, g, b]) {
} }
} }
return [Math.round(h), Math.round(s * 100), Math.round(l * 100)]; return [roundTo(h, 1), roundTo(s * 100, 1), roundTo(l * 100, 1)];
}
function roundTo(number, digits) {
const multiplier = Math.pow(10, digits);
return Math.round(number * multiplier) / multiplier;
} }
/** /**
@ -573,9 +578,9 @@ function hslToRGB([h, s, l]) {
m2 = l + s - l * s; m2 = l + s - l * s;
} }
m1 = l * 2 - m2; m1 = l * 2 - m2;
r = Math.floor(255 * _hslValue(m1, m2, h + 1.0 / 3.0)); r = Math.round(255 * _hslValue(m1, m2, h + 1.0 / 3.0));
g = Math.floor(255 * _hslValue(m1, m2, h)); g = Math.round(255 * _hslValue(m1, m2, h));
b = Math.floor(255 * _hslValue(m1, m2, h - 1.0 / 3.0)); b = Math.round(255 * _hslValue(m1, m2, h - 1.0 / 3.0));
return [r, g, b]; return [r, g, b];
} }

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

@ -44,6 +44,9 @@ const serviceWorkerRegistrationSpec = generateActorSpec({
events: { events: {
"push-subscription-modified": { "push-subscription-modified": {
type: "push-subscription-modified" type: "push-subscription-modified"
},
"registration-changed": {
type: "registration-changed"
} }
}, },
@ -66,3 +69,10 @@ const serviceWorkerRegistrationSpec = generateActorSpec({
}); });
exports.serviceWorkerRegistrationSpec = serviceWorkerRegistrationSpec; exports.serviceWorkerRegistrationSpec = serviceWorkerRegistrationSpec;
const serviceWorkerSpec = generateActorSpec({
typeName: "serviceWorker",
});
exports.serviceWorkerSpec = serviceWorkerSpec;

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

@ -193,11 +193,20 @@ nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
uint32_t newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP uint32_t newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
& ~FIXUP_FLAGS_MAKE_ALTERNATE_URI; & ~FIXUP_FLAGS_MAKE_ALTERNATE_URI;
rv = GetFixupURIInfo(Substring(uriString, const uint32_t viewSourceLen = sizeof("view-source:") - 1;
sizeof("view-source:") - 1, nsAutoCString innerURIString(Substring(uriString, viewSourceLen,
uriString.Length() - uriString.Length() -
(sizeof("view-source:") - 1)), viewSourceLen));
newFixupFlags, aPostData, getter_AddRefs(uriInfo)); // Prevent recursion:
innerURIString.Trim(" ");
nsAutoCString innerScheme;
ioService->ExtractScheme(innerURIString, innerScheme);
if (innerScheme.LowerCaseEqualsLiteral("view-source")) {
return NS_ERROR_FAILURE;
}
rv = GetFixupURIInfo(innerURIString, newFixupFlags, aPostData,
getter_AddRefs(uriInfo));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

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

@ -16,10 +16,6 @@
#include "nsRuleNode.h" #include "nsRuleNode.h"
#include "nsRuleData.h" #include "nsRuleData.h"
// For IsPictureEnabled() -- the candidate parser needs to be aware of sizes
// support being enabled
#include "HTMLPictureElement.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@ -557,8 +553,7 @@ ResponsiveImageDescriptors::AddDescriptor(const nsAString& aDescriptor)
// If the value is not a valid non-negative integer, it doesn't match this // If the value is not a valid non-negative integer, it doesn't match this
// descriptor, fall through. // descriptor, fall through.
if (ParseInteger(valueStr, possibleWidth) && possibleWidth >= 0) { if (ParseInteger(valueStr, possibleWidth) && possibleWidth >= 0) {
if (possibleWidth != 0 && HTMLPictureElement::IsPictureEnabled() && if (possibleWidth != 0 && mWidth.isNothing() && mDensity.isNothing()) {
mWidth.isNothing() && mDensity.isNothing()) {
mWidth.emplace(possibleWidth); mWidth.emplace(possibleWidth);
} else { } else {
// Valid width descriptor, but width or density were already seen, sizes // Valid width descriptor, but width or density were already seen, sizes

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

@ -6239,12 +6239,18 @@ NS_IMETHODIMP
nsDocument::LoadBindingDocument(const nsAString& aURI) nsDocument::LoadBindingDocument(const nsAString& aURI)
{ {
ErrorResult rv; ErrorResult rv;
nsIDocument::LoadBindingDocument(aURI, rv); nsIDocument::LoadBindingDocument(aURI,
nsContentUtils::GetCurrentJSContext()
? Some(nsContentUtils::SubjectPrincipal())
: Nothing(),
rv);
return rv.StealNSResult(); return rv.StealNSResult();
} }
void void
nsIDocument::LoadBindingDocument(const nsAString& aURI, ErrorResult& rv) nsIDocument::LoadBindingDocument(const nsAString& aURI,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& rv)
{ {
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), aURI, rv = NS_NewURI(getter_AddRefs(uri), aURI,
@ -6258,8 +6264,7 @@ nsIDocument::LoadBindingDocument(const nsAString& aURI, ErrorResult& rv)
// It's just designed to preserve the old semantics during a mass-conversion // It's just designed to preserve the old semantics during a mass-conversion
// patch. // patch.
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsCOMPtr<nsIPrincipal> subjectPrincipal =
nsContentUtils::GetCurrentJSContext() ? nsContentUtils::SubjectPrincipal() aSubjectPrincipal.isSome() ? aSubjectPrincipal.value() : NodePrincipal();
: NodePrincipal();
BindingManager()->LoadBindingDocument(this, uri, subjectPrincipal); BindingManager()->LoadBindingDocument(this, uri, subjectPrincipal);
} }

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

@ -10577,7 +10577,8 @@ nsGlobalWindow::GetSessionStorage(ErrorResult& aError)
} }
DOMStorage* DOMStorage*
nsGlobalWindow::GetLocalStorage(ErrorResult& aError) nsGlobalWindow::GetLocalStorage(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
{ {
MOZ_RELEASE_ASSERT(IsInnerWindow()); MOZ_RELEASE_ASSERT(IsInnerWindow());
@ -10586,7 +10587,7 @@ nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
} }
if (!mLocalStorage) { if (!mLocalStorage) {
if (!DOMStorage::CanUseStorage(AsInner())) { if (!DOMStorage::CanUseStorage(AsInner(), aSubjectPrincipal)) {
aError.Throw(NS_ERROR_DOM_SECURITY_ERR); aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr; return nullptr;
} }
@ -11535,8 +11536,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
// Clone the storage event included in the observer notification. We want // Clone the storage event included in the observer notification. We want
// to dispatch clones rather than the original event. // to dispatch clones rather than the original event.
ErrorResult error; ErrorResult error;
RefPtr<StorageEvent> newEvent = CloneStorageEvent(eventType, RefPtr<StorageEvent> newEvent = CloneStorageEvent(eventType, event, error);
event, error);
if (error.Failed()) { if (error.Failed()) {
return error.StealNSResult(); return error.StealNSResult();
} }
@ -11653,7 +11653,10 @@ nsGlobalWindow::CloneStorageEvent(const nsAString& aType,
RefPtr<DOMStorage> storage; RefPtr<DOMStorage> storage;
if (storageArea->GetType() == DOMStorage::LocalStorage) { if (storageArea->GetType() == DOMStorage::LocalStorage) {
storage = GetLocalStorage(aRv); storage = GetLocalStorage(nsContentUtils::GetCurrentJSContext()
? Some(nsContentUtils::SubjectPrincipal())
: Nothing(),
aRv);
} else { } else {
MOZ_ASSERT(storageArea->GetType() == DOMStorage::SessionStorage); MOZ_ASSERT(storageArea->GetType() == DOMStorage::SessionStorage);
storage = GetSessionStorage(aRv); storage = GetSessionStorage(aRv);

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

@ -1044,7 +1044,9 @@ public:
void Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String, void Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String,
mozilla::ErrorResult& aError); mozilla::ErrorResult& aError);
mozilla::dom::DOMStorage* GetSessionStorage(mozilla::ErrorResult& aError); mozilla::dom::DOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
mozilla::dom::DOMStorage* GetLocalStorage(mozilla::ErrorResult& aError); mozilla::dom::DOMStorage*
GetLocalStorage(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& aError);
mozilla::dom::Selection* GetSelectionOuter(); mozilla::dom::Selection* GetSelectionOuter();
mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError); mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
already_AddRefed<nsISelection> GetSelection() override; already_AddRefed<nsISelection> GetSelection() override;

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

@ -134,6 +134,11 @@ BroadcastBlobURLRegistration(const nsACString& aURI,
return; return;
} }
// We don't need to broadcast Blob URL if we have just 1 content process.
if (Preferences::GetInt("dom.ipc.processCount", 0) <= 1) {
return;
}
ContentChild* cc = ContentChild::GetSingleton(); ContentChild* cc = ContentChild::GetSingleton();
BlobChild* actor = cc->GetOrCreateActorForBlobImpl(aBlobImpl); BlobChild* actor = cc->GetOrCreateActorForBlobImpl(aBlobImpl);
if (NS_WARN_IF(!actor)) { if (NS_WARN_IF(!actor)) {

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

@ -2685,7 +2685,9 @@ public:
const nsAString& aAttrName, const nsAString& aAttrName,
const nsAString& aAttrValue); const nsAString& aAttrValue);
Element* GetBindingParent(nsINode& aNode); Element* GetBindingParent(nsINode& aNode);
void LoadBindingDocument(const nsAString& aURI, mozilla::ErrorResult& rv); void LoadBindingDocument(const nsAString& aURI,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& rv);
mozilla::dom::XPathExpression* mozilla::dom::XPathExpression*
CreateExpression(const nsAString& aExpression, CreateExpression(const nsAString& aExpression,
mozilla::dom::XPathNSResolver* aResolver, mozilla::dom::XPathNSResolver* aResolver,

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

@ -3537,8 +3537,10 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
} }
nsIDocument* nsIDocument*
nsObjectLoadingContent::GetContentDocument() nsObjectLoadingContent::GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
{ {
MOZ_ASSERT(aSubjectPrincipal.isSome());
nsCOMPtr<nsIContent> thisContent = nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@ -3552,7 +3554,7 @@ nsObjectLoadingContent::GetContentDocument()
} }
// Return null for cross-origin contentDocument. // Return null for cross-origin contentDocument.
if (!nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) { if (!aSubjectPrincipal.value()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
return nullptr; return nullptr;
} }

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

@ -27,6 +27,7 @@
class nsAsyncInstantiateEvent; class nsAsyncInstantiateEvent;
class nsStopPluginRunnable; class nsStopPluginRunnable;
class AutoSetInstantiatingToFalse; class AutoSetInstantiatingToFalse;
class nsIPrincipal;
class nsFrameLoader; class nsFrameLoader;
class nsPluginFrame; class nsPluginFrame;
class nsXULElement; class nsXULElement;
@ -179,7 +180,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
mozilla::ErrorResult& aRv); mozilla::ErrorResult& aRv);
// WebIDL API // WebIDL API
nsIDocument* GetContentDocument(); nsIDocument* GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
void GetActualType(nsAString& aType) const void GetActualType(nsAString& aType) const
{ {
CopyUTF8toUTF16(mContentType, aType); CopyUTF8toUTF16(mContentType, aType);

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

@ -329,6 +329,12 @@ operator<(const RefPtr<nsPluginElement>& lhs,
return lhs->PluginTag()->Name() < rhs->PluginTag()->Name(); return lhs->PluginTag()->Name() < rhs->PluginTag()->Name();
} }
static bool
PluginShouldBeHidden(nsCString aName) {
// This only supports one hidden plugin
return Preferences::GetCString("plugins.navigator.hidden_ctp_plugin").Equals(aName);
}
void void
nsPluginArray::EnsurePlugins() nsPluginArray::EnsurePlugins()
{ {
@ -357,8 +363,7 @@ nsPluginArray::EnsurePlugins()
if (pluginTag->IsClicktoplay()) { if (pluginTag->IsClicktoplay()) {
nsCString name; nsCString name;
pluginTag->GetName(name); pluginTag->GetName(name);
if (name.EqualsLiteral("Shockwave Flash") && if (PluginShouldBeHidden(name)) {
Preferences::GetBool("plugins.navigator_hide_disabled_flash", false)) {
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst(); RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
nsCString permString; nsCString permString;
nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString); nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString);
@ -377,6 +382,12 @@ nsPluginArray::EnsurePlugins()
} }
} }
if (mPlugins.Length() == 0 && mCTPPlugins.Length() != 0) {
nsCOMPtr<nsPluginTag> hiddenTag = new nsPluginTag("Hidden Plugin", NULL, "dummy.plugin", NULL, NULL,
NULL, NULL, NULL, 0, 0, false);
mPlugins.AppendElement(new nsPluginElement(mWindow, hiddenTag));
}
// Alphabetize the enumeration order of non-hidden plugins to reduce // Alphabetize the enumeration order of non-hidden plugins to reduce
// fingerprintable entropy based on plugins' installation file times. // fingerprintable entropy based on plugins' installation file times.
mPlugins.Sort(); mPlugins.Sort();

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

@ -167,9 +167,10 @@ public:
{ {
GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer); GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer);
} }
nsIDocument* GetSVGDocument() nsIDocument*
GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
{ {
return GetContentDocument(); return GetContentDocument(aSubjectPrincipal);
} }
bool Mozbrowser() const bool Mozbrowser() const
{ {

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

@ -50,12 +50,8 @@
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "mozilla/Preferences.h"
using namespace mozilla::net; using namespace mozilla::net;
static const char *kPrefSrcsetEnabled = "dom.image.srcset.enabled";
NS_IMPL_NS_NEW_HTML_ELEMENT(Image) NS_IMPL_NS_NEW_HTML_ELEMENT(Image)
#ifdef DEBUG #ifdef DEBUG
@ -170,19 +166,9 @@ HTMLImageElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex); nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
} }
bool
HTMLImageElement::IsSrcsetEnabled()
{
return Preferences::GetBool(kPrefSrcsetEnabled, false);
}
nsresult nsresult
HTMLImageElement::GetCurrentSrc(nsAString& aValue) HTMLImageElement::GetCurrentSrc(nsAString& aValue)
{ {
if (!IsSrcsetEnabled()) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIURI> currentURI; nsCOMPtr<nsIURI> currentURI;
GetCurrentURI(getter_AddRefs(currentURI)); GetCurrentURI(getter_AddRefs(currentURI));
if (currentURI) { if (currentURI) {
@ -433,12 +419,10 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
CancelImageRequests(aNotify); CancelImageRequests(aNotify);
} }
} else if (aName == nsGkAtoms::srcset && } else if (aName == nsGkAtoms::srcset &&
aNameSpaceID == kNameSpaceID_None && aNameSpaceID == kNameSpaceID_None) {
IsSrcsetEnabled()) {
PictureSourceSrcsetChanged(this, attrVal.String(), aNotify); PictureSourceSrcsetChanged(this, attrVal.String(), aNotify);
} else if (aName == nsGkAtoms::sizes && } else if (aName == nsGkAtoms::sizes &&
aNameSpaceID == kNameSpaceID_None && aNameSpaceID == kNameSpaceID_None) {
HTMLPictureElement::IsPictureEnabled()) {
PictureSourceSizesChanged(this, attrVal.String(), aNotify); PictureSourceSizesChanged(this, attrVal.String(), aNotify);
} }
@ -929,14 +913,10 @@ HTMLImageElement::QueueImageLoadTask(bool aAlwaysLoad)
bool bool
HTMLImageElement::HaveSrcsetOrInPicture() HTMLImageElement::HaveSrcsetOrInPicture()
{ {
if (IsSrcsetEnabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::srcset)) { if (HasAttr(kNameSpaceID_None, nsGkAtoms::srcset)) {
return true; return true;
} }
if (!HTMLPictureElement::IsPictureEnabled()) {
return false;
}
Element *parent = nsINode::GetParentElement(); Element *parent = nsINode::GetParentElement();
return (parent && parent->IsHTMLElement(nsGkAtoms::picture)); return (parent && parent->IsHTMLElement(nsGkAtoms::picture));
} }
@ -1027,14 +1007,8 @@ HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode,
const nsAString& aNewValue, const nsAString& aNewValue,
bool aNotify) bool aNotify)
{ {
bool isSelf = aSourceNode == this; MOZ_ASSERT(aSourceNode == this ||
IsPreviousSibling(aSourceNode, this),
if (!IsSrcsetEnabled() ||
(!isSelf && !HTMLPictureElement::IsPictureEnabled())) {
return;
}
MOZ_ASSERT(isSelf || IsPreviousSibling(aSourceNode, this),
"Should not be getting notifications for non-previous-siblings"); "Should not be getting notifications for non-previous-siblings");
nsIContent *currentSrc = nsIContent *currentSrc =
@ -1064,10 +1038,6 @@ HTMLImageElement::PictureSourceSizesChanged(nsIContent *aSourceNode,
const nsAString& aNewValue, const nsAString& aNewValue,
bool aNotify) bool aNotify)
{ {
if (!HTMLPictureElement::IsPictureEnabled()) {
return;
}
MOZ_ASSERT(aSourceNode == this || MOZ_ASSERT(aSourceNode == this ||
IsPreviousSibling(aSourceNode, this), IsPreviousSibling(aSourceNode, this),
"Should not be getting notifications for non-previous-siblings"); "Should not be getting notifications for non-previous-siblings");
@ -1090,10 +1060,6 @@ void
HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode, HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode,
bool aNotify) bool aNotify)
{ {
if (!HTMLPictureElement::IsPictureEnabled()) {
return;
}
MOZ_ASSERT(IsPreviousSibling(aSourceNode, this), MOZ_ASSERT(IsPreviousSibling(aSourceNode, this),
"Should not be getting notifications for non-previous-siblings"); "Should not be getting notifications for non-previous-siblings");
@ -1105,10 +1071,6 @@ HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode,
void void
HTMLImageElement::PictureSourceAdded(nsIContent *aSourceNode) HTMLImageElement::PictureSourceAdded(nsIContent *aSourceNode)
{ {
if (!HTMLPictureElement::IsPictureEnabled()) {
return;
}
MOZ_ASSERT(aSourceNode == this || MOZ_ASSERT(aSourceNode == this ||
IsPreviousSibling(aSourceNode, this), IsPreviousSibling(aSourceNode, this),
"Should not be getting notifications for non-previous-siblings"); "Should not be getting notifications for non-previous-siblings");
@ -1119,10 +1081,6 @@ HTMLImageElement::PictureSourceAdded(nsIContent *aSourceNode)
void void
HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode) HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode)
{ {
if (!HTMLPictureElement::IsPictureEnabled()) {
return;
}
MOZ_ASSERT(aSourceNode == this || MOZ_ASSERT(aSourceNode == this ||
IsPreviousSibling(aSourceNode, this), IsPreviousSibling(aSourceNode, this),
"Should not be getting notifications for non-previous-siblings"); "Should not be getting notifications for non-previous-siblings");
@ -1135,15 +1093,9 @@ HTMLImageElement::UpdateResponsiveSource()
{ {
bool hadSelector = !!mResponsiveSelector; bool hadSelector = !!mResponsiveSelector;
if (!IsSrcsetEnabled()) {
mResponsiveSelector = nullptr;
return hadSelector;
}
nsIContent *currentSource = nsIContent *currentSource =
mResponsiveSelector ? mResponsiveSelector->Content() : nullptr; mResponsiveSelector ? mResponsiveSelector->Content() : nullptr;
bool pictureEnabled = HTMLPictureElement::IsPictureEnabled(); Element *parent = nsINode::GetParentElement();
Element *parent = pictureEnabled ? nsINode::GetParentElement() : nullptr;
nsINode *candidateSource = nullptr; nsINode *candidateSource = nullptr;
if (parent && parent->IsHTMLElement(nsGkAtoms::picture)) { if (parent && parent->IsHTMLElement(nsGkAtoms::picture)) {
@ -1231,7 +1183,6 @@ HTMLImageElement::SourceElementMatches(nsIContent* aSourceNode)
DebugOnly<Element *> parent(nsINode::GetParentElement()); DebugOnly<Element *> parent(nsINode::GetParentElement());
MOZ_ASSERT(parent && parent->IsHTMLElement(nsGkAtoms::picture)); MOZ_ASSERT(parent && parent->IsHTMLElement(nsGkAtoms::picture));
MOZ_ASSERT(IsPreviousSibling(aSourceNode, this)); MOZ_ASSERT(IsPreviousSibling(aSourceNode, this));
MOZ_ASSERT(HTMLPictureElement::IsPictureEnabled());
// Check media and type // Check media and type
HTMLSourceElement *src = static_cast<HTMLSourceElement*>(aSourceNode); HTMLSourceElement *src = static_cast<HTMLSourceElement*>(aSourceNode);
@ -1249,15 +1200,8 @@ HTMLImageElement::SourceElementMatches(nsIContent* aSourceNode)
} }
bool bool
HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode, HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode)
const nsAString *aSrcset,
const nsAString *aSizes)
{ {
if (!IsSrcsetEnabled()) {
return false;
}
bool pictureEnabled = HTMLPictureElement::IsPictureEnabled();
// Skip if this is not a <source> with matching media query // Skip if this is not a <source> with matching media query
bool isSourceTag = aSourceNode->IsHTMLElement(nsGkAtoms::source); bool isSourceTag = aSourceNode->IsHTMLElement(nsGkAtoms::source);
if (isSourceTag) { if (isSourceTag) {
@ -1271,10 +1215,7 @@ HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode,
// Skip if has no srcset or an empty srcset // Skip if has no srcset or an empty srcset
nsString srcset; nsString srcset;
if (aSrcset) { if (!aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::srcset, srcset)) {
srcset = *aSrcset;
} else if (!aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::srcset,
srcset)) {
return false; return false;
} }
@ -1290,13 +1231,9 @@ HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode,
return false; return false;
} }
if (pictureEnabled && aSizes) { nsAutoString sizes;
sel->SetSizesFromDescriptor(*aSizes); aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::sizes, sizes);
} else if (pictureEnabled) { sel->SetSizesFromDescriptor(sizes);
nsAutoString sizes;
aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::sizes, sizes);
sel->SetSizesFromDescriptor(sizes);
}
// If this is the <img> tag, also pull in src as the default source // If this is the <img> tag, also pull in src as the default source
if (!isSourceTag) { if (!isSourceTag) {
@ -1326,12 +1263,7 @@ HTMLImageElement::SelectSourceForTagWithAttrs(nsIDocument *aDocument,
MOZ_ASSERT(!aIsSourceTag || aSrcAttr.IsEmpty(), MOZ_ASSERT(!aIsSourceTag || aSrcAttr.IsEmpty(),
"Passing aSrcAttr makes no sense with aIsSourceTag set"); "Passing aSrcAttr makes no sense with aIsSourceTag set");
bool pictureEnabled = HTMLPictureElement::IsPictureEnabled(); if (aSrcsetAttr.IsEmpty()) {
if (aIsSourceTag && !pictureEnabled) {
return false;
}
if (!IsSrcsetEnabled() || aSrcsetAttr.IsEmpty()) {
if (!aIsSourceTag) { if (!aIsSourceTag) {
// For an <img> with no srcset, we would always select the src attr. // For an <img> with no srcset, we would always select the src attr.
aResult.Assign(aSrcAttr); aResult.Assign(aSrcAttr);
@ -1355,7 +1287,7 @@ HTMLImageElement::SelectSourceForTagWithAttrs(nsIDocument *aDocument,
new ResponsiveImageSelector(aDocument); new ResponsiveImageSelector(aDocument);
sel->SetCandidatesFromSourceSet(aSrcsetAttr); sel->SetCandidatesFromSourceSet(aSrcsetAttr);
if (pictureEnabled && !aSizesAttr.IsEmpty()) { if (!aSizesAttr.IsEmpty()) {
sel->SetSizesFromDescriptor(aSizesAttr); sel->SetSizesFromDescriptor(aSizesAttr);
} }
if (!aIsSourceTag) { if (!aIsSourceTag) {

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

@ -15,9 +15,6 @@
#include "Units.h" #include "Units.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
// Only needed for IsPictureEnabled()
#include "mozilla/dom/HTMLPictureElement.h"
namespace mozilla { namespace mozilla {
class EventChainPreVisitor; class EventChainPreVisitor;
namespace dom { namespace dom {
@ -97,8 +94,6 @@ public:
void MaybeLoadImage(); void MaybeLoadImage();
static bool IsSrcsetEnabled();
bool IsMap() bool IsMap()
{ {
return GetBoolAttr(nsGkAtoms::ismap); return GetBoolAttr(nsGkAtoms::ismap);
@ -336,9 +331,7 @@ protected:
// If the node's srcset/sizes make for an invalid selector, returns // If the node's srcset/sizes make for an invalid selector, returns
// false. This does not guarantee the resulting selector matches an image, // false. This does not guarantee the resulting selector matches an image,
// only that it is valid. // only that it is valid.
bool TryCreateResponsiveSelector(nsIContent *aSourceNode, bool TryCreateResponsiveSelector(nsIContent *aSourceNode);
const nsAString *aSrcset = nullptr,
const nsAString *aSizes = nullptr);
CSSIntPoint GetXY(); CSSIntPoint GetXY();
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;

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

@ -2907,7 +2907,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mAudioChannelVolume(1.0), mAudioChannelVolume(1.0),
mPlayingThroughTheAudioChannel(false), mPlayingThroughTheAudioChannel(false),
mDisableVideo(false), mDisableVideo(false),
mElementInTreeState(ELEMENT_NOT_INTREE),
mHasUserInteraction(false), mHasUserInteraction(false),
mFirstFrameLoaded(false), mFirstFrameLoaded(false),
mDefaultPlaybackStartPosition(0.0), mDefaultPlaybackStartPosition(0.0),
@ -3408,6 +3407,9 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen
aParent, aParent,
aBindingParent, aBindingParent,
aCompileEventHandlers); aCompileEventHandlers);
mUnboundFromTree = false;
if (aDocument) { if (aDocument) {
mAutoplayEnabled = mAutoplayEnabled =
IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument()) && IsAutoplayEnabled() && (!aDocument || !aDocument->IsStaticDocument()) &&
@ -3416,7 +3418,6 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen
// It's value may have changed, so update it. // It's value may have changed, so update it.
UpdatePreloadAction(); UpdatePreloadAction();
} }
mElementInTreeState = ELEMENT_INTREE;
if (mDecoder) { if (mDecoder) {
// When the MediaElement is binding to tree, the dormant status is // When the MediaElement is binding to tree, the dormant status is
@ -3650,11 +3651,7 @@ HTMLMediaElement::ReportTelemetry()
void HTMLMediaElement::UnbindFromTree(bool aDeep, void HTMLMediaElement::UnbindFromTree(bool aDeep,
bool aNullParent) bool aNullParent)
{ {
if (!mPaused && mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) { mUnboundFromTree = true;
Pause();
}
mElementInTreeState = ELEMENT_NOT_INTREE_HAD_INTREE;
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
@ -3662,6 +3659,15 @@ void HTMLMediaElement::UnbindFromTree(bool aDeep,
MOZ_ASSERT(IsHidden()); MOZ_ASSERT(IsHidden());
mDecoder->NotifyOwnerActivityChanged(false); mDecoder->NotifyOwnerActivityChanged(false);
} }
RefPtr<HTMLMediaElement> self(this);
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self] () {
if (self->mUnboundFromTree &&
self->mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
self->Pause();
}
});
RunInStableState(task);
} }
/* static */ /* static */
@ -4989,11 +4995,8 @@ bool HTMLMediaElement::IsActive() const
bool HTMLMediaElement::IsHidden() const bool HTMLMediaElement::IsHidden() const
{ {
if (mElementInTreeState == ELEMENT_NOT_INTREE_HAD_INTREE) { nsIDocument* ownerDoc;
return true; return mUnboundFromTree || !(ownerDoc = OwnerDoc()) || ownerDoc->Hidden();
}
nsIDocument* ownerDoc = OwnerDoc();
return !ownerDoc || ownerDoc->Hidden();
} }
VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer() VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()

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

@ -1632,17 +1632,10 @@ protected:
// MediaStream. // MediaStream.
nsCOMPtr<nsIPrincipal> mSrcStreamVideoPrincipal; nsCOMPtr<nsIPrincipal> mSrcStreamVideoPrincipal;
enum ElementInTreeState { // True if UnbindFromTree() is called on the element.
// The MediaElement is not in the DOM tree now. // Note this flag is false when the element is in a phase after creation and
ELEMENT_NOT_INTREE, // before attaching to the DOM tree.
// The MediaElement is in the DOM tree now. bool mUnboundFromTree = false;
ELEMENT_INTREE,
// The MediaElement is not in the DOM tree now but had been binded to the
// tree before.
ELEMENT_NOT_INTREE_HAD_INTREE
};
ElementInTreeState mElementInTreeState;
public: public:
// Helper class to measure times for MSE telemetry stats // Helper class to measure times for MSE telemetry stats

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

@ -465,15 +465,16 @@ HTMLObjectElement::GetContentDocument(nsIDOMDocument **aContentDocument)
{ {
NS_ENSURE_ARG_POINTER(aContentDocument); NS_ENSURE_ARG_POINTER(aContentDocument);
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(GetContentDocument()); nsCOMPtr<nsIDOMDocument> domDoc =
do_QueryInterface(GetContentDocument(Some(nsContentUtils::SubjectPrincipal())));
domDoc.forget(aContentDocument); domDoc.forget(aContentDocument);
return NS_OK; return NS_OK;
} }
nsPIDOMWindowOuter* nsPIDOMWindowOuter*
HTMLObjectElement::GetContentWindow() HTMLObjectElement::GetContentWindow(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
{ {
nsIDocument* doc = GetContentDocument(); nsIDocument* doc = GetContentDocument(aSubjectPrincipal);
if (doc) { if (doc) {
return doc->GetWindow(); return doc->GetWindow();
} }

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

@ -156,7 +156,10 @@ public:
SetHTMLAttr(nsGkAtoms::height, aValue, aRv); SetHTMLAttr(nsGkAtoms::height, aValue, aRv);
} }
using nsObjectLoadingContent::GetContentDocument; using nsObjectLoadingContent::GetContentDocument;
nsPIDOMWindowOuter* GetContentWindow();
nsPIDOMWindowOuter*
GetContentWindow(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
using nsIConstraintValidation::CheckValidity; using nsIConstraintValidation::CheckValidity;
using nsIConstraintValidation::ReportValidity; using nsIConstraintValidation::ReportValidity;
using nsIConstraintValidation::GetValidationMessage; using nsIConstraintValidation::GetValidationMessage;
@ -234,9 +237,11 @@ public:
{ {
SetHTMLAttr(nsGkAtoms::border, aValue, aRv); SetHTMLAttr(nsGkAtoms::border, aValue, aRv);
} }
nsIDocument* GetSVGDocument()
nsIDocument*
GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
{ {
return GetContentDocument(); return GetContentDocument(aSubjectPrincipal);
} }
private: private:

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

@ -8,18 +8,11 @@
#include "mozilla/dom/HTMLPictureElementBinding.h" #include "mozilla/dom/HTMLPictureElementBinding.h"
#include "mozilla/dom/HTMLImageElement.h" #include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/Preferences.h"
static const char *kPrefPictureEnabled = "dom.image.picture.enabled";
// Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Picture) to add pref check. // Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Picture) to add pref check.
nsGenericHTMLElement* nsGenericHTMLElement*
NS_NewHTMLPictureElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, NS_NewHTMLPictureElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
mozilla::dom::FromParser aFromParser) mozilla::dom::FromParser aFromParser)
{ {
if (!mozilla::dom::HTMLPictureElement::IsPictureEnabled()) {
return new mozilla::dom::HTMLUnknownElement(aNodeInfo);
}
return new mozilla::dom::HTMLPictureElement(aNodeInfo); return new mozilla::dom::HTMLPictureElement(aNodeInfo);
} }
@ -95,13 +88,6 @@ HTMLPictureElement::InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotif
return rv; return rv;
} }
bool
HTMLPictureElement::IsPictureEnabled()
{
return HTMLImageElement::IsSrcsetEnabled() &&
Preferences::GetBool(kPrefPictureEnabled, false);
}
JSObject* JSObject*
HTMLPictureElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) HTMLPictureElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{ {

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

@ -11,8 +11,6 @@
#include "nsIDOMHTMLPictureElement.h" #include "nsIDOMHTMLPictureElement.h"
#include "nsGenericHTMLElement.h" #include "nsGenericHTMLElement.h"
#include "mozilla/dom/HTMLUnknownElement.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -32,8 +30,6 @@ public:
virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override; virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify) override; virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify) override;
static bool IsPictureEnabled();
protected: protected:
virtual ~HTMLPictureElement(); virtual ~HTMLPictureElement();

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

@ -187,9 +187,10 @@ public:
// height covered by <applet> // height covered by <applet>
// align covered by <applet> // align covered by <applet>
// name covered by <applet> // name covered by <applet>
nsIDocument* GetSVGDocument() nsIDocument*
GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
{ {
return GetContentDocument(); return GetContentDocument(aSubjectPrincipal);
} }
/** /**

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

@ -71,7 +71,7 @@ load 903106.html
load 916322-1.html load 916322-1.html
load 916322-2.html load 916322-2.html
load 1032654.html load 1032654.html
pref(dom.image.srcset.enabled,true) load 1141260.html load 1141260.html
load 1228876.html load 1228876.html
load 1230110.html load 1230110.html
load 1237633.html load 1237633.html

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

@ -79,13 +79,14 @@ nsresult
nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument) nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
{ {
NS_PRECONDITION(aContentDocument, "Null out param"); NS_PRECONDITION(aContentDocument, "Null out param");
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetContentDocument()); nsCOMPtr<nsIDOMDocument> document =
do_QueryInterface(GetContentDocument(Some(nsContentUtils::SubjectPrincipal())));
document.forget(aContentDocument); document.forget(aContentDocument);
return NS_OK; return NS_OK;
} }
nsIDocument* nsIDocument*
nsGenericHTMLFrameElement::GetContentDocument() nsGenericHTMLFrameElement::GetContentDocument(const Maybe<nsIPrincipal*>& aSubjectPrincipal)
{ {
nsCOMPtr<nsPIDOMWindowOuter> win = GetContentWindow(); nsCOMPtr<nsPIDOMWindowOuter> win = GetContentWindow();
if (!win) { if (!win) {
@ -98,8 +99,8 @@ nsGenericHTMLFrameElement::GetContentDocument()
} }
// Return null for cross-origin contentDocument. // Return null for cross-origin contentDocument.
if (!nsContentUtils::SubjectPrincipal()-> if (!aSubjectPrincipal.value()
SubsumesConsideringDomain(doc->NodePrincipal())) { ->SubsumesConsideringDomain(doc->NodePrincipal())) {
return nullptr; return nullptr;
} }
return doc; return doc;

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

@ -102,7 +102,8 @@ protected:
// it makes sense. // it makes sense.
void EnsureFrameLoader(); void EnsureFrameLoader();
nsresult LoadSrc(); nsresult LoadSrc();
nsIDocument* GetContentDocument(); nsIDocument*
GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
nsresult GetContentDocument(nsIDOMDocument** aContentDocument); nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
already_AddRefed<nsPIDOMWindowOuter> GetContentWindow(); already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();

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

@ -2390,7 +2390,7 @@ nsHTMLDocument::GenerateParserKey(void)
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLDocument::GetDesignMode(nsAString & aDesignMode) nsHTMLDocument::GetDesignMode(nsAString& aDesignMode)
{ {
if (HasFlag(NODE_IS_EDITABLE)) { if (HasFlag(NODE_IS_EDITABLE)) {
aDesignMode.AssignLiteral("on"); aDesignMode.AssignLiteral("on");
@ -2832,17 +2832,22 @@ nsHTMLDocument::EditingStateChanged()
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLDocument::SetDesignMode(const nsAString & aDesignMode) nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode)
{ {
ErrorResult rv; ErrorResult rv;
SetDesignMode(aDesignMode, rv); SetDesignMode(aDesignMode, nsContentUtils::GetCurrentJSContext()
? Some(nsContentUtils::SubjectPrincipal())
: Nothing(), rv);
return rv.StealNSResult(); return rv.StealNSResult();
} }
void void
nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode, ErrorResult& rv) nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& rv)
{ {
if (!nsContentUtils::LegacyIsCallerNativeCode() && !nsContentUtils::SubjectPrincipal()->Subsumes(NodePrincipal())) { if (!nsContentUtils::LegacyIsCallerNativeCode() &&
!aSubjectPrincipal.value()->Subsumes(NodePrincipal())) {
rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED); rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
return; return;
} }

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

@ -210,8 +210,14 @@ public:
mozilla::ErrorResult& rv); mozilla::ErrorResult& rv);
void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText, void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
mozilla::ErrorResult& rv); mozilla::ErrorResult& rv);
// The XPCOM GetDesignMode() works OK for us, since it never throws. void GetDesignMode(nsAString& aDesignMode,
void SetDesignMode(const nsAString& aDesignMode, mozilla::ErrorResult& rv); const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
{
GetDesignMode(aDesignMode);
}
void SetDesignMode(const nsAString& aDesignMode,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& rv);
bool ExecCommand(const nsAString& aCommandID, bool aDoShowUI, bool ExecCommand(const nsAString& aCommandID, bool aDoShowUI,
const nsAString& aValue, mozilla::ErrorResult& rv); const nsAString& aValue, mozilla::ErrorResult& rv);
bool QueryCommandEnabled(const nsAString& aCommandID, bool QueryCommandEnabled(const nsAString& aCommandID,

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

@ -48,8 +48,8 @@ skip == bug917595-exif-rotated.jpg bug917595-exif-rotated.jpg
# Bug 1150490 disabling on Mulet as on B2G # Bug 1150490 disabling on Mulet as on B2G
# Test support for SVG-as-image in <picture> elements. # Test support for SVG-as-image in <picture> elements.
pref(dom.image.picture.enabled,true) pref(dom.image.srcset.enabled,true) == bug1106522-1.html bug1106522-1.html == bug1106522-1.html bug1106522-1.html
pref(dom.image.picture.enabled,true) pref(dom.image.srcset.enabled,true) == bug1106522-2.html bug1106522-2.html == bug1106522-2.html bug1106522-2.html
== href-attr-change-restyles.html href-attr-change-restyles.html == href-attr-change-restyles.html href-attr-change-restyles.html
== figure.html figure.html == figure.html figure.html

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

@ -44,8 +44,8 @@ fuzzy(1,149) == bug917595-iframe-1.html bug917595-1-ref.html
skip-if(B2G||Mulet) fuzzy-if((!B2G&&!Mulet),3,640) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869 # Bug 1150490 disabling on Mulet as on B2G skip-if(B2G||Mulet) fuzzy-if((!B2G&&!Mulet),3,640) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869 # Bug 1150490 disabling on Mulet as on B2G
# Test support for SVG-as-image in <picture> elements. # Test support for SVG-as-image in <picture> elements.
pref(dom.image.picture.enabled,true) pref(dom.image.srcset.enabled,true) == bug1106522-1.html bug1106522-ref.html == bug1106522-1.html bug1106522-ref.html
pref(dom.image.picture.enabled,true) pref(dom.image.srcset.enabled,true) == bug1106522-2.html bug1106522-ref.html == bug1106522-2.html bug1106522-ref.html
== href-attr-change-restyles.html href-attr-change-restyles-ref.html == href-attr-change-restyles.html href-attr-change-restyles-ref.html
== figure.html figure-ref.html == figure.html figure-ref.html

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

@ -29,9 +29,19 @@ interface nsIWorkerDebugger;
[scriptable, builtinclass, uuid(76e357ed-208d-4e4c-9165-1c4059707879)] [scriptable, builtinclass, uuid(76e357ed-208d-4e4c-9165-1c4059707879)]
interface nsIServiceWorkerInfo : nsISupports interface nsIServiceWorkerInfo : nsISupports
{ {
// State values below should match the ServiceWorkerState enumeration.
const unsigned short STATE_INSTALLING = 0;
const unsigned short STATE_INSTALLED = 1;
const unsigned short STATE_ACTIVATING = 2;
const unsigned short STATE_ACTIVATED = 3;
const unsigned short STATE_REDUNDANT = 4;
const unsigned short STATE_UNKNOWN = 5;
readonly attribute DOMString scriptSpec; readonly attribute DOMString scriptSpec;
readonly attribute DOMString cacheName; readonly attribute DOMString cacheName;
readonly attribute unsigned short state;
readonly attribute nsIWorkerDebugger debugger; readonly attribute nsIWorkerDebugger debugger;
void attachDebugger(); void attachDebugger();

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

@ -3259,6 +3259,10 @@ TabChild::ReinitRendering()
lf->IdentifyTextureHost(mTextureFactoryIdentifier); lf->IdentifyTextureHost(mTextureFactoryIdentifier);
mApzcTreeManager = CompositorBridgeChild::Get()->GetAPZCTreeManager(mLayersId); mApzcTreeManager = CompositorBridgeChild::Get()->GetAPZCTreeManager(mLayersId);
if (mApzcTreeManager) {
APZChild* apz = ContentProcessController::Create(mUniqueId);
CompositorBridgeChild::Get()->SendPAPZConstructor(apz, mLayersId);
}
} }
void void

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

@ -437,11 +437,8 @@ public:
mDecodeStartTime = TimeStamp::Now(); mDecodeStartTime = TimeStamp::Now();
// Reset other state to pristine values before starting decode. mMaster->mIsPrerolling = true;
mMaster->mIsAudioPrerolling = !mMaster->DonePrerollingAudio() && mMaster->MaybeStopPrerolling();
!Reader()->IsWaitingAudioData();
mMaster->mIsVideoPrerolling = !mMaster->DonePrerollingVideo() &&
!Reader()->IsWaitingVideoData();
// Ensure that we've got tasks enqueued to decode data if we need to. // Ensure that we've got tasks enqueued to decode data if we need to.
mMaster->DispatchDecodeTasksIfNeeded(); mMaster->DispatchDecodeTasksIfNeeded();
@ -455,6 +452,7 @@ public:
TimeDuration decodeDuration = TimeStamp::Now() - mDecodeStartTime; TimeDuration decodeDuration = TimeStamp::Now() - mDecodeStartTime;
SLOG("Exiting DECODING, decoded for %.3lfs", decodeDuration.ToSeconds()); SLOG("Exiting DECODING, decoded for %.3lfs", decodeDuration.ToSeconds());
} }
mMaster->mIsPrerolling = false;
} }
void Step() override void Step() override
@ -718,8 +716,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mPlaybackRate(1.0), mPlaybackRate(1.0),
mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS), mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS), mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
mIsAudioPrerolling(false),
mIsVideoPrerolling(false),
mAudioCaptured(false), mAudioCaptured(false),
INIT_WATCHABLE(mAudioCompleted, false), INIT_WATCHABLE(mAudioCompleted, false),
INIT_WATCHABLE(mVideoCompleted, false), INIT_WATCHABLE(mVideoCompleted, false),
@ -989,12 +985,11 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
// readers that are async, as since their audio decode runs on a different // readers that are async, as since their audio decode runs on a different
// task queue it should never run low and skipping won't help their decode. // task queue it should never run low and skipping won't help their decode.
bool isLowOnDecodedAudio = !mReader->IsAsync() && bool isLowOnDecodedAudio = !mReader->IsAsync() &&
!mIsAudioPrerolling && IsAudioDecoding() && IsAudioDecoding() &&
(GetDecodedAudioDuration() < (GetDecodedAudioDuration() <
mLowAudioThresholdUsecs * mPlaybackRate); mLowAudioThresholdUsecs * mPlaybackRate);
bool isLowOnDecodedVideo = !mIsVideoPrerolling && bool isLowOnDecodedVideo = (GetClock() - mDecodedVideoEndTime) * mPlaybackRate >
((GetClock() - mDecodedVideoEndTime) * mPlaybackRate > LOW_VIDEO_THRESHOLD_USECS;
LOW_VIDEO_THRESHOLD_USECS);
bool lowBuffered = HasLowBufferedData(); bool lowBuffered = HasLowBufferedData();
if ((isLowOnDecodedAudio || isLowOnDecodedVideo) && !lowBuffered) { if ((isLowOnDecodedAudio || isLowOnDecodedVideo) && !lowBuffered) {
@ -1050,9 +1045,7 @@ MediaDecoderStateMachine::OnAudioDecoded(MediaData* aAudioSample)
case DECODER_STATE_DECODING: { case DECODER_STATE_DECODING: {
Push(audio, MediaData::AUDIO_DATA); Push(audio, MediaData::AUDIO_DATA);
if (mIsAudioPrerolling && DonePrerollingAudio()) { MaybeStopPrerolling();
StopPrerollingAudio();
}
return; return;
} }
@ -1128,15 +1121,7 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
MOZ_ASSERT(mReader->IsWaitForDataSupported(), MOZ_ASSERT(mReader->IsWaitForDataSupported(),
"Readers that send WAITING_FOR_DATA need to implement WaitForData"); "Readers that send WAITING_FOR_DATA need to implement WaitForData");
mReader->WaitForData(aType); mReader->WaitForData(aType);
MaybeStopPrerolling();
// We are out of data to decode and will enter buffering mode soon.
// We want to play the frames we have already decoded, so we stop pre-rolling
// and ensure that loadeddata is fired as required.
if (isAudio) {
StopPrerollingAudio();
} else {
StopPrerollingVideo();
}
return; return;
} }
@ -1159,11 +1144,12 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
// state. // state.
if (isAudio) { if (isAudio) {
AudioQueue().Finish(); AudioQueue().Finish();
StopPrerollingAudio();
} else { } else {
VideoQueue().Finish(); VideoQueue().Finish();
StopPrerollingVideo();
} }
MaybeStopPrerolling();
switch (mState) { switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: case DECODER_STATE_DECODING_FIRSTFRAME:
MaybeFinishDecodeFirstFrame(); MaybeFinishDecodeFirstFrame();
@ -1238,9 +1224,7 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample,
case DECODER_STATE_DECODING: { case DECODER_STATE_DECODING: {
Push(video, MediaData::VIDEO_DATA); Push(video, MediaData::VIDEO_DATA);
if (mIsVideoPrerolling && DonePrerollingVideo()) { MaybeStopPrerolling();
StopPrerollingVideo();
}
// For non async readers, if the requested video sample was slow to // For non async readers, if the requested video sample was slow to
// arrive, increase the amount of audio we buffer to ensure that we // arrive, increase the amount of audio we buffer to ensure that we
@ -1400,6 +1384,19 @@ void MediaDecoderStateMachine::StopPlayback()
DispatchDecodeTasksIfNeeded(); DispatchDecodeTasksIfNeeded();
} }
void
MediaDecoderStateMachine::MaybeStopPrerolling()
{
MOZ_ASSERT(OnTaskQueue());
if (mIsPrerolling &&
(DonePrerollingAudio() || mReader->IsWaitingAudioData()) &&
(DonePrerollingVideo() || mReader->IsWaitingVideoData())) {
mIsPrerolling = false;
// Check if we can start playback.
ScheduleStateMachine();
}
}
void MediaDecoderStateMachine::MaybeStartPlayback() void MediaDecoderStateMachine::MaybeStartPlayback()
{ {
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
@ -1414,13 +1411,10 @@ void MediaDecoderStateMachine::MaybeStartPlayback()
} }
bool playStatePermits = mPlayState == MediaDecoder::PLAY_STATE_PLAYING; bool playStatePermits = mPlayState == MediaDecoder::PLAY_STATE_PLAYING;
if (!playStatePermits || mIsAudioPrerolling || if (!playStatePermits || mIsPrerolling || mAudioOffloading) {
mIsVideoPrerolling || mAudioOffloading) {
DECODER_LOG("Not starting playback [playStatePermits: %d, " DECODER_LOG("Not starting playback [playStatePermits: %d, "
"mIsAudioPrerolling: %d, mIsVideoPrerolling: %d, " "mIsPrerolling: %d, mAudioOffloading: %d]",
"mAudioOffloading: %d]", playStatePermits, mIsPrerolling, mAudioOffloading);
(int)playStatePermits, (int)mIsAudioPrerolling,
(int)mIsVideoPrerolling, (int)mAudioOffloading);
return; return;
} }
@ -2110,12 +2104,10 @@ MediaDecoderStateMachine::OnSeekTaskResolved(SeekTaskResolveValue aValue)
if (aValue.mIsAudioQueueFinished) { if (aValue.mIsAudioQueueFinished) {
AudioQueue().Finish(); AudioQueue().Finish();
StopPrerollingAudio();
} }
if (aValue.mIsVideoQueueFinished) { if (aValue.mIsVideoQueueFinished) {
VideoQueue().Finish(); VideoQueue().Finish();
StopPrerollingVideo();
} }
SeekCompleted(); SeekCompleted();
@ -2131,12 +2123,10 @@ MediaDecoderStateMachine::OnSeekTaskRejected(SeekTaskRejectValue aValue)
if (aValue.mIsAudioQueueFinished) { if (aValue.mIsAudioQueueFinished) {
AudioQueue().Finish(); AudioQueue().Finish();
StopPrerollingAudio();
} }
if (aValue.mIsVideoQueueFinished) { if (aValue.mIsVideoQueueFinished) {
VideoQueue().Finish(); VideoQueue().Finish();
StopPrerollingVideo();
} }
DecodeError(aValue.mError); DecodeError(aValue.mError);
@ -2765,13 +2755,7 @@ MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate)
mPlaybackRate = aPlaybackRate; mPlaybackRate = aPlaybackRate;
mMediaSink->SetPlaybackRate(mPlaybackRate); mMediaSink->SetPlaybackRate(mPlaybackRate);
if (mIsAudioPrerolling && DonePrerollingAudio()) { // Schedule next cycle to check if we can stop prerolling.
StopPrerollingAudio();
}
if (mIsVideoPrerolling && DonePrerollingVideo()) {
StopPrerollingVideo();
}
ScheduleStateMachine(); ScheduleStateMachine();
} }
@ -2933,9 +2917,8 @@ MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured)
mAmpleAudioThresholdUsecs = mAudioCaptured ? mAmpleAudioThresholdUsecs = mAudioCaptured ?
detail::AMPLE_AUDIO_USECS / 2 : detail::AMPLE_AUDIO_USECS / 2 :
detail::AMPLE_AUDIO_USECS; detail::AMPLE_AUDIO_USECS;
if (mIsAudioPrerolling && DonePrerollingAudio()) {
StopPrerollingAudio(); MaybeStopPrerolling();
}
} }
uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
@ -2959,12 +2942,11 @@ MediaDecoderStateMachine::DumpDebugInfo()
"GetMediaTime=%lld GetClock=%lld mMediaSink=%p " "GetMediaTime=%lld GetClock=%lld mMediaSink=%p "
"mState=%s mPlayState=%d mSentFirstFrameLoadedEvent=%d IsPlaying=%d " "mState=%s mPlayState=%d mSentFirstFrameLoadedEvent=%d IsPlaying=%d "
"mAudioStatus=%s mVideoStatus=%s mDecodedAudioEndTime=%lld mDecodedVideoEndTime=%lld " "mAudioStatus=%s mVideoStatus=%s mDecodedAudioEndTime=%lld mDecodedVideoEndTime=%lld "
"mIsAudioPrerolling=%d mIsVideoPrerolling=%d " "mIsPrerolling=%d mAudioCompleted=%d mVideoCompleted=%d",
"mAudioCompleted=%d mVideoCompleted=%d",
GetMediaTime(), mMediaSink->IsStarted() ? GetClock() : -1, mMediaSink.get(), GetMediaTime(), mMediaSink->IsStarted() ? GetClock() : -1, mMediaSink.get(),
ToStateStr(), mPlayState.Ref(), mSentFirstFrameLoadedEvent, IsPlaying(), ToStateStr(), mPlayState.Ref(), mSentFirstFrameLoadedEvent, IsPlaying(),
AudioRequestStatus(), VideoRequestStatus(), mDecodedAudioEndTime, mDecodedVideoEndTime, AudioRequestStatus(), VideoRequestStatus(), mDecodedAudioEndTime, mDecodedVideoEndTime,
mIsAudioPrerolling, mIsVideoPrerolling, mAudioCompleted.Ref(), mVideoCompleted.Ref()); mIsPrerolling, mAudioCompleted.Ref(), mVideoCompleted.Ref());
}); });
OwnerThread()->DispatchStateChange(r.forget()); OwnerThread()->DispatchStateChange(r.forget());

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

@ -730,23 +730,7 @@ private:
VideoPrerollFrames() * mPlaybackRate + 1; VideoPrerollFrames() * mPlaybackRate + 1;
} }
void StopPrerollingAudio() void MaybeStopPrerolling();
{
MOZ_ASSERT(OnTaskQueue());
if (mIsAudioPrerolling) {
mIsAudioPrerolling = false;
ScheduleStateMachine();
}
}
void StopPrerollingVideo()
{
MOZ_ASSERT(OnTaskQueue());
if (mIsVideoPrerolling) {
mIsVideoPrerolling = false;
ScheduleStateMachine();
}
}
// When we start decoding (either for the first time, or after a pause) // When we start decoding (either for the first time, or after a pause)
// we may be low on decoded data. We don't want our "low data" logic to // we may be low on decoded data. We don't want our "low data" logic to
@ -754,10 +738,8 @@ private:
// can't keep up with the decode, and cause us to pause playback. So we // can't keep up with the decode, and cause us to pause playback. So we
// have a "preroll" stage, where we ignore the results of our "low data" // have a "preroll" stage, where we ignore the results of our "low data"
// logic during the first few frames of our decode. This occurs during // logic during the first few frames of our decode. This occurs during
// playback. The flags below are true when the corresponding stream is // playback.
// being "prerolled". bool mIsPrerolling = false;
bool mIsAudioPrerolling;
bool mIsVideoPrerolling;
// Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise) // Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
// should exist at any given moment. // should exist at any given moment.

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

@ -464,7 +464,8 @@ public:
bool IsEncrypted() const bool IsEncrypted() const
{ {
return mCrypto.IsEncrypted(); return (HasAudio() && mAudio.mCrypto.mValid) ||
(HasVideo() && mVideo.mCrypto.mValid);
} }
bool HasValidMedia() const bool HasValidMedia() const

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

@ -1447,35 +1447,56 @@ MediaStreamGraphImpl::ForceShutDown(ShutdownTicket* aShutdownTicket)
{ {
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread"); NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p ForceShutdown", this)); STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p ForceShutdown", this));
{
MonitorAutoLock lock(mMonitor); MonitorAutoLock lock(mMonitor);
mForceShutDown = true; if (aShutdownTicket) {
mForceShutdownTicket = aShutdownTicket; MOZ_ASSERT(!mForceShutdownTicket);
if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED) { // Avoid waiting forever for a graph to shut down
// We *could* have just sent this a message to start up, so don't // synchronously. Reports are that some 3rd-party audio drivers
// yank the rug out from under it. Tell it to startup and let it // occasionally hang in shutdown (both for us and Chrome).
// shut down. mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
RefPtr<GraphDriver> driver = CurrentDriver(); if (!mShutdownTimer) {
MonitorAutoUnlock unlock(mMonitor); return;
driver->Start();
} }
EnsureNextIterationLocked(); mShutdownTimer->InitWithCallback(this,
MediaStreamGraph::AUDIO_CALLBACK_DRIVER_SHUTDOWN_TIMEOUT,
nsITimer::TYPE_ONE_SHOT);
} }
mForceShutDown = true;
mForceShutdownTicket = aShutdownTicket;
if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED) {
// We *could* have just sent this a message to start up, so don't
// yank the rug out from under it. Tell it to startup and let it
// shut down.
RefPtr<GraphDriver> driver = CurrentDriver();
MonitorAutoUnlock unlock(mMonitor);
driver->Start();
}
EnsureNextIterationLocked();
} }
NS_IMETHODIMP
MediaStreamGraphImpl::Notify(nsITimer* aTimer)
{
MonitorAutoLock lock(mMonitor);
NS_ASSERTION(!mForceShutdownTicket, "MediaStreamGraph took too long to shut down!");
// Sigh, graph took too long to shut down. Stop blocking system
// shutdown and hope all is well.
mForceShutdownTicket = nullptr;
return NS_OK;
}
/* static */ StaticRefPtr<nsIAsyncShutdownBlocker> gMediaStreamGraphShutdownBlocker; /* static */ StaticRefPtr<nsIAsyncShutdownBlocker> gMediaStreamGraphShutdownBlocker;
namespace { namespace {
class MediaStreamGraphShutDownRunnable : public Runnable class MediaStreamGraphShutDownRunnable : public Runnable {
, public nsITimerCallback {
public: public:
explicit MediaStreamGraphShutDownRunnable(MediaStreamGraphImpl* aGraph) explicit MediaStreamGraphShutDownRunnable(MediaStreamGraphImpl* aGraph)
: mGraph(aGraph) : mGraph(aGraph)
{} {}
NS_DECL_ISUPPORTS_INHERITED NS_IMETHOD Run()
NS_IMETHOD Run() override
{ {
NS_ASSERTION(mGraph->mDetectedNotRunning, NS_ASSERTION(mGraph->mDetectedNotRunning,
"We should know the graph thread control loop isn't running!"); "We should know the graph thread control loop isn't running!");
@ -1493,24 +1514,12 @@ public:
} }
#endif #endif
if (mGraph->mForceShutdownTicket) {
// Avoid waiting forever for a callback driver to shut down
// synchronously. Reports are that some 3rd-party audio drivers
// occasionally hang in shutdown (both for us and Chrome).
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
if (!mTimer) {
return NS_ERROR_FAILURE;
}
mTimer->InitWithCallback(this,
MediaStreamGraph::AUDIO_CALLBACK_DRIVER_SHUTDOWN_TIMEOUT,
nsITimer::TYPE_ONE_SHOT);
}
mGraph->mDriver->Shutdown(); // This will wait until it's shutdown since mGraph->mDriver->Shutdown(); // This will wait until it's shutdown since
// we'll start tearing down the graph after this // we'll start tearing down the graph after this
// Safe to access these without the monitor since the graph isn't running.
// We may be one of several graphs. Drop ticket to eventually unblock shutdown. // We may be one of several graphs. Drop ticket to eventually unblock shutdown.
if (mTimer && !mGraph->mForceShutdownTicket) { if (mGraph->mShutdownTimer && !mGraph->mForceShutdownTicket) {
MOZ_ASSERT(false, MOZ_ASSERT(false,
"AudioCallbackDriver took too long to shut down and we let shutdown" "AudioCallbackDriver took too long to shut down and we let shutdown"
" continue - freezing and leaking"); " continue - freezing and leaking");
@ -1519,7 +1528,6 @@ public:
// teardown and just leak, for safety. // teardown and just leak, for safety.
return NS_OK; return NS_OK;
} }
mTimer = nullptr;
mGraph->mForceShutdownTicket = nullptr; mGraph->mForceShutdownTicket = nullptr;
// We can't block past the final LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION // We can't block past the final LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION
@ -1552,30 +1560,10 @@ public:
} }
return NS_OK; return NS_OK;
} }
NS_IMETHOD Notify(nsITimer* aTimer) override
{
// Sigh, driver took too long to shut down. Stop blocking system
// shutdown and hope all is well. Shutdown of this graph will proceed
// if the driver eventually comes back.
NS_ASSERTION(!(mGraph->mForceShutdownTicket),
"AudioCallbackDriver took too long to shut down - probably hung");
mGraph->mForceShutdownTicket = nullptr;
return NS_OK;
}
private: private:
~MediaStreamGraphShutDownRunnable() {}
nsCOMPtr<nsITimer> mTimer;
RefPtr<MediaStreamGraphImpl> mGraph; RefPtr<MediaStreamGraphImpl> mGraph;
}; };
NS_IMPL_ISUPPORTS_INHERITED(MediaStreamGraphShutDownRunnable, Runnable, nsITimerCallback)
class MediaStreamGraphStableStateRunnable : public Runnable { class MediaStreamGraphStableStateRunnable : public Runnable {
public: public:
explicit MediaStreamGraphStableStateRunnable(MediaStreamGraphImpl* aGraph, explicit MediaStreamGraphStableStateRunnable(MediaStreamGraphImpl* aGraph,
@ -3444,8 +3432,6 @@ MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
MOZ_ASSERT(aGraph->IsNonRealtime(), "Should not destroy the global graph here"); MOZ_ASSERT(aGraph->IsNonRealtime(), "Should not destroy the global graph here");
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(aGraph); MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(aGraph);
if (graph->mForceShutDown)
return; // already done
if (!graph->mNonRealtimeProcessing) { if (!graph->mNonRealtimeProcessing) {
// Start the graph, but don't produce anything // Start the graph, but don't produce anything
@ -3454,7 +3440,7 @@ MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
graph->ForceShutDown(nullptr); graph->ForceShutDown(nullptr);
} }
NS_IMPL_ISUPPORTS(MediaStreamGraphImpl, nsIMemoryReporter) NS_IMPL_ISUPPORTS(MediaStreamGraphImpl, nsIMemoryReporter, nsITimerCallback)
NS_IMETHODIMP NS_IMETHODIMP
MediaStreamGraphImpl::CollectReports(nsIHandleReportCallback* aHandleReport, MediaStreamGraphImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
@ -3969,7 +3955,7 @@ void
MediaStreamGraphImpl::UnregisterCaptureStreamForWindow(uint64_t aWindowId) MediaStreamGraphImpl::UnregisterCaptureStreamForWindow(uint64_t aWindowId)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
for (uint32_t i = 0; i < mWindowCaptureStreams.Length(); i++) { for (int32_t i = mWindowCaptureStreams.Length() - 1; i >= 0; i--) {
if (mWindowCaptureStreams[i].mWindowId == aWindowId) { if (mWindowCaptureStreams[i].mWindowId == aWindowId) {
mWindowCaptureStreams.RemoveElementAt(i); mWindowCaptureStreams.RemoveElementAt(i);
} }

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

@ -10,6 +10,7 @@
#include "nsDataHashtable.h" #include "nsDataHashtable.h"
#include "nsITimer.h"
#include "mozilla/Monitor.h" #include "mozilla/Monitor.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "nsIMemoryReporter.h" #include "nsIMemoryReporter.h"
@ -97,11 +98,13 @@ public:
* object too. * object too.
*/ */
class MediaStreamGraphImpl : public MediaStreamGraph, class MediaStreamGraphImpl : public MediaStreamGraph,
public nsIMemoryReporter public nsIMemoryReporter,
public nsITimerCallback
{ {
public: public:
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIMEMORYREPORTER NS_DECL_NSIMEMORYREPORTER
NS_DECL_NSITIMERCALLBACK
/** /**
* Use aGraphDriverRequested with SYSTEM_THREAD_DRIVER or AUDIO_THREAD_DRIVER * Use aGraphDriverRequested with SYSTEM_THREAD_DRIVER or AUDIO_THREAD_DRIVER
@ -808,6 +811,9 @@ public:
dom::AudioChannel AudioChannel() const { return mAudioChannel; } dom::AudioChannel AudioChannel() const { return mAudioChannel; }
// used to limit graph shutdown time
nsCOMPtr<nsITimer> mShutdownTimer;
private: private:
virtual ~MediaStreamGraphImpl(); virtual ~MediaStreamGraphImpl();

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

@ -54,11 +54,13 @@ parent:
async Drain(); async Drain();
async Shutdown(); async Shutdown();
async SetSeekThreshold(int64_t time);
async __delete__(); async __delete__();
child: child:
async InitComplete(); async InitComplete(bool hardware, nsCString hardwareReason);
async InitFailed(nsresult reason); async InitFailed(nsresult reason);
// Each output includes a SurfaceDescriptorGPUVideo that represents the decoded // Each output includes a SurfaceDescriptorGPUVideo that represents the decoded

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

@ -102,6 +102,26 @@ RemoteVideoDecoder::Shutdown()
}), NS_DISPATCH_NORMAL); }), NS_DISPATCH_NORMAL);
} }
bool
RemoteVideoDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
return mActor->IsHardwareAccelerated(aFailureReason);
}
void
RemoteVideoDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> self = this;
media::TimeUnit time = aTime;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([=]() {
MOZ_ASSERT(self->mActor);
self->mActor->SetSeekThreshold(time);
}), NS_DISPATCH_NORMAL);
}
nsresult nsresult
RemoteDecoderModule::Startup() RemoteDecoderModule::Startup()
{ {

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

@ -32,6 +32,8 @@ public:
void Flush() override; void Flush() override;
void Drain() override; void Drain() override;
void Shutdown() override; void Shutdown() override;
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
void SetSeekThreshold(const media::TimeUnit& aTime) override;
const char* GetDescriptionName() const override { return "RemoteVideoDecoder"; } const char* GetDescriptionName() const override { return "RemoteVideoDecoder"; }

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

@ -23,6 +23,8 @@ VideoDecoderChild::VideoDecoderChild()
: mThread(VideoDecoderManagerChild::GetManagerThread()) : mThread(VideoDecoderManagerChild::GetManagerThread())
, mLayersBackend(layers::LayersBackend::LAYERS_NONE) , mLayersBackend(layers::LayersBackend::LAYERS_NONE)
, mCanSend(true) , mCanSend(true)
, mInitialized(false)
, mIsHardwareAccelerated(false)
{ {
} }
@ -80,10 +82,13 @@ VideoDecoderChild::RecvError(const nsresult& aError)
} }
bool bool
VideoDecoderChild::RecvInitComplete() VideoDecoderChild::RecvInitComplete(const bool& aHardware, const nsCString& aHardwareReason)
{ {
AssertOnManagerThread(); AssertOnManagerThread();
mInitPromise.Resolve(TrackInfo::kVideoTrack, __func__); mInitPromise.Resolve(TrackInfo::kVideoTrack, __func__);
mInitialized = true;
mIsHardwareAccelerated = aHardware;
mHardwareAcceleratedReason = aHardwareReason;
return true; return true;
} }
@ -98,6 +103,13 @@ VideoDecoderChild::RecvInitFailed(const nsresult& aReason)
void void
VideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy) VideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy)
{ {
if (aWhy == AbnormalShutdown) {
if (mInitialized) {
mCallback->Error(NS_ERROR_DOM_MEDIA_FATAL_ERR);
} else {
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
}
}
mCanSend = false; mCanSend = false;
} }
@ -197,6 +209,23 @@ VideoDecoderChild::Shutdown()
if (!mCanSend || !SendShutdown()) { if (!mCanSend || !SendShutdown()) {
mCallback->Error(NS_ERROR_DOM_MEDIA_FATAL_ERR); mCallback->Error(NS_ERROR_DOM_MEDIA_FATAL_ERR);
} }
mInitialized = false;
}
bool
VideoDecoderChild::IsHardwareAccelerated(nsACString& aFailureReason) const
{
aFailureReason = mHardwareAcceleratedReason;
return mIsHardwareAccelerated;
}
void
VideoDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime)
{
AssertOnManagerThread();
if (!mCanSend || !SendSetSeekThreshold(aTime.ToMicroseconds())) {
mCallback->Error(NS_ERROR_DOM_MEDIA_FATAL_ERR);
}
} }
void void

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

@ -29,7 +29,7 @@ public:
bool RecvInputExhausted() override; bool RecvInputExhausted() override;
bool RecvDrainComplete() override; bool RecvDrainComplete() override;
bool RecvError(const nsresult& aError) override; bool RecvError(const nsresult& aError) override;
bool RecvInitComplete() override; bool RecvInitComplete(const bool& aHardware, const nsCString& aHardwareReason) override;
bool RecvInitFailed(const nsresult& aReason) override; bool RecvInitFailed(const nsresult& aReason) override;
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;
@ -39,6 +39,8 @@ public:
void Flush(); void Flush();
void Drain(); void Drain();
void Shutdown(); void Shutdown();
bool IsHardwareAccelerated(nsACString& aFailureReason) const;
void SetSeekThreshold(const media::TimeUnit& aTime);
MOZ_IS_CLASS_INIT MOZ_IS_CLASS_INIT
void InitIPDL(MediaDataDecoderCallback* aCallback, void InitIPDL(MediaDataDecoderCallback* aCallback,
@ -63,7 +65,10 @@ private:
VideoInfo mVideoInfo; VideoInfo mVideoInfo;
layers::LayersBackend mLayersBackend; layers::LayersBackend mLayersBackend;
nsCString mHardwareAcceleratedReason;
bool mCanSend; bool mCanSend;
bool mInitialized;
bool mIsHardwareAccelerated;
}; };
} // namespace dom } // namespace dom

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

@ -81,7 +81,9 @@ VideoDecoderParent::RecvInit(const VideoInfo& aInfo, const layers::LayersBackend
mDecoder->Init()->Then(mManagerTaskQueue, __func__, mDecoder->Init()->Then(mManagerTaskQueue, __func__,
[self] (TrackInfo::TrackType aTrack) { [self] (TrackInfo::TrackType aTrack) {
if (!self->mDestroyed) { if (!self->mDestroyed) {
Unused << self->SendInitComplete(); nsCString hardwareReason;
bool hardwareAccelerated = self->mDecoder->IsHardwareAccelerated(hardwareReason);
Unused << self->SendInitComplete(hardwareAccelerated, hardwareReason);
} }
}, },
[self] (MediaResult aReason) { [self] (MediaResult aReason) {
@ -135,6 +137,14 @@ VideoDecoderParent::RecvShutdown()
return true; return true;
} }
bool
VideoDecoderParent::RecvSetSeekThreshold(const int64_t& aTime)
{
MOZ_ASSERT(!mDestroyed);
mDecoder->SetSeekThreshold(media::TimeUnit::FromMicroseconds(aTime));
return true;
}
void void
VideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy) VideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
{ {

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

@ -35,6 +35,7 @@ public:
bool RecvFlush() override; bool RecvFlush() override;
bool RecvDrain() override; bool RecvDrain() override;
bool RecvShutdown() override; bool RecvShutdown() override;
bool RecvSetSeekThreshold(const int64_t& aTime) override;
void ActorDestroy(ActorDestroyReason aWhy) override; void ActorDestroy(ActorDestroyReason aWhy) override;

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

@ -461,3 +461,35 @@ function SetupEMEPref(callback) {
SpecialPowers.pushPrefEnv({ "set" : prefs }, callback); SpecialPowers.pushPrefEnv({ "set" : prefs }, callback);
} }
function fetchWithXHR(uri, onLoadFunction) {
var p = new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, true);
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", function () {
is(xhr.status, 200, "fetchWithXHR load uri='" + uri + "' status=" + xhr.status);
resolve(xhr.response);
});
xhr.send();
});
if (onLoadFunction) {
p.then(onLoadFunction);
}
return p;
};
function once(target, name, cb) {
var p = new Promise(function(resolve, reject) {
target.addEventListener(name, function onceEvent(arg) {
target.removeEventListener(name, onceEvent);
resolve(arg);
});
});
if (cb) {
p.then(cb);
}
return p;
}

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

@ -540,6 +540,8 @@ support-files =
sine.webm^headers^ sine.webm^headers^
short.mp4 short.mp4
short.mp4^headers^ short.mp4^headers^
short-audio-fragmented-cenc-without-pssh.mp4
short-audio-fragmented-cenc-without-pssh.mp4^headers^
short-video.ogv short-video.ogv
short-video.ogv^headers^ short-video.ogv^headers^
small-shot-mp3.mp4 small-shot-mp3.mp4
@ -688,6 +690,8 @@ skip-if = toolkit == 'android' # bug 1149374
skip-if = toolkit == 'android' # bug 1149374 skip-if = toolkit == 'android' # bug 1149374
[test_eme_initDataTypes.html] [test_eme_initDataTypes.html]
skip-if = toolkit == 'android' # bug 1149374 skip-if = toolkit == 'android' # bug 1149374
[test_eme_missing_pssh.html]
skip-if = toolkit == 'android' # bug 1149374
[test_eme_non_mse_fails.html] [test_eme_non_mse_fails.html]
skip-if = toolkit == 'android' # bug 1149374 skip-if = toolkit == 'android' # bug 1149374
[test_eme_request_notifications.html] [test_eme_request_notifications.html]

Двоичные данные
dom/media/test/short-audio-fragmented-cenc-without-pssh.mp4 Normal file

Двоичный файл не отображается.

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

@ -0,0 +1 @@
Cache-Control: no-store

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

@ -0,0 +1,92 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test Encrypted Media Extensions</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
<script type="text/javascript" src="eme.js"></script>
</head>
<body>
<audio controls id="audio"></audio>
<pre id="test">
<script class="testbody" type="text/javascript">
// Tests that a fragmented MP4 file without a PSSH, but with valid encrypted
// tracks with valid TENC boxes, is able to load with EME.
// We setup MSE before starting up EME, so that we exercise the "waiting for
// cdm" step in the MediaDecoderStateMachine.
SimpleTest.waitForExplicitFinish();
var pssh = [
0x00, 0x00, 0x00, 0x00,
0x70, 0x73, 0x73, 0x68, // BMFF box header (76 bytes, 'pssh')
0x01, 0x00, 0x00, 0x00, // Full box header (version = 1, flags = 0)
0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // SystemID
0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
0x00, 0x00, 0x00, 0x01, // KID_count (1)
0x2f, 0xef, 0x8a, 0xd8, 0x12, 0xdf, 0x42, 0x97,
0x83, 0xe9, 0xbf, 0x6e, 0x5e, 0x49, 0x3e, 0x53,
0x00, 0x00, 0x00, 0x00 // Size of Data (0)
];
var audio = document.getElementById("audio");
function LoadEME() {
var options = [{
initDataType: 'cenc',
audioType: 'audio/mp4; codecs="mp4a.40.2"',
}];
navigator.requestMediaKeySystemAccess("org.w3.clearkey", options)
.then((keySystemAccess) => {
return keySystemAccess.createMediaKeys();
}, bail("Failed to request key system access."))
.then((mediaKeys) => {
audio.setMediaKeys(mediaKeys);
var session = mediaKeys.createSession();
once(session, "message", (message) => {
is(message.messageType, 'license-request', "Expected a license-request");
var license = new TextEncoder().encode(JSON.stringify({
'keys': [{
'kty':'oct',
'kid':'L--K2BLfQpeD6b9uXkk-Uw',
'k':HexToBase64('7f412f0575f44f718259beef56ec7771')
}],
'type': 'temporary'
}));
session.update(license);
});
session.generateRequest('cenc', new Uint8Array(pssh));
});
}
function DownloadMedia(url, type, mediaSource) {
return new Promise(function(resolve, reject) {
var sourceBuffer = mediaSource.addSourceBuffer(type);
fetchWithXHR(url, (response) => {
once(sourceBuffer, "updateend", resolve);
sourceBuffer.appendBuffer(new Uint8Array(response));
});
});
}
function LoadMSE() {
var ms = new MediaSource();
audio.src = URL.createObjectURL(ms);
once(ms, "sourceopen", ()=>{
DownloadMedia('short-audio-fragmented-cenc-without-pssh.mp4', 'audio/mp4; codecs="mp4a.40.2"', ms)
.then(() => { ms.endOfStream(); LoadEME();});
});
audio.addEventListener("loadeddata", SimpleTest.finish);
}
SetupEMEPref(LoadMSE);
</script>
</pre>
</body>
</html>

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

@ -31,9 +31,11 @@ function startTest(test, token) {
manager.started(token); manager.started(token);
var a = new Audio(test.name); var a = new Audio(test.name);
a.autoplay = true; a.autoplay = true;
document.body.appendChild(a);
a.addEventListener("ended", a.addEventListener("ended",
function(e){ function(e){
ok(true, "[" + a.src + "]We should get to the end. Oh look we did."); ok(true, "[" + a.src + "]We should get to the end. Oh look we did.");
a.remove();
manager.finished(token); manager.finished(token);
}, },
false); false);

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

@ -33,9 +33,9 @@
#include "nsGlobalWindow.h" #include "nsGlobalWindow.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsIIDNService.h"
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h" #include "nsIScriptContext.h"
#include "nsIUnicodeNormalizer.h"
#include "nsDOMJSUtils.h" #include "nsDOMJSUtils.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsWildCard.h" #include "nsWildCard.h"
@ -1935,18 +1935,25 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
} }
nsCOMPtr<nsIUnicodeNormalizer> normalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID); nsCOMPtr<nsIIDNService> idnService = do_GetService(NS_IDNSERVICE_CONTRACTID);
if (!normalizer) { if (!idnService) {
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
} }
nsAutoString normalizedUTF16Origin; // This is a bit messy: we convert to UTF-8 here, but then
res = normalizer->NormalizeUnicodeNFKC(utf16Origin, normalizedUTF16Origin); // nsIDNService::Normalize will convert back to UTF-16 for processing,
// and back to UTF-8 again to return the result.
// Alternative: perhaps we should add a NormalizeUTF16 version of the API,
// and just convert to UTF-8 for the final return (resulting in one
// encoding form conversion instead of three).
NS_ConvertUTF16toUTF8 utf8Origin(utf16Origin);
nsAutoCString normalizedUTF8Origin;
res = idnService->Normalize(utf8Origin, normalizedUTF8Origin);
if (NS_FAILED(res)) { if (NS_FAILED(res)) {
return NPERR_GENERIC_ERROR; return NPERR_GENERIC_ERROR;
} }
*(char**)result = ToNewUTF8String(normalizedUTF16Origin); *(char**)result = ToNewCString(normalizedUTF8Origin);
return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR; return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
} }

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

@ -2093,6 +2093,22 @@ nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag)
} }
} }
static bool
PluginInfoIsFlash(const nsPluginInfo& info)
{
if (strcmp(info.fDescription, "Shockwave Flash") != 0) {
return false;
}
for (uint32_t i = 0; i < info.fVariantCount; ++i) {
if (info.fMimeTypeArray[i] &&
(!strcmp(info.fMimeTypeArray[i], "application/x-shockwave-flash") ||
!strcmp(info.fMimeTypeArray[i], "application/x-shockwave-flash-test"))) {
return true;
}
}
return false;
}
typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void); typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir, nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
@ -2113,6 +2129,8 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
("nsPluginHost::ScanPluginsDirectory dir=%s\n", dirPath.get())); ("nsPluginHost::ScanPluginsDirectory dir=%s\n", dirPath.get()));
#endif #endif
bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true);
nsCOMPtr<nsISimpleEnumerator> iter; nsCOMPtr<nsISimpleEnumerator> iter;
rv = pluginsDir->GetDirectoryEntries(getter_AddRefs(iter)); rv = pluginsDir->GetDirectoryEntries(getter_AddRefs(iter));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
@ -2215,7 +2233,8 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
res = pluginFile.GetPluginInfo(info, &library); res = pluginFile.GetPluginInfo(info, &library);
} }
// if we don't have mime type don't proceed, this is not a plugin // if we don't have mime type don't proceed, this is not a plugin
if (NS_FAILED(res) || !info.fMimeTypeArray) { if (NS_FAILED(res) || !info.fMimeTypeArray ||
(flashOnly && !PluginInfoIsFlash(info))) {
RefPtr<nsInvalidPluginTag> invalidTag = new nsInvalidPluginTag(filePath.get(), RefPtr<nsInvalidPluginTag> invalidTag = new nsInvalidPluginTag(filePath.get(),
fileModTime); fileModTime);
pluginFile.FreePluginInfo(info); pluginFile.FreePluginInfo(info);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше