Merging mozilla-central to Places.

This commit is contained in:
Shawn Wilsher 2010-10-29 11:39:41 -07:00
Родитель 6f48d0fb79 28678340e7
Коммит 9bd9238f38
124 изменённых файлов: 4165 добавлений и 2998 удалений

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

@ -91,14 +91,6 @@ nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
return arg.mAccessible;
}
void
nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocument *aDocument)
{
nsCOMPtr<nsISupports> container = aDocument->GetContainer();
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container);
ShutdownDocAccessiblesInTree(treeItem, aDocument);
}
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager protected
@ -132,21 +124,6 @@ nsAccDocManager::Shutdown()
ClearDocCache();
}
void
nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
{
nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(aDocument);
if (!docAccessible)
return;
// We're allowed to not remove listeners when accessible document is shutdown
// since we don't keep strong reference on chrome event target and listeners
// are removed automatically when chrome event target goes away.
docAccessible->Shutdown();
mDocAccessibleCache.Remove(aDocument);
}
////////////////////////////////////////////////////////////////////////////////
// nsISupports
@ -316,7 +293,14 @@ nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent)
return NS_OK;
// Shutdown this one and sub document accessibles.
ShutdownDocAccessiblesInTree(document);
// We're allowed to not remove listeners when accessible document is
// shutdown since we don't keep strong reference on chrome event target and
// listeners are removed automatically when chrome event target goes away.
nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(document);
if (docAccessible)
docAccessible->Shutdown();
return NS_OK;
}
@ -500,35 +484,6 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
return docAcc;
}
void
nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
nsIDocument *aDocument)
{
nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aTreeItem));
if (treeNode) {
PRInt32 subDocumentsCount = 0;
treeNode->GetChildCount(&subDocumentsCount);
for (PRInt32 idx = 0; idx < subDocumentsCount; idx++) {
nsCOMPtr<nsIDocShellTreeItem> treeItemChild;
treeNode->GetChildAt(idx, getter_AddRefs(treeItemChild));
NS_ASSERTION(treeItemChild, "No tree item when there should be");
if (!treeItemChild)
continue;
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(treeItemChild));
nsCOMPtr<nsIContentViewer> contentViewer;
docShell->GetContentViewer(getter_AddRefs(contentViewer));
if (!contentViewer)
continue;
ShutdownDocAccessiblesInTree(treeItemChild, contentViewer->GetDocument());
}
}
ShutdownDocAccessible(aDocument);
}
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager static

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

@ -75,13 +75,6 @@ public:
*/
nsAccessible* FindAccessibleInCache(nsINode* aNode) const;
/**
* Shutdown document accessibles in the tree starting from the given one.
*
* @param aDocument [in] the DOM document of start document accessible
*/
void ShutdownDocAccessiblesInTree(nsIDocument *aDocument);
/**
* Return document accessible from the cache. Convenient method for testing.
*/
@ -90,6 +83,14 @@ public:
return mDocAccessibleCache.GetWeak(aDocument);
}
/**
* Called by document accessible when it gets shutdown.
*/
inline void NotifyOfDocumentShutdown(nsIDocument* aDocument)
{
mDocAccessibleCache.Remove(aDocument);
}
protected:
nsAccDocManager() { };
@ -103,11 +104,6 @@ protected:
*/
void Shutdown();
/**
* Shutdown the document accessible.
*/
void ShutdownDocAccessible(nsIDocument* aDocument);
private:
nsAccDocManager(const nsAccDocManager&);
nsAccDocManager& operator =(const nsAccDocManager&);
@ -156,12 +152,6 @@ private:
*/
nsDocAccessible *CreateDocOrRootAccessible(nsIDocument *aDocument);
/**
* Shutdown document accessibles in the tree starting from given tree item.
*/
void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
nsIDocument *aDocument);
typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, nsDocAccessible>
nsDocAccessibleHashtable;

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

@ -382,7 +382,8 @@ nsAccessNode::ScrollTo(PRUint32 aScrollType)
PRInt16 vPercent, hPercent;
nsCoreUtils::ConvertScrollTypeToPercents(aScrollType, &vPercent, &hPercent);
return shell->ScrollContentIntoView(content, vPercent, hPercent);
return shell->ScrollContentIntoView(content, vPercent, hPercent,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
}
NS_IMETHODIMP

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

@ -543,7 +543,10 @@ nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
return;
NS_LOG_ACCDOCDESTROY("presshell destroyed", doc)
ShutdownDocAccessible(doc);
nsDocAccessible* docAccessible = GetDocAccessibleFromCache(doc);
if (docAccessible)
docAccessible->Shutdown();
}
void

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

@ -2368,7 +2368,8 @@ nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
// Scroll into view.
presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_PRESSHELL_SCROLL_ANYWHERE,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
// Fire mouse down and mouse up events.
PRBool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,

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

@ -675,6 +675,10 @@ nsDocAccessible::Shutdown()
mParent->RemoveChild(this);
}
PRUint32 childDocCount = mChildDocuments.Length();
for (PRUint32 idx = 0; idx < childDocCount; idx++)
mChildDocuments[idx]->Shutdown();
mChildDocuments.Clear();
mWeakShell = nsnull; // Avoid reentrancy
@ -686,6 +690,8 @@ nsDocAccessible::Shutdown()
mDocument = nsnull;
nsHyperTextAccessibleWrap::Shutdown();
GetAccService()->NotifyOfDocumentShutdown(kungFuDeathGripDoc);
}
nsIFrame*

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

@ -169,7 +169,7 @@ nsOuterDocAccessible::Shutdown()
if (childAcc) {
NS_LOG_ACCDOCDESTROY("outerdoc's child document shutdown",
childAcc->GetDocumentNode())
GetAccService()->ShutdownDocAccessiblesInTree(childAcc->GetDocumentNode());
childAcc->Shutdown();
}
nsAccessibleWrap::Shutdown();

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

@ -826,12 +826,7 @@
#ifdef WINCE
defaulticonsize="small" iconsize="small"
#endif
#ifdef XP_WIN
tabsontop="true"
#endif
#ifdef XP_MACOSX
tabsontop="true"
#endif
persist="tabsontop">
<!-- Menu -->
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"

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

@ -380,8 +380,7 @@ CSPRep.prototype = {
},
/**
* Generates string representation of the policy. Should be fairly similar
* to the original.
* Generates canonical string representation of the policy.
*/
toString:
function csp_toString() {
@ -607,8 +606,7 @@ CSPSourceList.prototype = {
},
/**
* Generates string representation of the Source List.
* Should be fairly similar to the original.
* Generates canonical string representation of the Source List.
*/
toString:
function() {
@ -639,7 +637,7 @@ CSPSourceList.prototype = {
},
/**
* Makes a new instance that resembles this object.
* Makes a new deep copy of this object.
* @returns
* a new CSPSourceList
*/
@ -951,7 +949,7 @@ CSPSource.fromString = function(aStr, self, enforceSelfChecks) {
// Allow scheme-only sources! These default to wildcard host/port,
// especially since host and port don't always matter.
// Example: "javascript:" and "data:"
if (!sObj._host) sObj._host = "*";
if (!sObj._host) sObj._host = CSPHost.fromString("*");
if (!sObj._port) sObj._port = "*";
} else {
// some host was defined.
@ -1050,8 +1048,7 @@ CSPSource.prototype = {
},
/**
* Generates string representation of the Source.
* Should be fairly similar to the original.
* Generates canonical string representation of the Source.
*/
toString:
function() {
@ -1069,7 +1066,7 @@ CSPSource.prototype = {
},
/**
* Makes a new instance that resembles this object.
* Makes a new deep copy of this object.
* @returns
* a new CSPSource
*/
@ -1172,13 +1169,28 @@ CSPSource.prototype = {
return null;
}
// NOTE: Both sources must have a host, if they don't, something funny is
// going on. The fromString() factory method should have set the host to
// * if there's no host specified in the input. Regardless, if a host is
// not present either the scheme is hostless or any host should be allowed.
// This means we can use the other source's host as the more restrictive
// host expression, or if neither are present, we can use "*", but the
// error should still be reported.
// host
if (!this._host)
newSource._host = that._host;
else if (!that._host)
newSource._host = this._host;
else // both this and that have hosts
if (this._host && that._host) {
newSource._host = this._host.intersectWith(that._host);
} else if (this._host) {
CSPError("intersecting source with undefined host: " + that.toString());
newSource._host = this._host.clone();
} else if (that._host) {
CSPError("intersecting source with undefined host: " + this.toString());
newSource._host = that._host.clone();
} else {
CSPError("intersecting two sources with undefined hosts: " +
this.toString() + " and " + that.toString());
newSource._host = CSPHost.fromString("*");
}
return newSource;
},
@ -1266,8 +1278,7 @@ CSPHost.fromString = function(aStr) {
CSPHost.prototype = {
/**
* Generates string representation of the Source.
* Should be fairly similar to the original.
* Generates canonical string representation of the Host.
*/
toString:
function() {
@ -1275,7 +1286,7 @@ CSPHost.prototype = {
},
/**
* Makes a new instance that resembles this object.
* Makes a new deep copy of this object.
* @returns
* a new CSPHost
*/
@ -1297,7 +1308,7 @@ CSPHost.prototype = {
*/
permits:
function(aHost) {
if (!aHost) return false;
if (!aHost) aHost = CSPHost.fromString("*");
if (!(aHost instanceof CSPHost)) {
// -- compare CSPHost to String

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

@ -5325,7 +5325,7 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor)
nsIEventStateManager* esm =
aVisitor.mPresContext->EventStateManager();
nsEventStateManager::SetGlobalActiveContent(
nsEventStateManager::SetActiveManager(
static_cast<nsEventStateManager*>(esm), this);
}
}

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

@ -35,6 +35,7 @@
//load('CSPUtils.jsm');
Components.utils.import('resource://gre/modules/CSPUtils.jsm');
Components.utils.import('resource://gre/modules/NetUtil.jsm');
// load the HTTP server
do_load_httpd_js();
@ -190,6 +191,7 @@ test(
//"funny characters (#) should not work for host.");
do_check_eq(null, CSPSource.fromString("a#2-c.com"));
//print(" --- Stop ignoring errors that print ---\n");
//"failed to parse host with port.");
@ -229,6 +231,16 @@ test(
do_check_true(src.permits("https://foobar.com"));
//"src should reject other hosts"
do_check_false(src.permits("https://a.com"));
src = CSPSource.create("javascript:", "https://foobar.com:443");
//"hostless schemes should be parseable."
var aUri = NetUtil.newURI("javascript:alert('foo');");
do_check_true(src.permits(aUri));
//"src should reject other hosts"
do_check_false(src.permits("https://a.com"));
//"nothing else should be allowed"
do_check_false(src.permits("https://foobar.com"));
});
///////////////////// Test the source list //////////////////////

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

@ -2074,6 +2074,7 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
PRBool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
targetContent, isSelection);
if (dragStarted) {
sActiveESM = nsnull;
aEvent->flags |= NS_EVENT_FLAG_STOP_DISPATCH;
}
}
@ -2935,7 +2936,6 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
if (par)
activeContent = par;
}
SetGlobalActiveContent(this, activeContent);
}
}
else {
@ -2943,11 +2943,12 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
// any of our own processing of a drag. Workaround for bug 43258.
StopTrackingDragGesture();
}
SetActiveManager(this, activeContent);
}
break;
case NS_MOUSE_BUTTON_UP:
{
ClearGlobalActiveContent();
ClearGlobalActiveContent(this);
if (IsMouseEventReal(aEvent)) {
if (!mCurrentTarget) {
nsIFrame* targ;
@ -3206,6 +3207,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
targetContent, &status);
}
}
ClearGlobalActiveContent(this);
break;
}
case NS_DRAGDROP_EXIT:
@ -4706,22 +4708,25 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
}
void
nsEventStateManager::SetGlobalActiveContent(nsEventStateManager* aNewESM,
nsIContent* aContent)
nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM,
nsIContent* aContent)
{
if (sActiveESM && aNewESM != sActiveESM) {
sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
}
sActiveESM = aNewESM;
if (sActiveESM) {
if (sActiveESM && aContent) {
sActiveESM->SetContentState(aContent, NS_EVENT_STATE_ACTIVE);
}
}
void
nsEventStateManager::ClearGlobalActiveContent()
nsEventStateManager::ClearGlobalActiveContent(nsEventStateManager* aClearer)
{
if (sActiveESM) {
if (aClearer) {
aClearer->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
}
if (sActiveESM && aClearer != sActiveESM) {
sActiveESM->SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
}
sActiveESM = nsnull;

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

@ -159,8 +159,10 @@ public:
static nsIEventStateManager* GetActiveEventStateManager() { return sActiveESM; }
static void SetGlobalActiveContent(nsEventStateManager* aNewESM,
nsIContent* aContent);
// Sets aNewESM to be the active event state manager, and
// if aContent is non-null, marks the object as active.
static void SetActiveManager(nsEventStateManager* aNewESM,
nsIContent* aContent);
protected:
void UpdateCursor(nsPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
/**
@ -415,7 +417,7 @@ protected:
static nsEventStateManager* sActiveESM;
static void ClearGlobalActiveContent();
static void ClearGlobalActiveContent(nsEventStateManager* aClearer);
// Functions used for click hold context menus
PRBool mClickHoldContextMenu;

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

@ -808,7 +808,8 @@ nsGenericHTMLElement::ScrollIntoView(PRBool aTop, PRUint8 optional_argc)
NS_PRESSHELL_SCROLL_BOTTOM;
presShell->ScrollContentIntoView(this, vpercent,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_PRESSHELL_SCROLL_ANYWHERE,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK;
}

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

@ -439,7 +439,7 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
if (NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
nsIEventStateManager* esm =
aVisitor.mPresContext->EventStateManager();
nsEventStateManager::SetGlobalActiveContent(
nsEventStateManager::SetActiveManager(
static_cast<nsEventStateManager*>(esm), this);
}
nsIFocusManager* fm = nsFocusManager::GetFocusManager();

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

@ -236,6 +236,8 @@ _TEST_FILES = \
test_bug600155.html \
test_bug556007.html \
test_bug606817.html \
test_bug297761.html \
file_bug297761.html \
$(NULL)
libs:: $(_TEST_FILES)

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

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<base href="http://www.mozilla.org/">
</head>
<body>
<form action="">
<input type='submit' formaction="">
<button type='submit' formaction=""></button>
<input id='i' type='image' formaction="">
</form>
</body>
</html>

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

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=297761
-->
<head>
<title>Test for Bug 297761</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=297761">Mozilla Bug 297761</a>
<p id="display"></p>
<div id="content">
<iframe src="file_bug297761.html"></iframe>
<iframe src="file_bug297761.html"></iframe>
<iframe src="file_bug297761.html"></iframe>
<iframe src="file_bug297761.html"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 297761 **/
SimpleTest.waitForExplicitFinish();
var nbTests = 4;
var curTest = 0;
function nextTest()
{
if (curTest == 3) {
frames[curTest].document.forms[0].submit();
} else {
var el = null;
if (curTest == 2) {
el = frames[curTest].document.getElementById('i');
} else {
el = frames[curTest].document.forms[0].elements[curTest];
}
el.focus();
el.click();
}
}
function frameLoaded(aFrame)
{
var documentLocation = location.href.replace(/\.html.*/, "\.html");
is(aFrame.contentWindow.location.href.replace(/\?x=0&y=0/, ""),
documentLocation.replace(/test_bug/, "file_bug"),
"form should have been submitted to the document location");
if (++curTest == nbTests) {
SimpleTest.finish();
} else {
nextTest();
}
}
function runTest()
{
// Initialize event handlers.
var frames = document.getElementsByTagName('iframe');
for (var i=0; i<nbTests; ++i) {
frames[i].setAttribute('onload', "frameLoaded(this);");
}
nextTest();
}
addLoadEvent(runTest);
</script>
</pre>
</body>
</html>

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

@ -22,57 +22,68 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=392567
/** Test for Bug 392567 **/
var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar";
var jarUrl = "jar:" + dataUrl + "!/index.html";
var httpUrl = location.href.replace(/\.html.*/, "_404");
var previousDir = location.href.replace(/test\/[^\/]*$/, "");
SimpleTest.waitForExplicitFinish();
var form = document.forms.testForm;
var frame = frames.testFrame;
document.getElementById("testFrame").onload = processTestResult;
// List of tests to run, each test consists of form action URL and expected result URL
var tests = [
[jarUrl, jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null],
["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS", null],
["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS", null],
[httpUrl, httpUrl + "?$PARAMS", null],
[httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ],
[httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null],
["", jarUrl + "?key=value0", null],
[" ", jarUrl + "?key=value0", document.location],
["../", previousDir + "?$PARAMS", previousDir],
];
var currentTest = -1;
SimpleTest.waitForExplicitFinish();
runNextTest();
function runNextTest() {
currentTest++;
if (currentTest >= tests.length) {
SimpleTest.finish();
function runTests()
{
if (window.location.search.match(/\?key=value/)) {
return;
}
form.setAttribute("action", tests[currentTest][0]);
is(form.action, tests[currentTest][0],
"action IDL attribute should reflect the action content attribute");
is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0],
"mozActionUri IDL attribute should resolve the action URI");
form.key.value = "value" + currentTest;
form.submit();
var dataUrl = "http://mochi.test:8888/tests/content/html/content/test/bug392567.jar";
var jarUrl = "jar:" + dataUrl + "!/index.html";
var httpUrl = location.href.replace(/\.html.*/, "_404");
var previousDir = location.href.replace(/test\/[^\/]*$/, "");
var documentURL = location.href.replace(/\.html.*/, "\.html");
var form = document.forms.testForm;
var frame = frames.testFrame;
document.getElementById("testFrame").onload = processTestResult;
// List of tests to run, each test consists of form action URL and expected result URL
var tests = [
[jarUrl, jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS", null],
[jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5", null],
["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS", null],
["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS", null],
[httpUrl, httpUrl + "?$PARAMS", null],
[httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS", null ],
[httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5", null],
["", documentURL + "?$PARAMS", null],
[" ", documentURL + "?$PARAMS", document.location],
["../", previousDir + "?$PARAMS", previousDir],
];
var currentTest = -1;
runNextTest();
function runNextTest() {
currentTest++;
if (currentTest >= tests.length) {
SimpleTest.finish();
return;
}
form.setAttribute("action", tests[currentTest][0]);
is(form.action, tests[currentTest][0],
"action IDL attribute should reflect the action content attribute");
is(form.mozActionUri, tests[currentTest][2] ? tests[currentTest][2] : tests[currentTest][0],
"mozActionUri IDL attribute should resolve the action URI");
form.key.value = "value" + currentTest;
form.submit();
}
function processTestResult() {
var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
setTimeout(runNextTest, 0);
}
}
function processTestResult() {
var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
setTimeout(runNextTest, 0);
}
addLoadEvent(runTests);
</script>
</pre>

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

@ -145,6 +145,7 @@ NS_NewXULPrototypeCache(nsISupports* aOuter, REFNSIID aIID, void** aResult)
nsXULPrototypeCache *p = result;
obsSvc->AddObserver(p, "chrome-flush-skin-caches", PR_FALSE);
obsSvc->AddObserver(p, "chrome-flush-caches", PR_FALSE);
obsSvc->AddObserver(p, "startupcache-invalidate", PR_FALSE);
}
return rv;
@ -410,10 +411,6 @@ nsXULPrototypeCache::AbortFastLoads()
NS_BREAK();
#endif
// Save a strong ref to the FastLoad file, so we can remove it after we
// close open streams to it.
nsCOMPtr<nsIFile> file = gFastLoadFile;
// Flush the XUL cache for good measure, in case we cached a bogus/downrev
// script, somehow.
Flush();
@ -421,29 +418,42 @@ nsXULPrototypeCache::AbortFastLoads()
// Clear the FastLoad set
mFastLoadURITable.Clear();
if (! gFastLoadService)
return;
nsCOMPtr<nsIFastLoadService> fastLoadService = gFastLoadService;
nsCOMPtr<nsIFile> file = gFastLoadFile;
nsresult rv;
if (! fastLoadService) {
fastLoadService = do_GetFastLoadService();
if (! fastLoadService)
return;
rv = fastLoadService->NewFastLoadFile(XUL_FASTLOAD_FILE_BASENAME,
getter_AddRefs(file));
if (NS_FAILED(rv))
return;
}
// Fetch the current input (if FastLoad file existed) or output (if we're
// creating the FastLoad file during this app startup) stream.
nsCOMPtr<nsIObjectInputStream> objectInput;
nsCOMPtr<nsIObjectOutputStream> objectOutput;
gFastLoadService->GetInputStream(getter_AddRefs(objectInput));
gFastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
fastLoadService->GetInputStream(getter_AddRefs(objectInput));
fastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
if (objectOutput) {
gFastLoadService->SetOutputStream(nsnull);
fastLoadService->SetOutputStream(nsnull);
if (NS_SUCCEEDED(objectOutput->Close()) && gChecksumXULFastLoadFile)
gFastLoadService->CacheChecksum(gFastLoadFile,
objectOutput);
fastLoadService->CacheChecksum(file,
objectOutput);
}
if (objectInput) {
// If this is the last of one or more XUL master documents loaded
// together at app startup, close the FastLoad service's singleton
// input stream now.
gFastLoadService->SetInputStream(nsnull);
fastLoadService->SetInputStream(nsnull);
objectInput->Close();
}
@ -462,13 +472,15 @@ nsXULPrototypeCache::AbortFastLoads()
}
file->MoveToNative(nsnull, NS_LITERAL_CSTRING("Aborted.mfasl"));
#else
file->Remove(PR_FALSE);
rv = file->Remove(PR_FALSE);
if (NS_FAILED(rv))
NS_WARNING("Failed to remove fastload file, fastload data may be outdated");
#endif
}
// If the list is empty now, the FastLoad process is done.
NS_RELEASE(gFastLoadService);
NS_RELEASE(gFastLoadFile);
NS_IF_RELEASE(gFastLoadService);
NS_IF_RELEASE(gFastLoadFile);
}

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

@ -1800,7 +1800,8 @@ nsFocusManager::ScrollIntoView(nsIPresShell* aPresShell,
if (!(aFlags & FLAG_NOSCROLL))
aPresShell->ScrollContentIntoView(aContent,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
}

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

@ -1052,7 +1052,6 @@ PluginInstanceChild::CreatePluginWindow()
return false;
// Apparently some plugins require an ASCII WndProc.
printf("setting DefWindowProcA\n");
SetWindowLongPtrA(mPluginWindowHWND, GWLP_WNDPROC,
reinterpret_cast<LONG_PTR>(DefWindowProcA));

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

@ -57,6 +57,7 @@ public class CrashReporter extends Activity
{
static final String kMiniDumpPathKey = "upload_file_minidump";
static final String kPageURLKey = "URL";
static final String kNotesKey = "Notes";
ProgressDialog mProgressDialog;
File mPendingMinidumpFile;
File mPendingExtrasFile;
@ -230,10 +231,35 @@ public class CrashReporter extends Activity
if (key.equals(kPageURLKey)) {
if (includeURLCheckbox.isChecked())
sendPart(os, boundary, key, extras.get(key));
} else if (!key.equals("ServerURL")){
} else if (!key.equals("ServerURL") && !key.equals(kNotesKey)) {
sendPart(os, boundary, key, extras.get(key));
}
}
// Add some extra information to notes so its displayed by
// crash-stats.mozilla.org. Remove this when bug 607942 is fixed.
String notes = extras.containsKey(kNotesKey) ? extras.get(kNotesKey) +
"\n" : "";
if (@MOZ_MIN_CPU_VERSION@ < 7)
notes += "nothumb Build\n";
notes += Build.MANUFACTURER + " ";
notes += Build.MODEL + "\n";
notes += Build.FINGERPRINT;
sendPart(os, boundary, kNotesKey, notes);
sendPart(os, boundary, "Min_ARM_Version", "@MOZ_MIN_CPU_VERSION@");
sendPart(os, boundary, "Android_Manufacturer", Build.MANUFACTURER);
sendPart(os, boundary, "Android_Model", Build.MODEL);
sendPart(os, boundary, "Android_Board", Build.BOARD);
sendPart(os, boundary, "Android_Brand", Build.BRAND);
sendPart(os, boundary, "Android_CPU_ABI", Build.CPU_ABI);
sendPart(os, boundary, "Android_CPU_ABI2", Build.CPU_ABI2);
sendPart(os, boundary, "Android_Device", Build.DEVICE);
sendPart(os, boundary, "Android_Display", Build.DISPLAY);
sendPart(os, boundary, "Android_Fingerprint", Build.FINGERPRINT);
sendPart(os, boundary, "Android_Hardware", Build.HARDWARE);
sendPart(os, boundary, "Android_Version", Build.VERSION.SDK_INT + " (" + Build.VERSION.CODENAME + ")");
sendFile(os, boundary, kMiniDumpPathKey, minidumpFile);
os.write(("\r\n--" + boundary + "--\r\n").getBytes());
os.flush();

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

@ -81,7 +81,11 @@
// Because the QPainter backend has some problems with glyphs rendering
// it is better to use image or xlib cairo backends by default
#if (MOZ_PLATFORM_MAEMO == 6)
#define DEFAULT_RENDER_MODE RENDER_BUFFERED
#else
#define DEFAULT_RENDER_MODE RENDER_DIRECT
#endif
static QPaintEngine::Type sDefaultQtPaintEngineType = QPaintEngine::X11;
gfxFontconfigUtils *gfxQtPlatform::sFontconfigUtils = nsnull;
@ -146,6 +150,9 @@ gfxQtPlatform::gfxQtPlatform()
case 1:
mRenderMode = RENDER_BUFFERED;
break;
case 2:
mRenderMode = RENDER_DIRECT;
break;
default:
mRenderMode = RENDER_QPAINTER;
}
@ -207,7 +214,7 @@ gfxQtPlatform::CreateOffscreenSurface(const gfxIntSize& size,
}
#endif
if (mRenderMode == RENDER_BUFFERED &&
if ((mRenderMode == RENDER_BUFFERED || mRenderMode == RENDER_DIRECT) &&
sDefaultQtPaintEngineType != QPaintEngine::X11) {
newSurface = new gfxImageSurface(size, imageFormat);
return newSurface.forget();

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

@ -60,6 +60,8 @@ public:
RENDER_QPAINTER = 0,
/* Use offscreen buffer for rendering with image or xlib gfx backend */
RENDER_BUFFERED,
/* Direct rendering to Widget surface */
RENDER_DIRECT,
/* max */
RENDER_MODE_MAX
};

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

@ -90,25 +90,29 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
(surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA &&
(mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA))))
{
if (mTransformType == TRANSLATION_ONLY) {
mRenderState = RENDER_STATE_NATIVE_DRAWING;
// grab the DC. This can fail if there is a complex clipping path,
// in which case we'll have to fall back.
mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()));
mDC = mWinSurface->GetDCWithClip(mContext);
mTranslation = m.GetTranslation();
if (mDC) {
if (mTransformType == TRANSLATION_ONLY) {
mRenderState = RENDER_STATE_NATIVE_DRAWING;
mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()));
} else if (((mTransformType == AXIS_ALIGNED_SCALE)
&& (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) ||
(mNativeDrawFlags & CAN_COMPLEX_TRANSFORM))
{
mWorldTransform.eM11 = (FLOAT) m.xx;
mWorldTransform.eM12 = (FLOAT) m.yx;
mWorldTransform.eM21 = (FLOAT) m.xy;
mWorldTransform.eM22 = (FLOAT) m.yy;
mWorldTransform.eDx = (FLOAT) m.x0;
mWorldTransform.eDy = (FLOAT) m.y0;
mTranslation = m.GetTranslation();
} else if (((mTransformType == AXIS_ALIGNED_SCALE)
&& (mNativeDrawFlags & CAN_AXIS_ALIGNED_SCALE)) ||
(mNativeDrawFlags & CAN_COMPLEX_TRANSFORM))
{
mWorldTransform.eM11 = (FLOAT) m.xx;
mWorldTransform.eM12 = (FLOAT) m.yx;
mWorldTransform.eM21 = (FLOAT) m.xy;
mWorldTransform.eM22 = (FLOAT) m.yy;
mWorldTransform.eDx = (FLOAT) m.x0;
mWorldTransform.eDy = (FLOAT) m.y0;
mRenderState = RENDER_STATE_NATIVE_DRAWING;
mWinSurface = static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()));
mRenderState = RENDER_STATE_NATIVE_DRAWING;
}
}
}
@ -156,9 +160,6 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
if (mRenderState == RENDER_STATE_NATIVE_DRAWING) {
// we can just do native drawing directly to the context's surface
// grab the DC
mDC = mWinSurface->GetDCWithClip(mContext);
// do we need to use SetWorldTransform?
if (mTransformType != TRANSLATION_ONLY) {
SetGraphicsMode(mDC, GM_ADVANCED);

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

@ -104,18 +104,6 @@ js_GetStringChars(JSContext *cx, JSString *str)
void
JSString::flatten()
{
// Diagnostic: serialize all calls to this function to see
// if concurrent calls are crashing us.
JS_LOCK_RUNTIME(asCell()->compartment()->rt);
// The main body of this function can be executed only if
// the string is a rope. With multiple threads, it's possible
// we waited while another one ran, and the string has
// already been flattened for us.
if (!isRope()) {
JS_UNLOCK_RUNTIME(asCell()->compartment()->rt);
return;
}
JSString *topNode;
jschar *chars;
size_t capacity;
@ -193,8 +181,6 @@ JSString::flatten()
/* Set null terminator. */
chars[pos] = 0;
topNode->initFlatMutable(chars, pos, capacity);
JS_UNLOCK_RUNTIME(asCell()->compartment()->rt);
}
#ifdef JS_TRACER

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

@ -255,7 +255,7 @@ JSWrapper::obj_toString(JSContext *cx, JSObject *wrapper)
JSString *str;
if (!enter(cx, wrapper, JSID_VOID, GET))
return NULL;
str = JSProxyHandler::obj_toString(cx, wrapper);
str = obj_toStringHelper(cx, wrappedObject(wrapper));
leave(cx, wrapper);
return str;
}

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

@ -1624,6 +1624,8 @@ DocumentViewerImpl::Destroy()
mPresContext = nsnull;
}
mWindow = nsnull;
mViewManager = nsnull;
mContainer = nsnull;
return NS_OK;
@ -2679,7 +2681,8 @@ NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode)
// Tell the PresShell to scroll to the primary frame of the content.
NS_ENSURE_SUCCESS(presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_ANYWHERE),
NS_PRESSHELL_SCROLL_ANYWHERE,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN),
NS_ERROR_FAILURE);
return NS_OK;
}

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

@ -22,6 +22,7 @@
* Contributor(s):
* Steve Clark <buster@netscape.com>
* Dan Rosen <dr@netscape.com>
* Mihai Șucan <mihai.sucan@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -139,8 +140,8 @@ typedef struct CapturingContentInfo {
} CapturingContentInfo;
#define NS_IPRESSHELL_IID \
{ 0xb79574cd, 0x2555, 0x4b57, \
{ 0xb3, 0xf8, 0x27, 0x57, 0x3e, 0x60, 0x74, 0x01 } }
{ 0xd1978bee, 0x43b9, 0x40de, \
{ 0x95, 0x47, 0x85, 0x06, 0x5e, 0x02, 0xec, 0xb4 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
@ -544,10 +545,18 @@ public:
* horizontally . A value of NS_PRESSHELL_SCROLL_ANYWHERE means move
* the frame the minimum amount necessary in order for the entire
* frame to be visible horizontally (if possible)
* @param aFlags If SCROLL_FIRST_ANCESTOR_ONLY is set, only the nearest
* scrollable ancestor is scrolled, otherwise all
* scrollable ancestors may be scrolled if necessary.
* If SCROLL_OVERFLOW_HIDDEN is set then we may scroll in a
* direction even if overflow:hidden is specified in that
* direction; otherwise we will not scroll in that direction
* when overflow:hidden is set for that direction.
*/
virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent) = 0;
PRIntn aHPercent,
PRUint32 aFlags) = 0;
enum {
SCROLL_FIRST_ANCESTOR_ONLY = 0x01,

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

@ -26,6 +26,7 @@
* Dan Rosen <dr@netscape.com>
* Daniel Glazman <glazman@netscape.com>
* Mats Palmgren <matspal@gmail.com>
* Mihai Șucan <mihai.sucan@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -773,7 +774,8 @@ public:
virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent);
PRIntn aHPercent,
PRUint32 aFlags);
virtual PRBool ScrollFrameRectIntoView(nsIFrame* aFrame,
const nsRect& aRect,
PRIntn aVPercent,
@ -1005,7 +1007,8 @@ protected:
// Helper for ScrollContentIntoView
void DoScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent);
PRIntn aHPercent,
PRUint32 aFlags);
friend struct AutoRenderingStateSaveRestore;
friend struct RenderingState;
@ -3906,7 +3909,8 @@ PresShell::GoToAnchor(const nsAString& aAnchorName, PRBool aScroll)
if (content) {
if (aScroll) {
rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_PRESSHELL_SCROLL_ANYWHERE,
SCROLL_OVERFLOW_HIDDEN);
NS_ENSURE_SUCCESS(rv, rv);
nsIScrollableFrame* rootScroll = GetRootScrollFrameAsScrollable();
@ -4013,7 +4017,8 @@ PresShell::ScrollToAnchor()
return NS_OK;
nsresult rv = ScrollContentIntoView(mLastAnchorScrolledTo, NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_PRESSHELL_SCROLL_ANYWHERE,
SCROLL_OVERFLOW_HIDDEN);
mLastAnchorScrolledTo = nsnull;
return rv;
}
@ -4196,7 +4201,8 @@ static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame,
nsresult
PresShell::ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent)
PRIntn aHPercent,
PRUint32 aFlags)
{
nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing.
NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
@ -4221,7 +4227,7 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
// than a single best-effort scroll followed by one final scroll on the first
// completed reflow.
if (mContentToScrollTo) {
DoScrollContentIntoView(content, aVPercent, aHPercent);
DoScrollContentIntoView(content, aVPercent, aHPercent, aFlags);
}
return NS_OK;
}
@ -4229,7 +4235,8 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
void
PresShell::DoScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent)
PRIntn aHPercent,
PRUint32 aFlags)
{
NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
@ -4272,7 +4279,7 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent,
} while ((frame = frame->GetNextContinuation()));
ScrollFrameRectIntoView(container, frameBounds, aVPercent, aHPercent,
SCROLL_OVERFLOW_HIDDEN);
aFlags);
}
PRBool
@ -4873,7 +4880,8 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) {
// We didn't get interrupted. Go ahead and scroll to our content
DoScrollContentIntoView(mContentToScrollTo, mContentScrollVPosition,
mContentScrollHPosition);
mContentScrollHPosition,
SCROLL_OVERFLOW_HIDDEN);
mContentToScrollTo = nsnull;
}
}
@ -7161,7 +7169,8 @@ PresShell::PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& aTarge
// an edit box below the current view, you'll get the edit box aligned with
// the top of the window. This is arguably better behavior anyway.
rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
SCROLL_OVERFLOW_HIDDEN);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
frame = content->GetPrimaryFrame();
NS_WARN_IF_FALSE(frame, "No frame for focused content?");
@ -7224,7 +7233,8 @@ PresShell::GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl,
{
nsCOMPtr<nsIContent> focusedContent(do_QueryInterface(aCurrentEl));
ScrollContentIntoView(focusedContent, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_PRESSHELL_SCROLL_ANYWHERE,
SCROLL_OVERFLOW_HIDDEN);
nsPresContext* presContext = GetPresContext();

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

@ -54,6 +54,33 @@ function sendMouseUp(el) {
utils.sendMouseEvent('mouseup', rect.left + 5, rect.top + 5, 0, 1, 0);
}
function fireEvent(target, event) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var utils =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.dispatchDOMEventViaPresShell(target, event, true);
}
function fireDrop(element) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var ds = Components.classes["@mozilla.org/widget/dragservice;1"].
getService(Components.interfaces.nsIDragService);
ds.startDragSession();
var event = document.createEvent("DragEvents");
event.initDragEvent("dragover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null);
fireEvent(element, event);
event = document.createEvent("DragEvents");
event.initDragEvent("drop", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null, null);
fireEvent(element, event);
ds.endDragSession(false);
ok(!ds.getCurrentSession(), "There shouldn't be a drag session anymore!");
}
function runTest() {
var d1 = document.getElementById("d1");
var didGetMouseMove = false;
@ -65,7 +92,27 @@ function runTest() {
true);
sendMouseMoveFaraway(d1);
ok(didGetMouseMove, "Should have got mousemove!");
sendMouseUp(d1)
sendMouseUp(d1);
didGetMouseMove = false;
document.addEventListener("mousedown",
function (e) {
e.preventDefault();
},
true);
sendMouseDown(d1);
sendMouseMoveFaraway(d1);
ok(didGetMouseMove, "Should have got mousemove! (2)");
sendMouseUp(d1);
didGetMouseMove = false;
sendMouseDown(d1);
fireDrop(d1);
sendMouseMoveFaraway(d1);
ok(!didGetMouseMove, "Shouldn't have got mousemove!");
SimpleTest.finish();
}

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

@ -365,6 +365,7 @@ public:
static void RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
void SetupCARefresh();
void* FixUpPluginWindow(PRInt32 inPaintState);
void HidePluginWindow();
// Set a flag that (if true) indicates the plugin port info has changed and
// SetWindow() needs to be called.
void SetPluginPortChanged(PRBool aState) { mPluginPortChanged = aState; }
@ -1102,8 +1103,6 @@ nsObjectFrame::CallSetWindow()
if (IsHidden())
return;
PRBool windowless = (window->type == NPWindowTypeDrawable);
// refresh the plugin port as well
window->window = mInstanceOwner->GetPluginPortFromWidget();
@ -2463,7 +2462,11 @@ DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop)
if (DoDelayedStop(aInstanceOwner, aDelayedStop))
return;
#if defined(XP_MACOSX)
aInstanceOwner->HidePluginWindow();
#endif
inst->Stop();
nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
@ -2554,7 +2557,6 @@ nsObjectFrame::StopPluginInternal(PRBool aDelayedStop)
nsTArray<nsIWidget::Configuration> configurations;
GetEmptyClipConfiguration(&configurations);
parent->ConfigureChildren(configurations);
DidSetWidgetGeometry();
}
}
else {
@ -6429,6 +6431,19 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
return nsnull;
}
void
nsPluginInstanceOwner::HidePluginWindow()
{
if (!mPluginWindow || !mInstance) {
return;
}
mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
mPluginWindow->clipRect.right = mPluginWindow->clipRect.left;
mWidgetVisible = PR_FALSE;
mInstance->SetWindow(mPluginWindow);
}
#endif // XP_MACOSX
// Little helper function to resolve relative URL in

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

@ -196,7 +196,8 @@ inFlasher::ScrollElementIntoView(nsIDOMElement *aElement)
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_ANYWHERE /* VPercent */,
NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */);
NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK;
}

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

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="padding:50px; border-radius:50px; width:400px; height:400px;">
<input type="radio">
<input type="checkbox">
</div>
</body>
</html>

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

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<body>
<div style="padding:50px; border-radius:50px; width:400px; height:400px; overflow:hidden;">
<input type="radio">
<input type="checkbox">
</div>
</body>
</html>

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

@ -61,4 +61,6 @@ skip-if(gtk2Widget) random-if(d2d) == resizer-bottomend-rtl.xul resizer-bottomen
skip-if(!winWidget) == scroll-thumb-minimum-size-notheme.html scroll-thumb-minimum-size-notheme-ref.html
# skip-if(!winWidget) == scroll-thumb-minimum-size-theme.html scroll-thumb-minimum-size-theme-ref.html # Bug 512206
== border-radius.html border-radius-ref.html
== checkbox-dynamic-1.html checkbox-dynamic-1-ref.html

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* Original Author: David W. Hyatt (hyatt@netscape.com)
* Mihai Șucan <mihai.sucan@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -254,56 +255,18 @@ NS_IMETHODIMP nsScrollBoxObject::ScrollToLine(PRInt32 line)
NS_IMETHODIMP nsScrollBoxObject::ScrollToElement(nsIDOMElement *child)
{
NS_ENSURE_ARG_POINTER(child);
nsIScrollableFrame* sf = GetScrollFrame();
if (!sf)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresShell> shell = GetPresShell(PR_FALSE);
if (!shell) {
return NS_ERROR_UNEXPECTED;
}
nsIFrame* scrolledBox = GetScrolledBox(this);
if (!scrolledBox)
return NS_ERROR_FAILURE;
nsRect rect, crect;
nsCOMPtr<nsIDOMDocument> doc;
child->GetOwnerDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDocument> nsDoc(do_QueryInterface(doc));
if(!nsDoc)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIBoxObject> childBoxObject;
nsDoc->GetBoxObjectFor(child, getter_AddRefs(childBoxObject));
if(!childBoxObject)
return NS_ERROR_UNEXPECTED;
PRInt32 x,y;
childBoxObject->GetX(&x);
childBoxObject->GetY(&y);
// get the twips rectangle from the boxobject (which has pixels)
rect.x = nsPresContext::CSSPixelsToAppUnits(x);
rect.y = nsPresContext::CSSPixelsToAppUnits(y);
// TODO: make sure the child is inside the box
// get our current info
nsPoint cp = sf->GetScrollPosition();
nsIntRect prect;
GetOffsetRect(prect);
crect = prect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel());
nscoord newx=cp.x, newy=cp.y;
// we only scroll in the direction of the scrollbox orientation
// always scroll to left or top edge of child element
if (scrolledBox->IsHorizontal()) {
newx = rect.x - crect.x;
} else {
newy = rect.y - crect.y;
}
// scroll away
sf->ScrollTo(nsPoint(newx, newy), nsIScrollableFrame::INSTANT);
nsCOMPtr<nsIContent> content = do_QueryInterface(child);
shell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_LEFT,
nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK;
}
@ -347,68 +310,17 @@ NS_IMETHODIMP nsScrollBoxObject::EnsureElementIsVisible(nsIDOMElement *child)
{
NS_ENSURE_ARG_POINTER(child);
// Start with getting info about the child, since that will flush
// layout and possibly destroy scrollable views, presshells, etc.
nsCOMPtr<nsIDOMDocument> doc;
// XXXbz sXBL/XBL2 issue -- which document?
child->GetOwnerDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDocument> nsDoc(do_QueryInterface(doc));
if(!nsDoc)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIBoxObject> childBoxObject;
nsDoc->GetBoxObjectFor(child, getter_AddRefs(childBoxObject));
if(!childBoxObject)
nsCOMPtr<nsIPresShell> shell = GetPresShell(PR_FALSE);
if (!shell) {
return NS_ERROR_UNEXPECTED;
PRInt32 x, y, width, height;
childBoxObject->GetX(&x);
childBoxObject->GetY(&y);
childBoxObject->GetWidth(&width);
childBoxObject->GetHeight(&height);
nsIScrollableFrame* sf = GetScrollFrame();
if (!sf)
return NS_ERROR_FAILURE;
nsIFrame* scrolledBox = GetScrolledBox(this);
if (!scrolledBox)
return NS_ERROR_FAILURE;
nsRect rect, crect;
// get the twips rectangle from the boxobject (which has pixels)
rect.x = nsPresContext::CSSPixelsToAppUnits(x);
rect.y = nsPresContext::CSSPixelsToAppUnits(y);
rect.width = nsPresContext::CSSPixelsToAppUnits(width);
rect.height = nsPresContext::CSSPixelsToAppUnits(height);
// TODO: make sure the child is inside the box
// get our current info
nsPoint cp = sf->GetScrollPosition();
nsIntRect prect;
GetOffsetRect(prect);
crect = prect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel());
nscoord newx=cp.x, newy=cp.y;
// we only scroll in the direction of the scrollbox orientation
if (scrolledBox->IsHorizontal()) {
if ((rect.x - crect.x) + rect.width > cp.x + crect.width) {
newx = cp.x + (((rect.x - crect.x) + rect.width)-(cp.x + crect.width));
} else if (rect.x - crect.x < cp.x) {
newx = rect.x - crect.x;
}
} else {
if ((rect.y - crect.y) + rect.height > cp.y + crect.height) {
newy = cp.y + (((rect.y - crect.y) + rect.height)-(cp.y + crect.height));
} else if (rect.y - crect.y < cp.y) {
newy = rect.y - crect.y;
}
}
// scroll away
sf->ScrollTo(nsPoint(newx, newy), nsIScrollableFrame::INSTANT);
nsCOMPtr<nsIContent> content = do_QueryInterface(child);
shell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE,
nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY |
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
return NS_OK;
}

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

@ -99,7 +99,7 @@ nsServerSocket::~nsServerSocket()
void
nsServerSocket::OnMsgClose()
{
LOG(("nsServerSocket::OnMsgClose [this=%p]\n", this));
SOCKET_LOG(("nsServerSocket::OnMsgClose [this=%p]\n", this));
if (NS_FAILED(mCondition))
return;
@ -116,7 +116,7 @@ nsServerSocket::OnMsgClose()
void
nsServerSocket::OnMsgAttach()
{
LOG(("nsServerSocket::OnMsgAttach [this=%p]\n", this));
SOCKET_LOG(("nsServerSocket::OnMsgAttach [this=%p]\n", this));
if (NS_FAILED(mCondition))
return;

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

@ -140,7 +140,7 @@ static PRErrorCode RandomizeConnectError(PRErrorCode code)
};
n = n % (sizeof(errors)/sizeof(errors[0]));
code = errors[n].err_code;
LOG(("simulating NSPR error %d [%s]\n", code, errors[n].err_name));
SOCKET_LOG(("simulating NSPR error %d [%s]\n", code, errors[n].err_name));
}
return code;
}
@ -202,7 +202,7 @@ ErrorAccordingToNSPR(PRErrorCode errorCode)
rv = GetXPCOMFromNSSError(errorCode);
break;
}
LOG(("ErrorAccordingToNSPR [in=%d out=%x]\n", errorCode, rv));
SOCKET_LOG(("ErrorAccordingToNSPR [in=%d out=%x]\n", errorCode, rv));
return rv;
}
@ -230,7 +230,7 @@ nsSocketInputStream::~nsSocketInputStream()
void
nsSocketInputStream::OnSocketReady(nsresult condition)
{
LOG(("nsSocketInputStream::OnSocketReady [this=%x cond=%x]\n",
SOCKET_LOG(("nsSocketInputStream::OnSocketReady [this=%x cond=%x]\n",
this, condition));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -284,7 +284,7 @@ nsSocketInputStream::Close()
NS_IMETHODIMP
nsSocketInputStream::Available(PRUint32 *avail)
{
LOG(("nsSocketInputStream::Available [this=%x]\n", this));
SOCKET_LOG(("nsSocketInputStream::Available [this=%x]\n", this));
*avail = 0;
@ -329,7 +329,7 @@ nsSocketInputStream::Available(PRUint32 *avail)
NS_IMETHODIMP
nsSocketInputStream::Read(char *buf, PRUint32 count, PRUint32 *countRead)
{
LOG(("nsSocketInputStream::Read [this=%x count=%u]\n", this, count));
SOCKET_LOG(("nsSocketInputStream::Read [this=%x count=%u]\n", this, count));
*countRead = 0;
@ -345,14 +345,14 @@ nsSocketInputStream::Read(char *buf, PRUint32 count, PRUint32 *countRead)
return NS_BASE_STREAM_WOULD_BLOCK;
}
LOG((" calling PR_Read [count=%u]\n", count));
SOCKET_LOG((" calling PR_Read [count=%u]\n", count));
// cannot hold lock while calling NSPR. (worried about the fact that PSM
// synchronously proxies notifications over to the UI thread, which could
// mistakenly try to re-enter this code.)
PRInt32 n = PR_Read(fd, buf, count);
LOG((" PR_Read returned [n=%d]\n", n));
SOCKET_LOG((" PR_Read returned [n=%d]\n", n));
nsresult rv;
{
@ -403,7 +403,7 @@ nsSocketInputStream::IsNonBlocking(PRBool *nonblocking)
NS_IMETHODIMP
nsSocketInputStream::CloseWithStatus(nsresult reason)
{
LOG(("nsSocketInputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
SOCKET_LOG(("nsSocketInputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
// may be called from any thread
@ -427,7 +427,7 @@ nsSocketInputStream::AsyncWait(nsIInputStreamCallback *callback,
PRUint32 amount,
nsIEventTarget *target)
{
LOG(("nsSocketInputStream::AsyncWait [this=%x]\n", this));
SOCKET_LOG(("nsSocketInputStream::AsyncWait [this=%x]\n", this));
// This variable will be non-null when we want to call the callback
// directly from this function, but outside the lock.
@ -489,7 +489,7 @@ nsSocketOutputStream::~nsSocketOutputStream()
void
nsSocketOutputStream::OnSocketReady(nsresult condition)
{
LOG(("nsSocketOutputStream::OnSocketReady [this=%x cond=%x]\n",
SOCKET_LOG(("nsSocketOutputStream::OnSocketReady [this=%x cond=%x]\n",
this, condition));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -549,7 +549,7 @@ nsSocketOutputStream::Flush()
NS_IMETHODIMP
nsSocketOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *countWritten)
{
LOG(("nsSocketOutputStream::Write [this=%x count=%u]\n", this, count));
SOCKET_LOG(("nsSocketOutputStream::Write [this=%x count=%u]\n", this, count));
*countWritten = 0;
@ -568,14 +568,14 @@ nsSocketOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *countWrit
return NS_BASE_STREAM_WOULD_BLOCK;
}
LOG((" calling PR_Write [count=%u]\n", count));
SOCKET_LOG((" calling PR_Write [count=%u]\n", count));
// cannot hold lock while calling NSPR. (worried about the fact that PSM
// synchronously proxies notifications over to the UI thread, which could
// mistakenly try to re-enter this code.)
PRInt32 n = PR_Write(fd, buf, count);
LOG((" PR_Write returned [n=%d]\n", n));
SOCKET_LOG((" PR_Write returned [n=%d]\n", n));
NS_ASSERTION(n != 0, "unexpected return value");
nsresult rv;
@ -645,7 +645,7 @@ nsSocketOutputStream::IsNonBlocking(PRBool *nonblocking)
NS_IMETHODIMP
nsSocketOutputStream::CloseWithStatus(nsresult reason)
{
LOG(("nsSocketOutputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
SOCKET_LOG(("nsSocketOutputStream::CloseWithStatus [this=%x reason=%x]\n", this, reason));
// may be called from any thread
@ -669,7 +669,7 @@ nsSocketOutputStream::AsyncWait(nsIOutputStreamCallback *callback,
PRUint32 amount,
nsIEventTarget *target)
{
LOG(("nsSocketOutputStream::AsyncWait [this=%x]\n", this));
SOCKET_LOG(("nsSocketOutputStream::AsyncWait [this=%x]\n", this));
{
nsAutoLock lock(mTransport->mLock);
@ -721,7 +721,7 @@ nsSocketTransport::nsSocketTransport()
, mOutput(this)
, mQoSBits(0x00)
{
LOG(("creating nsSocketTransport @%x\n", this));
SOCKET_LOG(("creating nsSocketTransport @%x\n", this));
NS_ADDREF(gSocketTransportService);
@ -731,7 +731,7 @@ nsSocketTransport::nsSocketTransport()
nsSocketTransport::~nsSocketTransport()
{
LOG(("destroying nsSocketTransport @%x\n", this));
SOCKET_LOG(("destroying nsSocketTransport @%x\n", this));
// cleanup socket type info
if (mTypes) {
@ -779,7 +779,7 @@ nsSocketTransport::Init(const char **types, PRUint32 typeCount,
proxyType = nsnull;
}
LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s:%hu]\n",
SOCKET_LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s:%hu]\n",
this, mHost.get(), mPort, mProxyHost.get(), mProxyPort));
// include proxy type as a socket type if proxy type is not "http"
@ -869,7 +869,7 @@ nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const PRNetAddr *addr
opt.value.non_blocking = PR_TRUE;
PR_SetSocketOption(mFD, &opt);
LOG(("nsSocketTransport::InitWithConnectedSocket [this=%p addr=%s:%hu]\n",
SOCKET_LOG(("nsSocketTransport::InitWithConnectedSocket [this=%p addr=%s:%hu]\n",
this, mHost.get(), mPort));
// jump to InitiateSocket to get ourselves attached to the STS poll list.
@ -879,7 +879,7 @@ nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const PRNetAddr *addr
nsresult
nsSocketTransport::PostEvent(PRUint32 type, nsresult status, nsISupports *param)
{
LOG(("nsSocketTransport::PostEvent [this=%p type=%u status=%x param=%p]\n",
SOCKET_LOG(("nsSocketTransport::PostEvent [this=%p type=%u status=%x param=%p]\n",
this, type, status, param));
nsCOMPtr<nsIRunnable> event = new nsSocketEvent(this, type, status, param);
@ -892,7 +892,7 @@ nsSocketTransport::PostEvent(PRUint32 type, nsresult status, nsISupports *param)
void
nsSocketTransport::SendStatus(nsresult status)
{
LOG(("nsSocketTransport::SendStatus [this=%x status=%x]\n", this, status));
SOCKET_LOG(("nsSocketTransport::SendStatus [this=%x status=%x]\n", this, status));
nsCOMPtr<nsITransportEventSink> sink;
PRUint64 progress;
@ -918,7 +918,7 @@ nsSocketTransport::SendStatus(nsresult status)
nsresult
nsSocketTransport::ResolveHost()
{
LOG(("nsSocketTransport::ResolveHost [this=%x]\n", this));
SOCKET_LOG(("nsSocketTransport::ResolveHost [this=%x]\n", this));
nsresult rv;
@ -955,7 +955,7 @@ nsSocketTransport::ResolveHost()
rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nsnull,
getter_AddRefs(mDNSRequest));
if (NS_SUCCEEDED(rv)) {
LOG((" advancing to STATE_RESOLVING\n"));
SOCKET_LOG((" advancing to STATE_RESOLVING\n"));
mState = STATE_RESOLVING;
// only report that we are resolving if we are still resolving...
if (mResolving)
@ -967,7 +967,7 @@ nsSocketTransport::ResolveHost()
nsresult
nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool &usingSSL)
{
LOG(("nsSocketTransport::BuildSocket [this=%x]\n", this));
SOCKET_LOG(("nsSocketTransport::BuildSocket [this=%x]\n", this));
nsresult rv;
@ -995,7 +995,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool
for (i=0; i<mTypeCount; ++i) {
nsCOMPtr<nsISocketProvider> provider;
LOG((" pushing io layer [%u:%s]\n", i, mTypes[i]));
SOCKET_LOG((" pushing io layer [%u:%s]\n", i, mTypes[i]));
rv = spserv->GetSocketProvider(mTypes[i], getter_AddRefs(provider));
if (NS_FAILED(rv))
@ -1043,7 +1043,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool
nsAutoLock lock(mLock);
mSecInfo = secinfo;
callbacks = mCallbacks;
LOG((" [secinfo=%x callbacks=%x]\n", mSecInfo.get(), mCallbacks.get()));
SOCKET_LOG((" [secinfo=%x callbacks=%x]\n", mSecInfo.get(), mCallbacks.get()));
}
// don't call into PSM while holding mLock!!
nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(secinfo));
@ -1063,7 +1063,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool
}
if (NS_FAILED(rv)) {
LOG((" error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv));
SOCKET_LOG((" error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv));
if (fd)
PR_Close(fd);
}
@ -1075,7 +1075,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool
nsresult
nsSocketTransport::InitiateSocket()
{
LOG(("nsSocketTransport::InitiateSocket [this=%x]\n", this));
SOCKET_LOG(("nsSocketTransport::InitiateSocket [this=%x]\n", this));
nsresult rv;
@ -1118,7 +1118,7 @@ nsSocketTransport::InitiateSocket()
rv = BuildSocket(fd, proxyTransparent, usingSSL);
if (NS_FAILED(rv)) {
LOG((" BuildSocket failed [rv=%x]\n", rv));
SOCKET_LOG((" BuildSocket failed [rv=%x]\n", rv));
return rv;
}
@ -1165,16 +1165,16 @@ nsSocketTransport::InitiateSocket()
mFDconnected = PR_FALSE;
}
LOG((" advancing to STATE_CONNECTING\n"));
SOCKET_LOG((" advancing to STATE_CONNECTING\n"));
mState = STATE_CONNECTING;
mPollTimeout = mTimeouts[TIMEOUT_CONNECT];
SendStatus(STATUS_CONNECTING_TO);
#if defined(PR_LOGGING)
if (LOG_ENABLED()) {
if (SOCKET_LOG_ENABLED()) {
char buf[64];
PR_NetAddrToString(&mNetAddr, buf, sizeof(buf));
LOG((" trying address: %s\n", buf));
SOCKET_LOG((" trying address: %s\n", buf));
}
#endif
@ -1215,7 +1215,7 @@ nsSocketTransport::InitiateSocket()
nsCOMPtr<nsISSLSocketControl> secCtrl =
do_QueryInterface(mSecInfo);
if (secCtrl) {
LOG((" calling ProxyStartSSL()\n"));
SOCKET_LOG((" calling ProxyStartSSL()\n"));
secCtrl->ProxyStartSSL();
}
// XXX what if we were forced to poll on the socket for a successful
@ -1243,7 +1243,7 @@ nsSocketTransport::RecoverFromError()
{
NS_ASSERTION(NS_FAILED(mCondition), "there should be something wrong");
LOG(("nsSocketTransport::RecoverFromError [this=%x state=%x cond=%x]\n",
SOCKET_LOG(("nsSocketTransport::RecoverFromError [this=%x state=%x cond=%x]\n",
this, mState, mCondition));
// can only recover from errors in these states
@ -1267,7 +1267,7 @@ nsSocketTransport::RecoverFromError()
if (mState == STATE_CONNECTING && mDNSRecord) {
nsresult rv = mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr);
if (NS_SUCCEEDED(rv)) {
LOG((" trying again with next ip address\n"));
SOCKET_LOG((" trying again with next ip address\n"));
tryAgain = PR_TRUE;
}
}
@ -1311,7 +1311,7 @@ nsSocketTransport::RecoverFromError()
void
nsSocketTransport::OnMsgInputClosed(nsresult reason)
{
LOG(("nsSocketTransport::OnMsgInputClosed [this=%x reason=%x]\n",
SOCKET_LOG(("nsSocketTransport::OnMsgInputClosed [this=%x reason=%x]\n",
this, reason));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -1333,7 +1333,7 @@ nsSocketTransport::OnMsgInputClosed(nsresult reason)
void
nsSocketTransport::OnMsgOutputClosed(nsresult reason)
{
LOG(("nsSocketTransport::OnMsgOutputClosed [this=%x reason=%x]\n",
SOCKET_LOG(("nsSocketTransport::OnMsgOutputClosed [this=%x reason=%x]\n",
this, reason));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -1354,7 +1354,7 @@ nsSocketTransport::OnMsgOutputClosed(nsresult reason)
void
nsSocketTransport::OnSocketConnected()
{
LOG((" advancing to STATE_TRANSFERRING\n"));
SOCKET_LOG((" advancing to STATE_TRANSFERRING\n"));
mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT);
mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
@ -1391,7 +1391,7 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
NS_ASSERTION(mFD == fd, "wrong fd");
if (--mFDref == 0) {
LOG(("nsSocketTransport: calling PR_Close [this=%x]\n", this));
SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%x]\n", this));
PR_Close(mFD);
mFD = nsnull;
}
@ -1403,12 +1403,12 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
void
nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *param)
{
LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n",
SOCKET_LOG(("nsSocketTransport::OnSocketEvent [this=%p type=%u status=%x param=%p]\n",
this, type, status, param));
if (NS_FAILED(mCondition)) {
// block event since we're apparently already dead.
LOG((" blocking event [condition=%x]\n", mCondition));
SOCKET_LOG((" blocking event [condition=%x]\n", mCondition));
//
// notify input/output streams in case either has a pending notify.
//
@ -1419,7 +1419,7 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa
switch (type) {
case MSG_ENSURE_CONNECT:
LOG((" MSG_ENSURE_CONNECT\n"));
SOCKET_LOG((" MSG_ENSURE_CONNECT\n"));
//
// ensure that we have created a socket, attached it, and have a
// connection.
@ -1427,11 +1427,11 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa
if (mState == STATE_CLOSED)
mCondition = ResolveHost();
else
LOG((" ignoring redundant event\n"));
SOCKET_LOG((" ignoring redundant event\n"));
break;
case MSG_DNS_LOOKUP_COMPLETE:
LOG((" MSG_DNS_LOOKUP_COMPLETE\n"));
SOCKET_LOG((" MSG_DNS_LOOKUP_COMPLETE\n"));
mDNSRequest = 0;
if (param) {
mDNSRecord = static_cast<nsIDNSRecord *>(param);
@ -1459,35 +1459,35 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa
break;
case MSG_INPUT_CLOSED:
LOG((" MSG_INPUT_CLOSED\n"));
SOCKET_LOG((" MSG_INPUT_CLOSED\n"));
OnMsgInputClosed(status);
break;
case MSG_INPUT_PENDING:
LOG((" MSG_INPUT_PENDING\n"));
SOCKET_LOG((" MSG_INPUT_PENDING\n"));
OnMsgInputPending();
break;
case MSG_OUTPUT_CLOSED:
LOG((" MSG_OUTPUT_CLOSED\n"));
SOCKET_LOG((" MSG_OUTPUT_CLOSED\n"));
OnMsgOutputClosed(status);
break;
case MSG_OUTPUT_PENDING:
LOG((" MSG_OUTPUT_PENDING\n"));
SOCKET_LOG((" MSG_OUTPUT_PENDING\n"));
OnMsgOutputPending();
break;
case MSG_TIMEOUT_CHANGED:
LOG((" MSG_TIMEOUT_CHANGED\n"));
SOCKET_LOG((" MSG_TIMEOUT_CHANGED\n"));
mPollTimeout = mTimeouts[(mState == STATE_TRANSFERRING)
? TIMEOUT_READ_WRITE : TIMEOUT_CONNECT];
break;
default:
LOG((" unhandled event!\n"));
SOCKET_LOG((" unhandled event!\n"));
}
if (NS_FAILED(mCondition)) {
LOG((" after event [this=%x cond=%x]\n", this, mCondition));
SOCKET_LOG((" after event [this=%x cond=%x]\n", this, mCondition));
if (!mAttached) // need to process this error ourselves...
OnSocketDetached(nsnull);
}
@ -1501,11 +1501,11 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, nsresult status, nsISupports *pa
void
nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags)
{
LOG(("nsSocketTransport::OnSocketReady [this=%x outFlags=%hd]\n",
SOCKET_LOG(("nsSocketTransport::OnSocketReady [this=%x outFlags=%hd]\n",
this, outFlags));
if (outFlags == -1) {
LOG(("socket timeout expired\n"));
SOCKET_LOG(("socket timeout expired\n"));
mCondition = NS_ERROR_NET_TIMEOUT;
return;
}
@ -1557,7 +1557,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags)
mCondition = ErrorAccordingToNSPR(code);
if ((mCondition == NS_ERROR_CONNECTION_REFUSED) && !mProxyHost.IsEmpty())
mCondition = NS_ERROR_PROXY_CONNECTION_REFUSED;
LOG((" connection failed! [reason=%x]\n", mCondition));
SOCKET_LOG((" connection failed! [reason=%x]\n", mCondition));
}
}
}
@ -1574,7 +1574,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags)
void
nsSocketTransport::OnSocketDetached(PRFileDesc *fd)
{
LOG(("nsSocketTransport::OnSocketDetached [this=%x cond=%x]\n",
SOCKET_LOG(("nsSocketTransport::OnSocketDetached [this=%x cond=%x]\n",
this, mCondition));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -1651,7 +1651,7 @@ nsSocketTransport::OpenInputStream(PRUint32 flags,
PRUint32 segcount,
nsIInputStream **result)
{
LOG(("nsSocketTransport::OpenInputStream [this=%x flags=%x]\n",
SOCKET_LOG(("nsSocketTransport::OpenInputStream [this=%x flags=%x]\n",
this, flags));
NS_ENSURE_TRUE(!mInput.IsReferenced(), NS_ERROR_UNEXPECTED);
@ -1699,7 +1699,7 @@ nsSocketTransport::OpenOutputStream(PRUint32 flags,
PRUint32 segcount,
nsIOutputStream **result)
{
LOG(("nsSocketTransport::OpenOutputStream [this=%x flags=%x]\n",
SOCKET_LOG(("nsSocketTransport::OpenOutputStream [this=%x flags=%x]\n",
this, flags));
NS_ENSURE_TRUE(!mOutput.IsReferenced(), NS_ERROR_UNEXPECTED);

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

@ -117,7 +117,7 @@ nsSocketTransportService::GetThreadSafely()
NS_IMETHODIMP
nsSocketTransportService::Dispatch(nsIRunnable *event, PRUint32 flags)
{
LOG(("STS dispatch [%p]\n", event));
SOCKET_LOG(("STS dispatch [%p]\n", event));
nsCOMPtr<nsIThread> thread = GetThreadSafely();
NS_ENSURE_TRUE(thread, NS_ERROR_NOT_INITIALIZED);
@ -144,7 +144,7 @@ nsSocketTransportService::IsOnCurrentThread(PRBool *result)
NS_IMETHODIMP
nsSocketTransportService::NotifyWhenCanAttachSocket(nsIRunnable *event)
{
LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n"));
SOCKET_LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n"));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -159,7 +159,7 @@ nsSocketTransportService::NotifyWhenCanAttachSocket(nsIRunnable *event)
NS_IMETHODIMP
nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler)
{
LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler));
SOCKET_LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler));
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -181,7 +181,7 @@ nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler
nsresult
nsSocketTransportService::DetachSocket(SocketContext *sock)
{
LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler));
SOCKET_LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler));
// inform the handler that this socket is going away
sock->mHandler->OnSocketDetached(sock->mFD);
@ -213,7 +213,7 @@ nsSocketTransportService::DetachSocket(SocketContext *sock)
nsresult
nsSocketTransportService::AddToPollList(SocketContext *sock)
{
LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler));
SOCKET_LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler));
if (mActiveCount == NS_SOCKET_MAX_COUNT) {
NS_ERROR("too many active sockets");
@ -227,19 +227,19 @@ nsSocketTransportService::AddToPollList(SocketContext *sock)
mPollList[mActiveCount].in_flags = sock->mHandler->mPollFlags;
mPollList[mActiveCount].out_flags = 0;
LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
return NS_OK;
}
void
nsSocketTransportService::RemoveFromPollList(SocketContext *sock)
{
LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler));
SOCKET_LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler));
PRUint32 index = sock - mActiveList;
NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
LOG((" index=%u mActiveCount=%u\n", index, mActiveCount));
SOCKET_LOG((" index=%u mActiveCount=%u\n", index, mActiveCount));
if (index != mActiveCount-1) {
mActiveList[index] = mActiveList[mActiveCount-1];
@ -247,13 +247,13 @@ nsSocketTransportService::RemoveFromPollList(SocketContext *sock)
}
mActiveCount--;
LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
}
nsresult
nsSocketTransportService::AddToIdleList(SocketContext *sock)
{
LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler));
SOCKET_LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler));
if (mIdleCount == NS_SOCKET_MAX_COUNT) {
NS_ERROR("too many idle sockets");
@ -263,14 +263,14 @@ nsSocketTransportService::AddToIdleList(SocketContext *sock)
mIdleList[mIdleCount] = *sock;
mIdleCount++;
LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
return NS_OK;
}
void
nsSocketTransportService::RemoveFromIdleList(SocketContext *sock)
{
LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler));
SOCKET_LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler));
PRUint32 index = sock - &mIdleList[0];
NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
@ -279,7 +279,7 @@ nsSocketTransportService::RemoveFromIdleList(SocketContext *sock)
mIdleList[index] = mIdleList[mIdleCount-1];
mIdleCount--;
LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
}
void
@ -320,7 +320,7 @@ nsSocketTransportService::PollTimeout()
if (r < minR)
minR = r;
}
LOG(("poll timeout: %lu\n", minR));
SOCKET_LOG(("poll timeout: %lu\n", minR));
return PR_SecondsToInterval(minR);
}
@ -352,13 +352,13 @@ nsSocketTransportService::Poll(PRBool wait, PRUint32 *interval)
PRIntervalTime ts = PR_IntervalNow();
LOG((" timeout = %i milliseconds\n",
SOCKET_LOG((" timeout = %i milliseconds\n",
PR_IntervalToMilliseconds(pollTimeout)));
PRInt32 rv = PR_Poll(pollList, pollCount, pollTimeout);
PRIntervalTime passedInterval = PR_IntervalNow() - ts;
LOG((" ...returned after %i milliseconds\n",
SOCKET_LOG((" ...returned after %i milliseconds\n",
PR_IntervalToMilliseconds(passedInterval)));
*interval = PR_IntervalToSeconds(passedInterval);
@ -409,7 +409,7 @@ nsSocketTransportService::Init()
//
if (!mThreadEvent) {
NS_WARNING("running socket transport thread without a pollable event");
LOG(("running socket transport thread without a pollable event"));
SOCKET_LOG(("running socket transport thread without a pollable event"));
}
}
@ -440,7 +440,7 @@ nsSocketTransportService::Init()
NS_IMETHODIMP
nsSocketTransportService::Shutdown()
{
LOG(("nsSocketTransportService::Shutdown\n"));
SOCKET_LOG(("nsSocketTransportService::Shutdown\n"));
NS_ENSURE_STATE(NS_IsMainThread());
@ -559,7 +559,7 @@ nsSocketTransportService::AfterProcessNextEvent(nsIThreadInternal* thread,
NS_IMETHODIMP
nsSocketTransportService::Run()
{
LOG(("STS thread init\n"));
SOCKET_LOG(("STS thread init\n"));
gSocketThread = PR_GetCurrentThread();
@ -589,7 +589,7 @@ nsSocketTransportService::Run()
NS_ProcessNextEvent(thread);
}
LOG(("STS shutting down thread\n"));
SOCKET_LOG(("STS shutting down thread\n"));
// detach any sockets
PRInt32 i;
@ -604,14 +604,14 @@ nsSocketTransportService::Run()
gSocketThread = nsnull;
LOG(("STS thread exit\n"));
SOCKET_LOG(("STS thread exit\n"));
return NS_OK;
}
nsresult
nsSocketTransportService::DoPollIteration(PRBool wait)
{
LOG(("STS poll iter [%d]\n", wait));
SOCKET_LOG(("STS poll iter [%d]\n", wait));
PRInt32 i, count;
@ -629,7 +629,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait)
count = mIdleCount;
for (i=mActiveCount-1; i>=0; --i) {
//---
LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
SOCKET_LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
mActiveList[i].mHandler,
mActiveList[i].mHandler->mCondition,
mActiveList[i].mHandler->mPollFlags));
@ -649,7 +649,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait)
}
for (i=count-1; i>=0; --i) {
//---
LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
SOCKET_LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
mIdleList[i].mHandler,
mIdleList[i].mHandler->mCondition,
mIdleList[i].mHandler->mPollFlags));
@ -660,14 +660,14 @@ nsSocketTransportService::DoPollIteration(PRBool wait)
MoveToPollList(&mIdleList[i]);
}
LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount));
SOCKET_LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount));
// Measures seconds spent while blocked on PR_Poll
PRUint32 pollInterval;
PRInt32 n = Poll(wait, &pollInterval);
if (n < 0) {
LOG((" PR_Poll error [%d]\n", PR_GetError()));
SOCKET_LOG((" PR_Poll error [%d]\n", PR_GetError()));
pollError = PR_TRUE;
}
else {
@ -722,7 +722,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait)
if (!mThreadEvent) {
NS_WARNING("running socket transport thread without "
"a pollable event");
LOG(("running socket transport thread without "
SOCKET_LOG(("running socket transport thread without "
"a pollable event"));
}
mPollList[0].fd = mThreadEvent;

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

@ -59,8 +59,8 @@
//
extern PRLogModuleInfo *gSocketTransportLog;
#endif
#define LOG(args) PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args)
#define LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG)
#define SOCKET_LOG(args) PR_LOG(gSocketTransportLog, PR_LOG_DEBUG, args)
#define SOCKET_LOG_ENABLED() PR_LOG_TEST(gSocketTransportLog, PR_LOG_DEBUG)
//-----------------------------------------------------------------------------

15
netwerk/cache/nsCacheService.cpp поставляемый
Просмотреть файл

@ -793,14 +793,6 @@ nsCacheService::DispatchToCacheIOThread(nsIRunnable* event)
PRBool
nsCacheProfilePrefObserver::DiskCacheEnabled()
{
#ifdef MOZ_IPC
// Bad Things (tm) are likely to happen if child and parent both write to
// disk cache.
// - TODO: remove once we turn off caching entirely in child (bug 559714)
if (mozilla::net::IsNeckoChild())
return PR_FALSE;
#endif
if ((mDiskCacheCapacity == 0) || (!mDiskCacheParentDirectory)) return PR_FALSE;
return mDiskCacheEnabled;
}
@ -858,13 +850,6 @@ nsCacheProfilePrefObserver::MemoryCacheEnabled()
PRInt32
nsCacheProfilePrefObserver::MemoryCacheCapacity()
{
#ifdef MOZ_IPC
// For now use small memory cache (1 MB) on child, just for FTP/wyciwyg
// - TODO: remove once we turn off caching entirely in child (bug 559714)
if (mozilla::net::IsNeckoChild())
return 1024;
#endif
PRInt32 capacity = mMemoryCacheCapacity;
if (capacity >= 0) {
CACHE_LOG_DEBUG(("Memory cache capacity forced to %d\n", capacity));

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

@ -143,6 +143,12 @@ HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result)
return mActiveChannel->mTabParent->QueryInterface(aIID, result);
}
if (aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) {
if (!mActiveChannel || !mActiveChannel->mTabParent)
return NS_NOINTERFACE;
return mActiveChannel->mTabParent->QueryInterface(aIID, result);
}
if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
if (!mActiveChannel)
return NS_NOINTERFACE;

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

@ -206,6 +206,8 @@ nsHttpConnectionMgr::StopPruneDeadConnectionsTimer()
{
LOG(("nsHttpConnectionMgr::StopPruneDeadConnectionsTimer\n"));
// Reset mTimeOfNextWakeUp so that we can find a new shortest value.
mTimeOfNextWakeUp = LL_MAXUINT;
if (mTimer) {
mTimer->Cancel();
mTimer = NULL;
@ -412,8 +414,8 @@ nsHttpConnectionMgr::PruneDeadConnectionsCB(nsHashKey *key, void *data, void *cl
// If time to next expire found is shorter than time to next wake-up, we need to
// change the time for next wake-up.
PRUint32 now = NowInSeconds();
if (0 < ent->mIdleConns.Length()) {
PRUint32 now = NowInSeconds();
PRUint64 timeOfNextExpire = now + timeToNextExpire;
// If pruning of dead connections is not already scheduled to happen
// or time found for next connection to expire is is before
@ -556,7 +558,8 @@ nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 cap
LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n",
ci->HashKey().get(), caps));
// use >= just to be safe
// If we have more active connections than the limit, then we're done --
// purging idle connections won't get us below it.
if (mNumActiveConns >= mMaxConns) {
LOG((" num active conns == max conns\n"));
return PR_TRUE;
@ -602,11 +605,6 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
*result = nsnull;
if (AtActiveConnectionLimit(ent, caps)) {
LOG((" at active connection limit!\n"));
return;
}
nsHttpConnection *conn = nsnull;
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
@ -624,15 +622,31 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
LOG((" reusing connection [conn=%x]\n", conn));
ent->mIdleConns.RemoveElementAt(0);
mNumIdleConns--;
// If there are no idle connections left at all, we need to make
// sure that we are not pruning dead connections anymore.
if (0 == mNumIdleConns)
StopPruneDeadConnectionsTimer();
}
}
if (!conn) {
// No reusable idle connection found for this entry. If there are no
// idle connections left at all, we need to make sure that we are not
// pruning dead connections anymore.
if (0 == mNumIdleConns)
StopPruneDeadConnectionsTimer();
// Check if we need to purge an idle connection. Note that we may have
// removed one above; if so, this will be a no-op. We do this before
// checking the active connection limit to catch the case where we do
// have an idle connection, but the purge timer hasn't fired yet.
// XXX this just purges a random idle connection. we should instead
// enumerate the entire hash table to find the eldest idle connection.
if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns)
mCT.Enumerate(PurgeOneIdleConnectionCB, this);
// Need to make a new TCP connection. First, we check if we've hit
// either the maximum connection limit globally or for this particular
// host or proxy. If we have, we're done.
if (AtActiveConnectionLimit(ent, caps)) {
LOG((" at active connection limit!\n"));
return;
}
conn = new nsHttpConnection();
if (!conn)
@ -644,15 +658,6 @@ nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
NS_RELEASE(conn);
return;
}
// We created a new connection that will become active, purge the
// oldest idle connection if we've reached the upper limit.
// This only needs to be done if there is a idle connection.
if (0 < mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 > mMaxConns)
mCT.Enumerate(PurgeOneIdleConnectionCB, this);
// XXX this just purges a random idle connection. we should instead
// enumerate the entire hash table to find the eldest idle connection.
}
*result = conn;
@ -932,6 +937,8 @@ nsHttpConnectionMgr::OnMsgPruneDeadConnections(PRInt32, void *)
{
LOG(("nsHttpConnectionMgr::OnMsgPruneDeadConnections\n"));
// Reset mTimeOfNextWakeUp so that we can find a new shortest value.
mTimeOfNextWakeUp = LL_MAXUINT;
if (mNumIdleConns > 0)
mCT.Enumerate(PruneDeadConnectionsCB, this);
}

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

@ -76,6 +76,7 @@
#include "nsNetUtil.h"
#include "nsIOService.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "nsSocketTransportService2.h"
#include "nsIXULAppInfo.h"
@ -854,7 +855,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
if (NS_SUCCEEDED(rv)) {
mMaxConnections = (PRUint16) NS_CLAMP(val, 1, 0xffff);
mMaxConnections = (PRUint16) NS_CLAMP(val, 1, NS_SOCKET_MAX_COUNT);
if (mConnMgr)
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
mMaxConnections);

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

@ -102,6 +102,7 @@ CPPSRCS = \
nsIdentityChecking.cpp \
nsDataSignatureVerifier.cpp \
nsRandomGenerator.cpp \
NSSErrorsService.cpp \
$(NULL)
ifdef MOZ_XUL

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

@ -0,0 +1,189 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Personal Security Manager.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
* Mitch Stoltz <mstoltz@netscape.com>
* Brian Ryner <bryner@brianryner.com>
* Kai Engert <kaie@netscape.com>
* Vipul Gupta <vipul.gupta@sun.com>
* Douglas Stebila <douglas@stebila.ca>
* Kai Engert <kengert@redhat.com>
* honzab.moz@firemni.cz
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "NSSErrorsService.h"
#include "nsNSSComponent.h"
#include "nsServiceManagerUtils.h"
#include "secerr.h"
#include "sslerr.h"
#define PIPNSS_STRBUNDLE_URL "chrome://pipnss/locale/pipnss.properties"
#define NSSERR_STRBUNDLE_URL "chrome://pipnss/locale/nsserrors.properties"
namespace mozilla {
namespace psm {
NS_IMPL_ISUPPORTS1(NSSErrorsService, nsINSSErrorsService)
nsresult
NSSErrorsService::Init()
{
nsresult rv;
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
if (NS_FAILED(rv) || !bundleService)
return NS_ERROR_FAILURE;
bundleService->CreateBundle(PIPNSS_STRBUNDLE_URL,
getter_AddRefs(mPIPNSSBundle));
if (!mPIPNSSBundle)
rv = NS_ERROR_FAILURE;
bundleService->CreateBundle(NSSERR_STRBUNDLE_URL,
getter_AddRefs(mNSSErrorsBundle));
if (!mNSSErrorsBundle)
rv = NS_ERROR_FAILURE;
return rv;
}
#define EXPECTED_SEC_ERROR_BASE (-0x2000)
#define EXPECTED_SSL_ERROR_BASE (-0x3000)
#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE
#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code"
/*
* Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000
* Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts.
* The current code also assumes that NSS library error codes are negative.
*/
#endif
NS_IMETHODIMP
NSSErrorsService::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval)
{
if (!_retval)
return NS_ERROR_FAILURE;
*_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode);
return NS_OK;
}
NS_IMETHODIMP
NSSErrorsService::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode)
{
if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
return NS_ERROR_FAILURE;
if (!aXPCOMErrorCode)
return NS_ERROR_INVALID_ARG;
// The error codes within each module may be a 16 bit value.
// For simplicity let's use the positive value of the NSS code.
*aXPCOMErrorCode =
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY,
-1 * aNSPRCode);
return NS_OK;
}
NS_IMETHODIMP
NSSErrorsService::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass)
{
NS_ENSURE_ARG(aErrorClass);
if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
|| NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
return NS_ERROR_FAILURE;
PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
return NS_ERROR_FAILURE;
switch (aNSPRCode)
{
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_CA_CERT_INVALID:
case SEC_ERROR_UNTRUSTED_ISSUER:
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
case SEC_ERROR_UNTRUSTED_CERT:
case SEC_ERROR_INADEQUATE_KEY_USAGE:
case SSL_ERROR_BAD_CERT_DOMAIN:
case SEC_ERROR_EXPIRED_CERTIFICATE:
*aErrorClass = ERROR_CLASS_BAD_CERT;
break;
default:
*aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
break;
}
return NS_OK;
}
NS_IMETHODIMP
NSSErrorsService::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage)
{
if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
|| NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
return NS_ERROR_FAILURE;
PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle;
const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode);
if (!id_str) {
id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode);
theBundle = mNSSErrorsBundle;
}
if (!id_str || !theBundle)
return NS_ERROR_FAILURE;
nsAutoString msg;
nsresult rv =
theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(),
getter_Copies(msg));
if (NS_SUCCEEDED(rv)) {
aErrorMessage = msg;
}
return rv;
}
} // psm
} // mozilla

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

@ -0,0 +1,68 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Personal Security Manager.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Hubbie Shaw
* Doug Turner <dougt@netscape.com>
* Brian Ryner <bryner@brianryner.com>
* Kai Engert <kaie@netscape.com>
* Kai Engert <kengert@redhat.com>
* honzab.moz@firemni.cz
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsINSSErrorsService.h"
#include "nsIStringBundle.h"
#include "nsCOMPtr.h"
namespace mozilla {
namespace psm {
class NSSErrorsService : public nsINSSErrorsService
{
NS_DECL_ISUPPORTS
NS_DECL_NSINSSERRORSSERVICE
public:
nsresult Init();
private:
nsCOMPtr<nsIStringBundle> mPIPNSSBundle;
nsCOMPtr<nsIStringBundle> mNSSErrorsBundle;
};
} // psm
} // mozilla
#define NS_NSSERRORSSERVICE_CID \
{ 0x9ef18451, 0xa157, 0x4d17, { 0x81, 0x32, 0x47, 0xaf, 0xef, 0x21, 0x36, 0x89 } }

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

@ -1953,14 +1953,13 @@ nsNSSComponent::Init()
}
/* nsISupports Implementation for the class */
NS_IMPL_THREADSAFE_ISUPPORTS7(nsNSSComponent,
NS_IMPL_THREADSAFE_ISUPPORTS6(nsNSSComponent,
nsISignatureVerifier,
nsIEntropyCollector,
nsINSSComponent,
nsIObserver,
nsISupportsWeakReference,
nsITimerCallback,
nsINSSErrorsService)
nsITimerCallback)
/* Callback functions for decoder. For now, use empty/default functions. */
@ -2453,112 +2452,6 @@ nsNSSComponent::RememberCert(CERTCertificate *cert)
return NS_OK;
}
#define EXPECTED_SEC_ERROR_BASE (-0x2000)
#define EXPECTED_SSL_ERROR_BASE (-0x3000)
#if SEC_ERROR_BASE != EXPECTED_SEC_ERROR_BASE || SSL_ERROR_BASE != EXPECTED_SSL_ERROR_BASE
#error "Unexpected change of error code numbers in lib NSS, please adjust the mapping code"
/*
* Please ensure the NSS error codes are mapped into the positive range 0x1000 to 0xf000
* Search for NS_ERROR_MODULE_SECURITY to ensure there are no conflicts.
* The current code also assumes that NSS library error codes are negative.
*/
#endif
NS_IMETHODIMP
nsNSSComponent::IsNSSErrorCode(PRInt32 aNSPRCode, PRBool *_retval)
{
if (!_retval)
return NS_ERROR_FAILURE;
*_retval = IS_SEC_ERROR(aNSPRCode) || IS_SSL_ERROR(aNSPRCode);
return NS_OK;
}
NS_IMETHODIMP
nsNSSComponent::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCode)
{
if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
return NS_ERROR_FAILURE;
if (!aXPCOMErrorCode)
return NS_ERROR_INVALID_ARG;
// The error codes within each module may be a 16 bit value.
// For simplicity let's use the positive value of the NSS code.
*aXPCOMErrorCode =
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY,
-1 * aNSPRCode);
return NS_OK;
}
NS_IMETHODIMP
nsNSSComponent::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass)
{
NS_ENSURE_ARG(aErrorClass);
if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
|| NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
return NS_ERROR_FAILURE;
PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
return NS_ERROR_FAILURE;
switch (aNSPRCode)
{
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_CA_CERT_INVALID:
case SEC_ERROR_UNTRUSTED_ISSUER:
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
case SEC_ERROR_UNTRUSTED_CERT:
case SEC_ERROR_INADEQUATE_KEY_USAGE:
case SSL_ERROR_BAD_CERT_DOMAIN:
case SEC_ERROR_EXPIRED_CERTIFICATE:
*aErrorClass = ERROR_CLASS_BAD_CERT;
break;
default:
*aErrorClass = ERROR_CLASS_SSL_PROTOCOL;
break;
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage)
{
if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY
|| NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR)
return NS_ERROR_FAILURE;
PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode);
if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIStringBundle> theBundle = mPIPNSSBundle;
const char *id_str = nsNSSErrors::getOverrideErrorStringName(aNSPRCode);
if (!id_str) {
id_str = nsNSSErrors::getDefaultErrorStringName(aNSPRCode);
theBundle = mNSSErrorsBundle;
}
if (!id_str || !theBundle)
return NS_ERROR_FAILURE;
nsAutoString msg;
nsresult rv =
theBundle->GetStringFromName(NS_ConvertASCIItoUTF16(id_str).get(),
getter_Copies(msg));
if (NS_SUCCEEDED(rv)) {
aErrorMessage = msg;
}
return rv;
}
void
nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
{

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

@ -239,8 +239,7 @@ class nsNSSComponent : public nsISignatureVerifier,
public nsINSSComponent,
public nsIObserver,
public nsSupportsWeakReference,
public nsITimerCallback,
public nsINSSErrorsService
public nsITimerCallback
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
@ -253,7 +252,6 @@ public:
NS_DECL_NSIENTROPYCOLLECTOR
NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
NS_DECL_NSINSSERRORSSERVICE
NS_METHOD Init();

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

@ -379,6 +379,11 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown()
// with a socket close, and the socket transport might detach the callbacks
// instance prior to our error reporting.
nsISecureBrowserUI* secureUI = nsnull;
#ifdef MOZ_IPC
CallGetInterface(proxiedCallbacks.get(), &secureUI);
#endif
nsCOMPtr<nsIDocShell> docshell;
nsCOMPtr<nsIDocShellTreeItem> item(do_GetInterface(proxiedCallbacks));
@ -397,7 +402,7 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown()
NS_ASSERTION(docshell, "rootItem do_QI is null");
}
if (docshell)
if (docshell && !secureUI)
{
nsCOMPtr<nsIDocShell> proxiedDocShell;
NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
@ -405,28 +410,28 @@ nsNSSSocketInfo::EnsureDocShellDependentStuffKnown()
docshell.get(),
NS_PROXY_SYNC,
getter_AddRefs(proxiedDocShell));
nsISecureBrowserUI* secureUI = nsnull;
if (proxiedDocShell)
proxiedDocShell->GetSecurityUI(&secureUI);
if (secureUI)
{
nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
mExternalErrorReporting = PR_TRUE;
}
// If this socket is associated to a docshell, let's try to remember
// the currently used cert. If this socket gets a notification from NSS
// having the same raw socket, we can keep the PSM wrapper object
// and all the data it has cached (like verification results).
nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
if (statprov) {
nsCOMPtr<nsISupports> isup_stat;
statprov->GetSSLStatus(getter_AddRefs(isup_stat));
if (isup_stat) {
nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
if (sslstat) {
sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
}
if (secureUI)
{
nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
NS_ProxyRelease(mainThread, secureUI, PR_FALSE);
mExternalErrorReporting = PR_TRUE;
// If this socket is associated to a docshell, let's try to remember
// the currently used cert. If this socket gets a notification from NSS
// having the same raw socket, we can keep the PSM wrapper object
// and all the data it has cached (like verification results).
nsCOMPtr<nsISSLStatusProvider> statprov = do_QueryInterface(secureUI);
if (statprov) {
nsCOMPtr<nsISupports> isup_stat;
statprov->GetSSLStatus(getter_AddRefs(isup_stat));
if (isup_stat) {
nsCOMPtr<nsISSLStatus> sslstat = do_QueryInterface(isup_stat);
if (sslstat) {
sslstat->GetServerCert(getter_AddRefs(mPreviousCert));
}
}
}

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

@ -78,6 +78,7 @@
#include "nsRecentBadCerts.h"
#include "nsSSLStatus.h"
#include "nsNSSIOLayer.h"
#include "NSSErrorsService.h"
#ifdef MOZ_IPC
#include "nsXULAppAPI.h"
@ -261,6 +262,9 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsRecentBadCertsService, Init
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsNSSSocketInfo)
typedef mozilla::psm::NSSErrorsService NSSErrorsService;
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init)
NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID);
NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID);
NS_DEFINE_NAMED_CID(NS_STARTTLSSOCKETPROVIDER_CID);
@ -296,6 +300,7 @@ NS_DEFINE_NAMED_CID(NS_RANDOMGENERATOR_CID);
NS_DEFINE_NAMED_CID(NS_RECENTBADCERTS_CID);
NS_DEFINE_NAMED_CID(NS_SSLSTATUS_CID);
NS_DEFINE_NAMED_CID(NS_NSSSOCKETINFO_CID);
NS_DEFINE_NAMED_CID(NS_NSSERRORSSERVICE_CID);
static const mozilla::Module::CIDEntry kNSSCIDs[] = {
@ -334,12 +339,13 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = {
{ &kNS_RECENTBADCERTS_CID, false, NULL, nsRecentBadCertsServiceConstructor },
{ &kNS_SSLSTATUS_CID, false, NULL, nsSSLStatusConstructor },
{ &kNS_NSSSOCKETINFO_CID, false, NULL, nsNSSSocketInfoConstructor },
{ &kNS_NSSERRORSSERVICE_CID, false, NULL, NSSErrorsServiceConstructor },
{ NULL }
};
static const mozilla::Module::ContractIDEntry kNSSContracts[] = {
{ PSM_COMPONENT_CONTRACTID, &kNS_NSSCOMPONENT_CID },
{ NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSCOMPONENT_CID },
{ NS_NSS_ERRORS_SERVICE_CONTRACTID, &kNS_NSSERRORSSERVICE_CID },
{ NS_SSLSOCKETPROVIDER_CONTRACTID, &kNS_SSLSOCKETPROVIDER_CID },
{ NS_STARTTLSSOCKETPROVIDER_CONTRACTID, &kNS_STARTTLSSOCKETPROVIDER_CID },
{ NS_SDR_CONTRACTID, &kNS_SDR_CID },

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

@ -71,12 +71,6 @@ WeaveCrypto.prototype = {
}
},
// This is its own method so that it can be overridden.
// (Components.Exception isn't thread-safe for instance)
makeException : function makeException(message, result) {
return Components.Exception(message, result);
},
init : function() {
try {
// Preferences. Add observer so we get notified of changes.
@ -108,34 +102,21 @@ WeaveCrypto.prototype = {
Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports);
// Open the NSS library.
let nssfile = Services.dirsvc.get("GreD", Ci.nsILocalFile);
let os = Services.appinfo.OS;
switch (os) {
case "WINNT":
case "WINMO":
case "WINCE":
nssfile.append("nss3.dll");
break;
case "Darwin":
nssfile.append("libnss3.dylib");
break;
case "Linux":
case "SunOS":
case "WebOS": // Palm Pre
nssfile.append("libnss3.so");
break;
case "Android":
// Android uses a $GREDIR/lib/ subdir.
nssfile.append("lib");
nssfile.append("libnss3.so");
break;
default:
throw this.makeException("unsupported platform: " + os, Cr.NS_ERROR_UNEXPECTED);
}
this.log("Using NSS library " + nssfile.path);
let path = ctypes.libraryName("nss3");
// XXX really want to be able to pass specific dlopen flags here.
let nsslib = ctypes.open(nssfile.path);
var nsslib;
try {
this.log("Trying NSS library without path");
nsslib = ctypes.open(path);
} catch(e) {
// In case opening the library without a full path fails,
// try again with a full path.
let file = Services.dirsvc.get("GreD", Ci.nsILocalFile);
file.append(path);
this.log("Trying again with path " + file.path);
nsslib = ctypes.open(file.path);
}
this.log("Initializing NSS types and function declarations...");
@ -530,31 +511,31 @@ WeaveCrypto.prototype = {
let mechanism = this.nss.PK11_AlgtagToMechanism(this.algorithm);
mechanism = this.nss.PK11_GetPadMechanism(mechanism);
if (mechanism == this.nss.CKM_INVALID_MECHANISM)
throw this.makeException("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE);
throw Components.Exception("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE);
let ctx, symKey, slot, ivParam;
try {
ivParam = this.nss.PK11_ParamFromIV(mechanism, ivItem.address());
if (ivParam.isNull())
throw this.makeException("can't convert IV to param", Cr.NS_ERROR_FAILURE);
throw Components.Exception("can't convert IV to param", Cr.NS_ERROR_FAILURE);
slot = this.nss.PK11_GetInternalKeySlot();
if (slot.isNull())
throw this.makeException("can't get internal key slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("can't get internal key slot", Cr.NS_ERROR_FAILURE);
symKey = this.nss.PK11_ImportSymKey(slot, mechanism, this.nss.PK11_OriginUnwrap, operation, keyItem.address(), null);
if (symKey.isNull())
throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE);
ctx = this.nss.PK11_CreateContextBySymKey(mechanism, operation, symKey, ivParam);
if (ctx.isNull())
throw this.makeException("couldn't create context for symkey", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't create context for symkey", Cr.NS_ERROR_FAILURE);
let maxOutputSize = output.length;
let tmpOutputSize = new ctypes.int(); // Note 1: NSS uses a signed int here...
if (this.nss.PK11_CipherOp(ctx, output, tmpOutputSize.address(), maxOutputSize, input, input.length))
throw this.makeException("cipher operation failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("cipher operation failed", Cr.NS_ERROR_FAILURE);
let actualOutputSize = tmpOutputSize.value;
let finalOutput = output.addressOfElement(actualOutputSize);
@ -565,7 +546,7 @@ WeaveCrypto.prototype = {
// cipher operation. You'd think it would be called PK11_CipherOpFinal...
let tmpOutputSize2 = new ctypes.unsigned_int(); // Note 2: ...but an unsigned here!
if (this.nss.PK11_DigestFinal(ctx, finalOutput, tmpOutputSize2.address(), maxOutputSize))
throw this.makeException("cipher finalize failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("cipher finalize failed", Cr.NS_ERROR_FAILURE);
actualOutputSize += tmpOutputSize2.value;
let newOutput = ctypes.cast(output, ctypes.unsigned_char.array(actualOutputSize));
@ -604,7 +585,7 @@ WeaveCrypto.prototype = {
slot = this.nss.PK11_GetInternalSlot();
if (slot.isNull())
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
// Generate the keypair.
privKey = this.nss.PK11_GenerateKeyPairWithFlags(slot,
@ -613,18 +594,18 @@ WeaveCrypto.prototype = {
pubKey.address(),
attrFlags, null);
if (privKey.isNull())
throw this.makeException("keypair generation failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("keypair generation failed", Cr.NS_ERROR_FAILURE);
let s = this.nss.PK11_SetPrivateKeyNickname(privKey, "Weave User PrivKey");
if (s)
throw this.makeException("key nickname failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("key nickname failed", Cr.NS_ERROR_FAILURE);
let wrappedPrivateKey = this._wrapPrivateKey(privKey, passphrase, salt, iv);
out_wrappedPrivateKey.value = wrappedPrivateKey; // outparam
let derKey = this.nss.SECKEY_EncodeDERSubjectPublicKeyInfo(pubKey);
if (derKey.isNull())
throw this.makeException("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
let encodedPublicKey = this.encodeBase64(derKey.contents.data, derKey.contents.len);
out_encodedPublicKey.value = encodedPublicKey; // outparam
@ -664,27 +645,27 @@ WeaveCrypto.prototype = {
break;
default:
throw this.makeException("unknown algorithm", Cr.NS_ERROR_FAILURE);
throw Components.Exception("unknown algorithm", Cr.NS_ERROR_FAILURE);
}
let slot, randKey, keydata;
try {
slot = this.nss.PK11_GetInternalSlot();
if (slot.isNull())
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
randKey = this.nss.PK11_KeyGen(slot, keygenMech, null, keySize, null);
if (randKey.isNull())
throw this.makeException("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE);
// Slightly odd API, this call just prepares the key value for
// extraction, we get the actual bits from the call to PK11_GetKeyData().
if (this.nss.PK11_ExtractKeyValue(randKey))
throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
keydata = this.nss.PK11_GetKeyData(randKey);
if (keydata.isNull())
throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
return this.encodeBase64(keydata.contents.data, keydata.contents.len);
} catch (e) {
@ -715,7 +696,7 @@ WeaveCrypto.prototype = {
// Temporary buffer to hold the generated data.
let scratch = new ctypes.ArrayType(ctypes.unsigned_char, byteCount)();
if (this.nss.PK11_GenerateRandom(scratch, byteCount))
throw this.makeException("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE);
return this.encodeBase64(scratch.address(), scratch.length);
},
@ -738,7 +719,7 @@ WeaveCrypto.prototype = {
try {
slot = this.nss.PK11_GetInternalSlot();
if (slot.isNull())
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
// ImportSymKey wants a mechanism, from which it derives the key type.
let keyMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
@ -747,7 +728,7 @@ WeaveCrypto.prototype = {
// really matter because we're just going to wrap it up and not use it.
symKey = this.nss.PK11_ImportSymKey(slot, keyMech, this.nss.PK11_OriginUnwrap, this.nss.CKA_ENCRYPT, symKeyData.address(), null);
if (symKey.isNull())
throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE);
// Step 3. Put the public key bits into a P11 key object.
@ -755,11 +736,11 @@ WeaveCrypto.prototype = {
// pubKey = SECKEY_ImportDERPublicKey(&pubKeyData, CKK_RSA);
pubKeyInfo = this.nss.SECKEY_DecodeDERSubjectPublicKeyInfo(pubKeyData.address());
if (pubKeyInfo.isNull())
throw this.makeException("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
pubKey = this.nss.SECKEY_ExtractPublicKey(pubKeyInfo);
if (pubKey.isNull())
throw this.makeException("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE);
// Step 4. Wrap the symmetric key with the public key.
@ -767,7 +748,7 @@ WeaveCrypto.prototype = {
let s = this.nss.PK11_PubWrapSymKey(wrapMech, pubKey, symKey, wrappedKey.address());
if (s)
throw this.makeException("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE);
// Step 5. Base64 encode the wrapped key, cleanup, and return to caller.
return this.encodeBase64(wrappedKey.data, wrappedKey.len);
@ -807,16 +788,16 @@ WeaveCrypto.prototype = {
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
throw this.makeException("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
throw Components.Exception("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
if (ivParam.isNull())
throw this.makeException("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
// Step 3. Unwrap the private key with the key from the passphrase.
slot = this.nss.PK11_GetInternalSlot();
if (slot.isNull())
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
// Normally, one wants to associate a private key with a public key.
// P11_UnwrapPrivKey() passes its keyID arg to PK11_MakeIDFromPubKey(),
@ -837,7 +818,7 @@ WeaveCrypto.prototype = {
privKeyUsage.addressOfElement(0), privKeyUsageLength,
null); // wincx
if (privKey.isNull())
throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
// Step 4. Unwrap the symmetric key with the user's private key.
@ -846,15 +827,15 @@ WeaveCrypto.prototype = {
symKey = this.nss.PK11_PubUnwrapSymKey(privKey, wrappedSymKey.address(), wrapMech,
this.nss.CKA_DECRYPT, 0);
if (symKey.isNull())
throw this.makeException("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE);
// Step 5. Base64 encode the unwrapped key, cleanup, and return to caller.
if (this.nss.PK11_ExtractKeyValue(symKey))
throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
symKeyData = this.nss.PK11_GetKeyData(symKey);
if (symKeyData.isNull())
throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
return this.encodeBase64(symKeyData.contents.data, symKeyData.contents.len);
} catch (e) {
@ -894,16 +875,16 @@ WeaveCrypto.prototype = {
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
if (ivParam.isNull())
throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
// Step 3. Unwrap the private key with the key from the passphrase.
slot = this.nss.PK11_GetInternalSlot();
if (slot.isNull())
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
let keyID = ivItem.address();
@ -917,7 +898,7 @@ WeaveCrypto.prototype = {
privKeyUsage.addressOfElement(0), privKeyUsageLength,
null); // wincx
if (privKey.isNull())
throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
// Step 4. Rewrap the private key with the new passphrase.
return this._wrapPrivateKey(privKey, newPassphrase, salt, iv);
@ -956,16 +937,16 @@ WeaveCrypto.prototype = {
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
if (ivParam.isNull())
throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
// Step 3. Unwrap the private key with the key from the passphrase.
slot = this.nss.PK11_GetInternalSlot();
if (slot.isNull())
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
let keyID = ivItem.address();
@ -1059,15 +1040,15 @@ WeaveCrypto.prototype = {
algid = this.nss.PK11_CreatePBEV2AlgorithmID(pbeAlg, cipherAlg, prfAlg,
keyLength, iterations, saltItem.address());
if (algid.isNull())
throw this.makeException("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE);
slot = this.nss.PK11_GetInternalSlot();
if (slot.isNull())
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
symKey = this.nss.PK11_PBEKeyGen(slot, algid, passItem.address(), false, null);
if (symKey.isNull())
throw this.makeException("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE);
} catch (e) {
this.log("_deriveKeyFromPassphrase: failed: " + e);
throw e;
@ -1095,11 +1076,11 @@ WeaveCrypto.prototype = {
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
throw this.makeException("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE);
throw Components.Exception("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE);
let ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
if (ivParam.isNull())
throw this.makeException("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
// Use a buffer to hold the wrapped key. NSS says about 1200 bytes for
// a 2048-bit RSA key, so a 4096 byte buffer should be plenty.
@ -1111,7 +1092,7 @@ WeaveCrypto.prototype = {
wrapMech, ivParam,
wrappedKey.address(), null);
if (s)
throw this.makeException("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE);
throw Components.Exception("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE);
return this.encodeBase64(wrappedKey.data, wrappedKey.len);
} catch (e) {

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

@ -1,150 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Firefox Sync.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Philipp von Weitershausen <philipp@weitershausen>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const EXPORTED_SYMBOLS = ["ThreadedCrypto"];
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://services-sync/ext/Sync.js");
Cu.import("resource://services-crypto/WeaveCrypto.js");
/*
* Execute a function in a thread.
*/
function Runner(func, thisObj, returnval, error) {
this.func = func;
this.thisObj = thisObj;
this.returnval = returnval;
this.error = error;
}
Runner.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]),
run: function run() {
let ex = this.error;
if (ex) {
this.func.throw(ex);
} else {
this.func.call(this.thisObj, this.returnval);
}
}
};
/*
* Execute a function in a thread and notify a callback on another thread
* afterward.
*/
function CallbackRunner(func, thisObj, args, callback, cbThread) {
this.func = func;
this.thisObj = thisObj;
this.args = args;
this.callback = callback;
this.cbThread = cbThread;
}
CallbackRunner.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]),
run: function run() {
let returnval, error;
try {
returnval = this.func.apply(this.thisObj, this.args);
} catch(ex) {
error = ex;
}
this.cbThread.dispatch(new Runner(this.callback, this.thisObj,
returnval, error),
Ci.nsIThread.DISPATCH_NORMAL);
}
};
/*
* Implementation of IWeaveCrypto that defers method calls to another thread
* but keeps the synchronous API. (Don't ask...)
*/
function ThreadedCrypto() {
this.backgroundThread = Services.tm.newThread(0);
this.crypto = new WeaveCrypto();
// Components.Exception isn't thread-safe.
this.crypto.makeException = function makeException(message, result) {
return result;
};
// Make sure to kill the thread before XPCOM shuts down.
Services.obs.addObserver(this, "profile-before-change", true);
}
ThreadedCrypto.deferToThread = function deferToThread(methodname) {
return function threadMethod() {
// Dispatch method call to background thread.
let args = Array.slice(arguments);
return Sync(function(callback) {
let runner = new CallbackRunner(this.crypto[methodname], this.crypto,
args, callback, Services.tm.mainThread);
this.backgroundThread.dispatch(runner, Ci.nsIThread.DISPATCH_NORMAL);
}, this)();
};
};
ThreadedCrypto.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.IWeaveCrypto,
Ci.nsISupportsWeakReference]),
observe: function observe() {
this.backgroundThread.shutdown();
},
get algorithm() this.crypto.algorithm,
set algorithm(value) this.crypto.algorithm = value,
get keypairBits() this.crypto.keypairBits,
set keypairBits(value) this.crypto.keypairBits = value,
encrypt: ThreadedCrypto.deferToThread("encrypt"),
decrypt: ThreadedCrypto.deferToThread("decrypt"),
generateKeypair: ThreadedCrypto.deferToThread("generateKeypair"),
generateRandomKey: ThreadedCrypto.deferToThread("generateRandomKey"),
generateRandomIV: ThreadedCrypto.deferToThread("generateRandomIV"),
generateRandomBytes: ThreadedCrypto.deferToThread("generateRandomBytes"),
wrapSymmetricKey: ThreadedCrypto.deferToThread("wrapSymmetricKey"),
unwrapSymmetricKey: ThreadedCrypto.deferToThread("unwrapSymmetricKey"),
rewrapPrivateKey: ThreadedCrypto.deferToThread("rewrapPrivateKey"),
verifyPassphrase: ThreadedCrypto.deferToThread("verifyPassphrase")
};

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

@ -11,8 +11,6 @@ try {
}
catch(ex) {
do_get_profile();
// Make sure to provide the right OS so crypto loads the right binaries
let OS = "XPCShell";
if ("@mozilla.org/windows-registry-key;1" in Cc)

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

@ -1,7 +1,7 @@
let cryptoSvc;
try {
Components.utils.import("resource://services-crypto/threaded.js");
cryptoSvc = new ThreadedCrypto();
Components.utils.import("resource://services-crypto/WeaveCrypto.js");
cryptoSvc = new WeaveCrypto();
} catch (ex) {
// Fallback to binary WeaveCrypto
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]

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

@ -1,7 +1,7 @@
let cryptoSvc;
try {
Components.utils.import("resource://services-crypto/threaded.js");
cryptoSvc = new ThreadedCrypto();
Components.utils.import("resource://services-crypto/WeaveCrypto.js");
cryptoSvc = new WeaveCrypto();
} catch (ex) {
// Fallback to binary WeaveCrypto
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]

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

@ -1,7 +1,7 @@
let cryptoSvc;
try {
Components.utils.import("resource://services-crypto/threaded.js");
cryptoSvc = new ThreadedCrypto();
Components.utils.import("resource://services-crypto/WeaveCrypto.js");
cryptoSvc = new WeaveCrypto();
} catch (ex) {
// Fallback to binary WeaveCrypto
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]

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

@ -1,7 +1,7 @@
let cryptoSvc;
try {
Components.utils.import("resource://services-crypto/threaded.js");
cryptoSvc = new ThreadedCrypto();
Components.utils.import("resource://services-crypto/WeaveCrypto.js");
cryptoSvc = new WeaveCrypto();
} catch (ex) {
// Fallback to binary WeaveCrypto
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]

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

@ -1,7 +1,7 @@
let cryptoSvc;
try {
Components.utils.import("resource://services-crypto/threaded.js");
cryptoSvc = new ThreadedCrypto();
Components.utils.import("resource://services-crypto/WeaveCrypto.js");
cryptoSvc = new WeaveCrypto();
} catch (ex) {
// Fallback to binary WeaveCrypto
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]

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

@ -1039,8 +1039,8 @@ Svc.__defineGetter__("Crypto", function() {
let cryptoSvc;
try {
let ns = {};
Cu.import("resource://services-crypto/threaded.js", ns);
cryptoSvc = new ns.ThreadedCrypto();
Cu.import("resource://services-crypto/WeaveCrypto.js", ns);
cryptoSvc = new ns.WeaveCrypto();
} catch (ex) {
// Fallback to binary WeaveCrypto
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"].

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

@ -3,6 +3,9 @@ Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/log4moz.js");
function run_test() {
if (DISABLE_TESTS_BUG_604565)
return;
let logger = Log4Moz.repository.rootLogger;
Log4Moz.repository.rootLogger.addAppender(new Log4Moz.DumpAppender());

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

@ -3907,159 +3907,152 @@ function JSPropertyProvider(aScope, aInputValue)
*/
function JSTermHelper(aJSTerm)
{
return {
/**
* Returns the result of document.getElementById(aId).
*
* @param string aId
* A string that is passed to window.document.getElementById.
* @returns nsIDOMNode or null
*/
$: function JSTH_$(aId)
{
try {
return aJSTerm._window.document.getElementById(aId);
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
},
/**
* Returns the result of document.querySelectorAll(aSelector).
*
* @param string aSelector
* A string that is passed to window.document.querySelectorAll.
* @returns array of nsIDOMNode
*/
$$: function JSTH_$$(aSelector)
{
try {
return aJSTerm._window.document.querySelectorAll(aSelector);
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
},
/**
* Runs a xPath query and returns all matched nodes.
*
* @param string aXPath
* xPath search query to execute.
* @param [optional] nsIDOMNode aContext
* Context to run the xPath query on. Uses window.document if not set.
* @returns array of nsIDOMNode
*/
$x: function JSTH_$x(aXPath, aContext)
{
let nodes = [];
let doc = aJSTerm._window.wrappedJSObject.document;
let aContext = aContext || doc;
try {
let results = doc.evaluate(aXPath, aContext, null,
Ci.nsIDOMXPathResult.ANY_TYPE, null);
let node;
while (node = results.iterateNext()) {
nodes.push(node);
}
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
return nodes;
},
/**
* Clears the output of the JSTerm.
*/
clear: function JSTH_clear()
{
aJSTerm.clearOutput();
},
/**
* Returns the result of Object.keys(aObject).
*
* @param object aObject
* Object to return the property names from.
* @returns array of string
*/
keys: function JSTH_keys(aObject)
{
try {
return Object.keys(XPCNativeWrapper.unwrap(aObject));
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
},
/**
* Returns the values of all properties on aObject.
*
* @param object aObject
* Object to display the values from.
* @returns array of string
*/
values: function JSTH_values(aObject)
{
let arrValues = [];
let obj = XPCNativeWrapper.unwrap(aObject);
try {
for (let prop in obj) {
arrValues.push(obj[prop]);
}
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
return arrValues;
},
/**
* Inspects the passed aObject. This is done by opening the PropertyPanel.
*
* @param object aObject
* Object to inspect.
* @returns void
*/
inspect: function JSTH_inspect(aObject)
{
let obj = XPCNativeWrapper.unwrap(aObject);
aJSTerm.openPropertyPanel(null, obj);
},
/**
* Prints aObject to the output.
*
* @param object aObject
* Object to print to the output.
* @returns void
*/
pprint: function JSTH_pprint(aObject)
{
if (aObject === null || aObject === undefined || aObject === true || aObject === false) {
aJSTerm.console.error(HUDService.getStr("helperFuncUnsupportedTypeError"));
return;
}
let output = [];
if (typeof aObject != "string") {
aObject = XPCNativeWrapper.unwrap(aObject);
}
let pairs = namesAndValuesOf(aObject);
pairs.forEach(function(pair) {
output.push(" " + pair.display);
});
aJSTerm.writeOutput(output.join("\n"));
/**
* Returns the result of document.getElementById(aId).
*
* @param string aId
* A string that is passed to window.document.getElementById.
* @returns nsIDOMNode or null
*/
aJSTerm.sandbox.$ = function JSTH_$(aId)
{
try {
return aJSTerm._window.document.getElementById(aId);
}
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
};
/**
* Returns the result of document.querySelectorAll(aSelector).
*
* @param string aSelector
* A string that is passed to window.document.querySelectorAll.
* @returns array of nsIDOMNode
*/
aJSTerm.sandbox.$$ = function JSTH_$$(aSelector)
{
try {
return aJSTerm._window.document.querySelectorAll(aSelector);
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
};
/**
* Runs a xPath query and returns all matched nodes.
*
* @param string aXPath
* xPath search query to execute.
* @param [optional] nsIDOMNode aContext
* Context to run the xPath query on. Uses window.document if not set.
* @returns array of nsIDOMNode
*/
aJSTerm.sandbox.$x = function JSTH_$x(aXPath, aContext)
{
let nodes = [];
let doc = aJSTerm._window.document;
let aContext = aContext || doc;
try {
let results = doc.evaluate(aXPath, aContext, null,
Ci.nsIDOMXPathResult.ANY_TYPE, null);
let node;
while (node = results.iterateNext()) {
nodes.push(node);
}
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
return nodes;
};
/**
* Clears the output of the JSTerm.
*/
aJSTerm.sandbox.clear = function JSTH_clear()
{
aJSTerm.clearOutput();
};
/**
* Returns the result of Object.keys(aObject).
*
* @param object aObject
* Object to return the property names from.
* @returns array of string
*/
aJSTerm.sandbox.keys = function JSTH_keys(aObject)
{
try {
return Object.keys(aObject);
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
};
/**
* Returns the values of all properties on aObject.
*
* @param object aObject
* Object to display the values from.
* @returns array of string
*/
aJSTerm.sandbox.values = function JSTH_values(aObject)
{
let arrValues = [];
try {
for (let prop in aObject) {
arrValues.push(aObject[prop]);
}
}
catch (ex) {
aJSTerm.console.error(ex.message);
}
return arrValues;
};
/**
* Inspects the passed aObject. This is done by opening the PropertyPanel.
*
* @param object aObject
* Object to inspect.
* @returns void
*/
aJSTerm.sandbox.inspect = function JSTH_inspect(aObject)
{
aJSTerm.openPropertyPanel(null, aObject);
};
/**
* Prints aObject to the output.
*
* @param object aObject
* Object to print to the output.
* @returns void
*/
aJSTerm.sandbox.pprint = function JSTH_pprint(aObject)
{
if (aObject === null || aObject === undefined || aObject === true || aObject === false) {
aJSTerm.console.error(HUDService.getStr("helperFuncUnsupportedTypeError"));
return;
}
let output = [];
let pairs = namesAndValuesOf(aObject);
pairs.forEach(function(pair) {
output.push(" " + pair.display);
});
aJSTerm.writeOutput(output.join("\n"));
};
}
/**
@ -4146,11 +4139,10 @@ JSTerm.prototype = {
createSandbox: function JST_setupSandbox()
{
// create a JS Sandbox out of this.context
this.sandbox = new Cu.Sandbox(this._window);
this.sandbox.window = this._window;
this.sandbox = new Cu.Sandbox(this._window,
{ sandboxPrototype: this._window, wantXrays: false });
this.sandbox.console = this.console;
this.sandbox.__helperFunctions__ = JSTermHelper(this);
this.sandbox.__proto__ = this._window.wrappedJSObject;
JSTermHelper(this);
},
get _window()
@ -4168,8 +4160,7 @@ JSTerm.prototype = {
*/
evalInSandbox: function JST_evalInSandbox(aString)
{
let execStr = "with(__helperFunctions__) { with(window) {" + aString + "} }";
return Cu.evalInSandbox(execStr, this.sandbox, "default", "HUD Console", 1);
return Cu.evalInSandbox(aString, this.sandbox, "1.8", "HUD Console", 1);
},

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

@ -98,6 +98,7 @@ _BROWSER_TEST_FILES = \
browser_webconsole_bug_594497_history_arrow_keys.js \
browser_webconsole_bug_588342_document_focus.js \
browser_webconsole_bug_595934_message_categories.js \
browser_webconsole_bug_601352_scroll.js \
head.js \
$(NULL)

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

@ -0,0 +1,62 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Contributor(s):
* Mihai Șucan <mihai.sucan@gmail.com>
*
* ***** END LICENSE BLOCK ***** */
function tabLoad(aEvent) {
browser.removeEventListener(aEvent.type, arguments.callee, true);
openConsole();
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudWeakReferences[hudId].get();
let longMessage = "";
for (let i = 0; i < 20; i++) {
longMessage += "LongNonwrappingMessage";
}
for (let i = 0; i < 100; i++) {
HUD.console.log("test message " + i);
}
HUD.console.log(longMessage);
for (let i = 0; i < 100; i++) {
HUD.console.log("test message " + i);
}
HUD.jsterm.execute("1+1");
executeSoon(function() {
isnot(HUD.outputNode.scrollTop, 0, "scroll location is not at the top");
let node = HUD.outputNode.querySelector(".hud-group > *:last-child");
let rectNode = node.getBoundingClientRect();
let rectOutput = HUD.outputNode.getBoundingClientRect();
// Visible scroll viewport.
let height = HUD.outputNode.scrollHeight - HUD.outputNode.scrollTop;
// Top position of the last message node, relative to the outputNode.
let top = rectNode.top - rectOutput.top;
// Bottom position of the last message node, relative to the outputNode.
let bottom = rectNode.bottom - rectOutput.top;
ok(top >= 0 && bottom <= height, "last message is visible");
finishTest();
});
}
function test() {
addTab("data:text/html,Web Console test for bug 601352");
browser.addEventListener("load", tabLoad, true);
}

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

@ -98,5 +98,21 @@ function testJSTerm()
let label = jsterm.outputNode.querySelector(".jsterm-output-line");
is(label.textContent.trim(), "a: 1\n b: 2", "pprint() worked");
// check instanceof correctness, bug 599940
jsterm.clearOutput();
jsterm.execute("[] instanceof Array");
checkResult("true", "[] instanceof Array == true", 1);
jsterm.clearOutput();
jsterm.execute("({}) instanceof Object");
checkResult("true", "({}) instanceof Object == true", 1);
// check for occurrences of Object XRayWrapper, bug 604430
jsterm.clearOutput();
jsterm.execute("document");
let label = jsterm.outputNode.querySelector(".jsterm-output-line");
is(label.textContent.trim().search(/\[object XrayWrapper/), -1,
"check for non-existence of [object XrayWrapper ");
finishTest();
}

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

@ -124,6 +124,33 @@ ok(true, "whee, done!");
SimpleTest.finish();
}
function addNotificationCallback(cb)
{
storageObserver.notificationCallbacks.push(cb);
}
var storageObserver = {
notificationCallbacks: [],
QueryInterface : function (iid) {
const interfaces = [Ci.nsIObserver,
Ci.nsISupports, Ci.nsISupportsWeakReference];
if (!interfaces.some( function(v) { return iid.equals(v) } ))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
observe : function (subject, topic, data) {
if (this.notificationCallbacks.length)
this.notificationCallbacks.splice(0, 1)[0]();
}
};
var observerService = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(storageObserver, "passwordmgr-storage-changed", false);
/*
* handleDialog
*
@ -417,12 +444,6 @@ function handleLoad() {
is(username, "mochiuser1", "Checking for echoed username");
is(password, "mochipass1-new", "Checking for echoed password");
// Check for the popup notification, and change the password.
popup = getPopup(popupNotifications, "password-change");
ok(popup, "got popup notification");
clickPopupButton(popup, kChangeButton);
popup.remove();
// Housekeeping: change it back
function resetIt() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
@ -430,7 +451,13 @@ function handleLoad() {
"mochiuser1", "mochipass1-new", "", "");
pwmgr.modifyLogin(tmpLogin, login3A);
}
setTimeout(resetIt, 0);
addNotificationCallback(resetIt);
// Check for the popup notification, and change the password.
popup = getPopup(popupNotifications, "password-change");
ok(popup, "got popup notification");
clickPopupButton(popup, kChangeButton);
popup.remove();
// Same as last test, but for a realm we haven't already authenticated
// to (but have an existing saved login for, so that we'll trigger
@ -445,30 +472,30 @@ function handleLoad() {
is(username, "mochiuser3", "Checking for echoed username");
is(password, "mochipass3-new", "Checking for echoed password");
// Housekeeping: change it back to the original login4. Actually,
// just delete it and we'll re-add it as the next test.
function clearIt() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
tmpLogin.init("http://mochi.test:8888", null, "mochitest3",
"mochiuser3", "mochipass3-new", "", "");
pwmgr.removeLogin(tmpLogin);
// Trigger a new prompt, so we can test adding a new login.
startCallbackTimer();
iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3";
}
addNotificationCallback(clearIt);
// Check for the popup notification, and change the password.
popup = getPopup(popupNotifications, "password-change");
ok(popup, "got popup notification");
clickPopupButton(popup, kChangeButton);
popup.remove();
// Housekeeping: change it back to the original login4. Actually,
// just delete it and we'll re-add it as the next test.
function clearIt() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
tmpLogin.init("http://mochi.test:8888", null, "mochitest3",
"mochiuser3", "mochipass3-new", "", "");
pwmgr.removeLogin(tmpLogin);
}
setTimeout(clearIt, 0);
// Clear cached auth from this subtest, and avoid leaking due to bug 459620.
var authMgr = Cc['@mozilla.org/network/http-auth-manager;1'].
getService(Ci.nsIHttpAuthManager);
authMgr.clearAll();
// Trigger a new prompt, so we can test adding a new login.
startCallbackTimer();
iframe.src = "authenticate.sjs?user=mochiuser3&pass=mochipass3-old&realm=mochitest3";
break;
case 1005:
@ -477,17 +504,17 @@ function handleLoad() {
is(username, "mochiuser3", "Checking for echoed username");
is(password, "mochipass3-old", "Checking for echoed password");
function finishIt() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
finishTest();
}
addNotificationCallback(finishIt);
// Check for the popup notification, and change the password.
popup = getPopup(popupNotifications, "password-save");
ok(popup, "got popup notification");
clickPopupButton(popup, kRememberButton);
popup.remove();
function finishIt() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
finishTest();
}
setTimeout(finishIt, 0);
break;
default:

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

@ -1181,12 +1181,27 @@ History::RegisterVisitedCallback(nsIURI* aURI,
// Links wanting to know about this URI. Therefore, we should query the
// database now.
nsresult rv = VisitedQuery::Start(aURI);
// In IPC builds, we are passed a NULL Link from
// ContentParent::RecvStartVisitedQuery. Since we won't be adding a NULL
// entry to our list of observers, and the code after this point assumes
// that aLink is non-NULL, we will need to return now.
if (NS_FAILED(rv) || !aLink) {
// Remove our array from the hashtable so we don't keep it around.
mObservers.RemoveEntry(aURI);
return rv;
}
}
#ifdef MOZ_IPC
// In IPC builds, we are passed a NULL Link from
// ContentParent::RecvStartVisitedQuery. All of our code after this point
// assumes aLink is non-NULL, so we have to return now.
else if (!aLink) {
NS_ASSERTION(XRE_GetProcessType() == GeckoProcessType_Default,
"We should only ever get a null Link in the default process!");
return NS_OK;
}
#endif
// Sanity check that Links are not registered more than once for a given URI.
// This will not catch a case where it is registered for two different URIs.

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

@ -550,6 +550,34 @@ test_visituri_transition_embed()
run_next_test();
}
////////////////////////////////////////////////////////////////////////////////
//// IPC-only Tests
#ifdef MOZ_IPC
void
test_two_null_links_same_uri()
{
// Tests that we do not crash when we have had two NULL Links passed to
// RegisterVisitedCallback and then the visit occurs (bug 607469). This only
// happens in IPC builds.
nsCOMPtr<nsIURI> testURI(new_test_uri());
nsCOMPtr<IHistory> history(do_get_IHistory());
nsresult rv = history->RegisterVisitedCallback(testURI, NULL);
do_check_success(rv);
rv = history->RegisterVisitedCallback(testURI, NULL);
do_check_success(rv);
rv = history->VisitURI(testURI, NULL, mozilla::IHistory::TOP_LEVEL);
do_check_success(rv);
nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver();
finisher->WaitForNotification();
run_next_test();
}
#endif // MOZ_IPC
////////////////////////////////////////////////////////////////////////////////
//// Test Harness
@ -571,6 +599,11 @@ Test gTests[] = {
TEST(test_visituri_creates_visit),
TEST(test_visituri_transition_typed),
TEST(test_visituri_transition_embed),
// The rest of these tests are tests that are only run in IPC builds.
#ifdef MOZ_IPC
TEST(test_two_null_links_same_uri),
#endif // MOZ_IPC
};
const char* file = __FILE__;

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

@ -45,116 +45,56 @@ const Cc = Components.classes;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/CommonDialog.jsm");
let gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
.QueryInterface(Ci.nsIWritablePropertyBag);
let propBag, args, Dialog;
let promptType, numButtons, iconClass, soundID, hasInputField = true;
function earlyInit() {
// This is called before onload fires, so we can't be certain that any elements
// in the document have their bindings ready, so don't call any methods/properties
// here on xul elements that come from xbl bindings.
promptType = gArgs.getProperty("promptType");
switch (promptType) {
case "alert":
case "alertCheck":
hasInputField = false;
numButtons = 1;
iconClass = "alert-icon";
soundID = Ci.nsISound.EVENT_ALERT_DIALOG_OPEN;
break;
case "confirmCheck":
case "confirm":
hasInputField = false;
numButtons = 2;
iconClass = "question-icon";
soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "confirmEx":
numButtons = 0;
if (gArgs.hasKey("button0Label"))
numButtons++;
if (gArgs.hasKey("button1Label"))
numButtons++;
if (gArgs.hasKey("button2Label"))
numButtons++;
if (gArgs.hasKey("button3Label"))
numButtons++;
if (numButtons == 0)
throw "A dialog with no buttons? Can not haz.";
hasInputField = false;
iconClass = "question-icon";
soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "prompt":
numButtons = 2;
iconClass = "question-icon";
soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
initTextbox("login", gArgs.getProperty("value"));
// Clear the label, since this isn't really a username prompt.
document.getElementById("loginLabel").setAttribute("value", "");
break;
case "promptUserAndPass":
numButtons = 2;
iconClass = "authentication-icon question-icon";
soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
initTextbox("login", gArgs.getProperty("user"));
initTextbox("password1", gArgs.getProperty("pass"));
break;
case "promptPassword":
numButtons = 2;
iconClass = "authentication-icon question-icon";
soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
initTextbox("password1", gArgs.getProperty("pass"));
// Clear the label, since the message presumably indicates its purpose.
document.getElementById("password1Label").setAttribute("value", "");
break;
default:
Cu.reportError("commonDialog opened for unknown type: " + promptType);
window.close();
function commonDialogOnLoad() {
propBag = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
.QueryInterface(Ci.nsIWritablePropertyBag);
// Convert to a JS object
args = {};
let propEnum = propBag.enumerator;
while (propEnum.hasMoreElements()) {
let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
args[prop.name] = prop.value;
}
let dialog = document.documentElement;
let ui = {
loginContainer : document.getElementById("loginContainer"),
loginTextbox : document.getElementById("loginTextbox"),
loginLabel : document.getElementById("loginLabel"),
password1Container : document.getElementById("password1Container"),
password1Textbox : document.getElementById("password1Textbox"),
password1Label : document.getElementById("password1Label"),
infoBody : document.getElementById("info.body"),
infoTitle : document.getElementById("info.title"),
infoIcon : document.getElementById("info.icon"),
checkbox : document.getElementById("checkbox"),
checkboxContainer : document.getElementById("checkboxContainer"),
button3 : dialog.getButton("extra2"),
button2 : dialog.getButton("extra1"),
button1 : dialog.getButton("cancel"),
button0 : dialog.getButton("accept"),
focusTarget : window,
};
// limit the dialog to the screen width
document.getElementById("filler").maxWidth = screen.availWidth;
Services.obs.addObserver(softkbObserver, "softkb-change", false);
Dialog = new CommonDialog(args, ui);
Dialog.onLoad(dialog);
window.getAttention();
}
function initTextbox(aName, aValue) {
document.getElementById(aName + "Container").hidden = false;
document.getElementById(aName + "Textbox").setAttribute("value", aValue);
}
function setLabelForNode(aNode, aLabel, aIsLabelFlag) {
// This is for labels which may contain embedded access keys.
// If we end in (&X) where X represents the access key, optionally preceded
// by spaces and/or followed by the ':' character, store the access key and
// remove the access key placeholder + leading spaces from the label.
// Otherwise a character preceded by one but not two &s is the access key.
// Store it and remove the &.
// Note that if you change the following code, see the comment of
// nsTextBoxFrame::UpdateAccessTitle.
var accessKey = null;
if (/ *\(\&([^&])\)(:)?$/.test(aLabel)) {
aLabel = RegExp.leftContext + RegExp.$2;
accessKey = RegExp.$1;
} else if (/^(.*[^&])?\&(([^&]).*$)/.test(aLabel)) {
aLabel = RegExp.$1 + RegExp.$2;
accessKey = RegExp.$3;
}
// && is the magic sequence to embed an & in your label.
aLabel = aLabel.replace(/\&\&/g, "&");
if (aIsLabelFlag) { // Set text for <label> element
aNode.setAttribute("value", aLabel);
} else { // Set text for other xul elements
aNode.label = aLabel;
}
// XXXjag bug 325251
// Need to set this after aNode.setAttribute("value", aLabel);
if (accessKey)
aNode.accessKey = accessKey;
function commonDialogOnUnload() {
Services.obs.removeObserver(softkbObserver, "softkb-change");
// Convert args back into property bag
for (let propName in args)
propBag.setProperty(propName, args[propName]);
}
function softkbObserver(subject, topic, data) {
@ -167,201 +107,3 @@ function softkbObserver(subject, topic, data) {
window.moveTo(left, top);
}
}
function commonDialogOnLoad() {
// limit the dialog to the screen width
document.getElementById("filler").maxWidth = screen.availWidth;
// set the document title
let title = gArgs.getProperty("title");
#ifdef XP_MACOSX
document.getElementById("info.title").appendChild(document.createTextNode(title));
#else
document.title = title;
#endif
Services.obs.addObserver(softkbObserver, "softkb-change", false);
// Set button visibility
let dialog = document.documentElement;
switch (numButtons) {
case 1:
dialog.getButton("cancel").hidden = true;
break;
case 4:
dialog.getButton("extra2").hidden = false;
case 3:
dialog.getButton("extra1").hidden = false;
}
// Set button labels
switch (numButtons) {
case 4:
setLabelForNode(document.documentElement.getButton("extra2"), gArgs.getProperty("button3Label"));
// fall through
case 3:
setLabelForNode(document.documentElement.getButton("extra1"), gArgs.getProperty("button2Label"));
// fall through
default:
case 2:
if (gArgs.hasKey("button1Label"))
setLabelForNode(document.documentElement.getButton("cancel"), gArgs.getProperty("button1Label"));
// fall through
case 1:
if (gArgs.hasKey("button0Label"))
setLabelForNode(document.documentElement.getButton("accept"), gArgs.getProperty("button0Label"));
break;
}
// display the main text
// Bug 317334 - crop string length as a workaround.
let croppedMessage = gArgs.getProperty("text").substr(0, 10000);
document.getElementById("info.body").appendChild(document.createTextNode(croppedMessage));
if (gArgs.hasKey("checkLabel")) {
let label = gArgs.getProperty("checkLabel")
// Only show the checkbox if label has a value.
if (label) {
document.getElementById("checkboxContainer").hidden = false;
let checkboxElement = document.getElementById("checkbox");
setLabelForNode(checkboxElement, label);
checkboxElement.checked = gArgs.getProperty("checked");
}
}
// set the icon
document.getElementById("info.icon").className += " " + iconClass;
// set default result to cancelled
gArgs.setProperty("ok", false);
gArgs.setProperty("buttonNumClicked", 1);
// If there are no input fields on the dialog, select the default button.
// Otherwise, select the appropriate input field.
if (!hasInputField) {
let dlgButtons = ['accept', 'cancel', 'extra1', 'extra2'];
// Set the default button and focus it on non-OS X systems
let b = 0;
if (gArgs.hasKey("defaultButtonNum"))
b = gArgs.getProperty("defaultButtonNum");
let dButton = dlgButtons[b];
// XXX shouldn't we set the default even when a textbox is focused?
document.documentElement.defaultButton = dButton;
#ifndef XP_MACOSX
document.documentElement.getButton(dButton).focus();
#endif
} else {
if (promptType == "promptPassword")
document.getElementById("password1Textbox").select();
else
document.getElementById("loginTextbox").select();
}
if (gArgs.hasKey("enableDelay") && gArgs.getProperty("enableDelay")) {
let delayInterval = Services.prefs.getIntPref("security.dialog_enable_delay");
document.documentElement.getButton("accept").disabled = true;
document.documentElement.getButton("extra1").disabled = true;
document.documentElement.getButton("extra2").disabled = true;
setTimeout(commonDialogReenableButtons, delayInterval);
addEventListener("blur", commonDialogBlur, false);
addEventListener("focus", commonDialogFocus, false);
}
window.getAttention();
// play sound
try {
if (soundID) {
Cc["@mozilla.org/sound;1"].
createInstance(Ci.nsISound).
playEventSound(soundID);
}
} catch (e) { }
Services.obs.notifyObservers(window, "common-dialog-loaded", null);
}
function commonDialogOnUnload() {
Services.obs.removeObserver(softkbObserver, "softkb-change");
}
var gDelayExpired = false;
var gBlurred = false;
function commonDialogBlur(aEvent) {
if (aEvent.target != document)
return;
gBlurred = true;
document.documentElement.getButton("accept").disabled = true;
document.documentElement.getButton("extra1").disabled = true;
document.documentElement.getButton("extra2").disabled = true;
}
function commonDialogFocus(aEvent) {
if (aEvent.target != document)
return;
gBlurred = false;
// When refocusing the window, don't enable the buttons unless the countdown
// delay has expired.
if (gDelayExpired) {
let script;
script = "document.documentElement.getButton('accept').disabled = false; ";
script += "document.documentElement.getButton('extra1').disabled = false; ";
script += "document.documentElement.getButton('extra2').disabled = false;";
setTimeout(script, 250);
}
}
function commonDialogReenableButtons() {
// Don't automatically enable the buttons if we're not in the foreground
if (!gBlurred) {
document.documentElement.getButton("accept").disabled = false;
document.documentElement.getButton("extra1").disabled = false;
document.documentElement.getButton("extra2").disabled = false;
}
gDelayExpired = true;
}
function onCheckboxClick(aCheckboxElement) {
gArgs.setProperty("checked", aCheckboxElement.checked);
}
function commonDialogOnAccept() {
gArgs.setProperty("ok", true);
gArgs.setProperty("buttonNumClicked", 0);
let username = document.getElementById("loginTextbox").value;
let password = document.getElementById("password1Textbox").value;
// Return textfield values
switch (promptType) {
case "prompt":
gArgs.setProperty("value", username);
break;
case "promptUserAndPass":
gArgs.setProperty("user", username);
gArgs.setProperty("pass", password);
break;
case "promptPassword":
gArgs.setProperty("pass", password);
break;
}
}
function commonDialogOnExtra1() {
// .setProperty("ok", true)?
gArgs.setProperty("buttonNumClicked", 2);
window.close();
}
function commonDialogOnExtra2() {
// .setProperty("ok", true)?
gArgs.setProperty("buttonNumClicked", 3);
window.close();
}

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

@ -1,4 +1,4 @@
<?xml version="1.0"?>
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://global/content/commonDialog.css" type="text/css"?>
@ -7,15 +7,16 @@
<!DOCTYPE dialog SYSTEM "chrome://global/locale/commonDialog.dtd">
<dialog id="commonDialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
aria-describedby="info.body"
onload="commonDialogOnLoad();"
onunload="commonDialogOnUnload();"
ondialogaccept="return commonDialogOnAccept();"
ondialogextra1="return commonDialogOnExtra1();"
ondialogextra2="return commonDialogOnExtra2();"
ondialogaccept="Dialog.onButton0(); return true;"
ondialogcancel="Dialog.onButton1(); return true;"
ondialogextra1="Dialog.onButton2(); window.close();"
ondialogextra2="Dialog.onButton3(); window.close();"
buttonpack="center">
<script type="application/javascript" src="chrome://global/content/commonDialog.js"/>
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
@ -55,10 +56,12 @@
<image id="info.icon" class="spaced"/>
</hbox>
<vbox id="infoContainer">
#ifdef XP_MACOSX
<!-- Dialog title is inside dialog for OS X -->
<description id="info.title"/>
<!-- Only shown on OS X, since it has no dialog title -->
<description id="info.title"
#ifndef XP_MACOSX
style="display: none"
#endif
/>
<spacer style="height: 1em"/>
<description id="info.body" context="contentAreaContextMenu" noinitialfocus="true"/>
</vbox>
@ -73,16 +76,9 @@
</row>
<row id="checkboxContainer" hidden="true">
<spacer/>
<checkbox id="checkbox" oncommand="onCheckboxClick(this);"/>
<checkbox id="checkbox" oncommand="Dialog.onCheckbox()"/>
</row>
</rows>
</grid>
<!-- This method is called inline because it may unset hidden="true" on the
above boxes, causing their frames to be build and bindings to load.
So, by calling this inline, we guarantee the textboxes and checkboxes
above will have their bindings before initButtons is called, and the
dialog will be intrinsically sized correctly. -->
<script type="application/javascript">earlyInit();</script>
</dialog>

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

@ -41,12 +41,12 @@ const Cr = Components.results;
const Cc = Components.classes;
const Cu = Components.utils;
let gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
.QueryInterface(Ci.nsIWritablePropertyBag);
let listBox;
let gArgs, listBox;
function dialogOnLoad() {
gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
.QueryInterface(Ci.nsIWritablePropertyBag);
let promptType = gArgs.getProperty("promptType");
if (promptType != "select") {
Cu.reportError("selectDialog opened for unknown type: " + promptType);

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

@ -1,4 +1,4 @@
<?xml version="1.0"?>
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -37,10 +37,10 @@
***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://global/locale/commonDialog.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="dialogOnLoad()"
ondialogaccept="return dialogOK();">

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

@ -0,0 +1,350 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is CommonDialog.jsm code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Justin Dolske <dolske@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var EXPORTED_SYMBOLS = ["CommonDialog"];
const Ci = Components.interfaces;
const Cr = Components.results;
const Cc = Components.classes;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
function CommonDialog(args, ui) {
this.args = args;
this.ui = ui;
}
CommonDialog.prototype = {
args : null,
ui : null,
hasInputField : true,
numButtons : undefined,
iconClass : undefined,
soundID : undefined,
focusTimer : null,
onLoad : function(xulDialog) {
switch (this.args.promptType) {
case "alert":
case "alertCheck":
this.hasInputField = false;
this.numButtons = 1;
this.iconClass = ["alert-icon"];
this.soundID = Ci.nsISound.EVENT_ALERT_DIALOG_OPEN;
break;
case "confirmCheck":
case "confirm":
this.hasInputField = false;
this.numButtons = 2;
this.iconClass = ["question-icon"];
this.soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "confirmEx":
var numButtons = 0;
if (this.args.button0Label)
numButtons++;
if (this.args.button1Label)
numButtons++;
if (this.args.button2Label)
numButtons++;
if (this.args.button3Label)
numButtons++;
if (numButtons == 0)
throw "A dialog with no buttons? Can not haz.";
this.numButtons = numButtons;
this.hasInputField = false;
this.iconClass = ["question-icon"];
this.soundID = Ci.nsISound.EVENT_CONFIRM_DIALOG_OPEN;
break;
case "prompt":
this.numButtons = 2;
this.iconClass = ["question-icon"];
this.soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
this.initTextbox("login", this.args.value);
// Clear the label, since this isn't really a username prompt.
this.ui.loginLabel.setAttribute("value", "");
break;
case "promptUserAndPass":
this.numButtons = 2;
this.iconClass = ["authentication-icon", "question-icon"];
this.soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
this.initTextbox("login", this.args.user);
this.initTextbox("password1", this.args.pass);
break;
case "promptPassword":
this.numButtons = 2;
this.iconClass = ["authentication-icon", "question-icon"];
this.soundID = Ci.nsISound.EVENT_PROMPT_DIALOG_OPEN;
this.initTextbox("password1", this.args.pass);
// Clear the label, since the message presumably indicates its purpose.
this.ui.password1Label.setAttribute("value", "");
break;
default:
Cu.reportError("commonDialog opened for unknown type: " + this.args.promptType);
throw "unknown dialog type";
}
// set the document title
let title = this.args.title;
// OS X doesn't have a title on modal dialogs, this is hidden on other platforms.
let infoTitle = this.ui.infoTitle;
infoTitle.appendChild(infoTitle.ownerDocument.createTextNode(title));
if (xulDialog)
xulDialog.ownerDocument.title = title;
// Set button labels and visibility
//
// This assumes that button0 defaults to a visible "ok" button, and
// button1 defaults to a visible "cancel" button. The other 2 buttons
// have no default labels (and are hidden).
switch (this.numButtons) {
case 4:
this.setLabelForNode(this.ui.button3, this.args.button3Label);
this.ui.button3.hidden = false;
// fall through
case 3:
this.setLabelForNode(this.ui.button2, this.args.button2Label);
this.ui.button2.hidden = false;
// fall through
case 2:
// Defaults to a visible "cancel" button
if (this.args.button1Label)
this.setLabelForNode(this.ui.button1, this.args.button1Label);
break;
case 1:
this.ui.button1.hidden = true;
break;
}
// Defaults to a visible "ok" button
if (this.args.button0Label)
this.setLabelForNode(this.ui.button0, this.args.button0Label);
// display the main text
// Bug 317334 - crop string length as a workaround.
let croppedMessage = this.args.text.substr(0, 10000);
let infoBody = this.ui.infoBody;
infoBody.appendChild(infoBody.ownerDocument.createTextNode(croppedMessage));
let label = this.args.checkLabel;
if (label) {
// Only show the checkbox if label has a value.
this.ui.checkboxContainer.hidden = false;
this.setLabelForNode(this.ui.checkbox, label);
this.ui.checkbox.checked = this.args.checked;
}
// set the icon
let icon = this.ui.infoIcon;
this.iconClass.forEach(function(el,idx,arr) icon.classList.add(el));
// set default result to cancelled
this.args.ok = false;
this.args.buttonNumClicked = 1;
// If there are no input fields on the dialog, select the default button.
// Otherwise, select the appropriate input field.
// XXX shouldn't we set an unfocused default even when a textbox is focused?
if (!this.hasInputField) {
// Set the default button (and focus it on non-OS X systems)
let b = 0;
if (this.args.defaultButtonNum)
b = this.args.defaultButtonNum;
let button = this.ui["button" + b];
if (xulDialog) {
xulDialog.defaultButton = ['accept', 'cancel', 'extra1', 'extra2'][b];
let isOSX = ("nsILocalFileMac" in Components.interfaces);
if (!isOSX)
button.focus();
}
// TODO:
// else
// (tabmodal prompts need to set a default button for Enter to act upon)
} else {
if (this.args.promptType == "promptPassword")
this.ui.password1Textbox.select();
else
this.ui.loginTextbox.select();
}
if (this.args.enableDelay) {
this.setButtonsEnabledState(false);
// Use a longer, pref-controlled delay when the dialog is first opened.
let delayTime = Services.prefs.getIntPref("security.dialog_enable_delay");
this.startOnFocusDelay(delayTime);
let self = this;
this.ui.focusTarget.addEventListener("blur", function(e) { self.onBlur(e); }, false);
this.ui.focusTarget.addEventListener("focus", function(e) { self.onFocus(e); }, false);
}
// play sound
try {
if (this.soundID) {
Cc["@mozilla.org/sound;1"].
createInstance(Ci.nsISound).
playEventSound(soundID);
}
} catch (e) { }
if (xulDialog)
Services.obs.notifyObservers(xulDialog.ownerDocument.defaultView, "common-dialog-loaded", null);
// TODO:
// else
// (notify using what as the subject?)
},
setLabelForNode: function(aNode, aLabel) {
// This is for labels which may contain embedded access keys.
// If we end in (&X) where X represents the access key, optionally preceded
// by spaces and/or followed by the ':' character, store the access key and
// remove the access key placeholder + leading spaces from the label.
// Otherwise a character preceded by one but not two &s is the access key.
// Store it and remove the &.
// Note that if you change the following code, see the comment of
// nsTextBoxFrame::UpdateAccessTitle.
var accessKey = null;
if (/ *\(\&([^&])\)(:)?$/.test(aLabel)) {
aLabel = RegExp.leftContext + RegExp.$2;
accessKey = RegExp.$1;
} else if (/^(.*[^&])?\&(([^&]).*$)/.test(aLabel)) {
aLabel = RegExp.$1 + RegExp.$2;
accessKey = RegExp.$3;
}
// && is the magic sequence to embed an & in your label.
aLabel = aLabel.replace(/\&\&/g, "&");
aNode.label = aLabel;
// XXXjag bug 325251
// Need to set this after aNode.setAttribute("value", aLabel);
if (accessKey)
aNode.accessKey = accessKey;
},
initTextbox : function (aName, aValue) {
this.ui[aName + "Container"].hidden = false;
this.ui[aName + "Textbox"].setAttribute("value", aValue);
},
setButtonsEnabledState : function(enabled) {
this.ui.button0.disabled = !enabled;
// button1 (cancel) remains enabled.
this.ui.button2.disabled = !enabled;
this.ui.button3.disabled = !enabled;
},
onBlur : function (aEvent) {
if (aEvent.target != this.ui.focusTarget)
return;
this.setButtonsEnabledState(false);
// If we blur while waiting to enable the buttons, just cancel the
// timer to ensure the delay doesn't fire while not focused.
if (this.focusTimer) {
this.focusTimer.cancel();
this.focusTimer = null;
}
},
onFocus : function (aEvent) {
if (aEvent.target != this.ui.focusTarget)
return;
this.startOnFocusDelay();
},
startOnFocusDelay : function(delayTime) {
// Shouldn't already have a timer, but just in case...
if (this.focusTimer)
return;
// If no delay specified, use 250ms. (This is the normal case for when
// after the dialog has been opened and focus shifts.)
if (!delayTime)
delayTime = 250;
let self = this;
this.focusTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this.focusTimer.initWithCallback(function() { self.onFocusTimeout(); },
delayTime, Ci.nsITimer.TYPE_ONE_SHOT);
},
onFocusTimeout : function() {
this.focusTimer = null;
this.setButtonsEnabledState(true);
},
onCheckbox : function() {
this.args.checked = this.ui.checkbox.checked;
},
onButton0 : function() {
this.args.ok = true;
this.args.buttonNumClicked = 0;
let username = this.ui.loginTextbox.value;
let password = this.ui.password1Textbox.value;
// Return textfield values
switch (this.args.promptType) {
case "prompt":
this.args.value = username;
break;
case "promptUserAndPass":
this.args.user = username;
this.args.pass = password;
break;
case "promptPassword":
this.args.pass = password;
break;
}
},
onButton1 : function() {
this.args.buttonNumClicked = 1;
},
onButton2 : function() {
this.args.buttonNumClicked = 2;
},
onButton3 : function() {
this.args.buttonNumClicked = 3;
},
};

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

@ -48,4 +48,8 @@ EXTRA_COMPONENTS = \
nsPrompter.manifest \
$(NULL)
EXTRA_JS_MODULES = \
CommonDialog.jsm \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -322,6 +322,25 @@ let PromptUtils = {
return text;
},
objectToPropBag : function (obj) {
let bag = Cc["@mozilla.org/hash-property-bag;1"].
createInstance(Ci.nsIWritablePropertyBag2);
bag.QueryInterface(Ci.nsIWritablePropertyBag);
for (let propName in obj)
bag.setProperty(propName, obj[propName]);
return bag;
},
propBagToObject : function (propBag, obj) {
// Here we iterate over the object's original properties, not the bag
// (ie, the prompt can't return more/different properties than were
// passed in). This just helps ensure that the caller provides default
// values, lest the prompt forget to set them.
for (let propName in obj)
obj[propName] = propBag.getProperty(propName);
},
};
XPCOMUtils.defineLazyGetter(PromptUtils, "strBundle", function () {
@ -343,8 +362,19 @@ XPCOMUtils.defineLazyGetter(PromptUtils, "ellipsis", function () {
const COMMON_DIALOG = "chrome://global/content/commonDialog.xul";
const SELECT_DIALOG = "chrome://global/content/selectDialog.xul";
function openModalWindow(domWin, uri, args) {
// XXX do we want to do modal state if we fall back to .activeWindow?
if (!domWin)
domWin = Services.ww.activeWindow;
// XXX domWin may still be null here if there are _no_ windows open.
// Note that we don't need to fire DOMWillOpenModalDialog and
// DOMModalDialogClosed events here, wwatcher's OpenWindowJSInternal
// will do that. Similarly for enterModalState / leaveModalState.
Services.ww.openWindow(domWin, uri, "_blank", "centerscreen,chrome,modal,titlebar", args);
}
function ModalPrompter(domWin) {
this.domWin = domWin;
@ -358,25 +388,15 @@ ModalPrompter.prototype = {
/* ---------- internal methods ---------- */
newPropBag : function () {
let bag = Cc["@mozilla.org/hash-property-bag;1"].
createInstance(Ci.nsIWritablePropertyBag2);
return bag.QueryInterface(Ci.nsIWritablePropertyBag);
},
openPrompt : function (args) {
const COMMON_DIALOG = "chrome://global/content/commonDialog.xul";
const SELECT_DIALOG = "chrome://global/content/selectDialog.xul";
openPrompt : function (uri, args) {
// XXX do we want to do modal state if we fall back to .activeWindow?
let domWin = this.domWin;
if (!domWin)
domWin = Services.ww.activeWindow;
let uri = (args.promptType == "select") ? SELECT_DIALOG : COMMON_DIALOG;
// XXX domWin may still be null here if there are _no_ windows open.
// Note that we don't need to fire DOMWillOpenModalDialog and
// DOMModalDialogClosed events here, wwatcher's OpenWindowJSInternal
// will do that. Similarly for enterModalState / leaveModalState.
Services.ww.openWindow(domWin, uri, "_blank", "centerscreen,chrome,modal,titlebar", args);
let propBag = PromptUtils.objectToPropBag(args);
openModalWindow(this.domWin, uri, propBag);
PromptUtils.propBagToObject(propBag, args);
},
@ -421,66 +441,70 @@ ModalPrompter.prototype = {
if (!title)
title = PromptUtils.getLocalizedString("Alert");
let args = this.newPropBag();
args.setProperty("promptType", "alert");
args.setProperty("title", title);
args.setProperty("text", text);
let args = {
promptType: "alert",
title: title,
text: text,
};
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
},
alertCheck : function (title, text, checkLabel, checkValue) {
if (!title)
title = PromptUtils.getLocalizedString("Alert");
let args = this.newPropBag();
args.setProperty("promptType", "alertCheck");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("checkLabel", checkLabel);
args.setProperty("checked", checkValue.value);
let args = {
promptType: "alertCheck",
title: title,
text: text,
checkLabel: checkLabel,
checked: checkValue.value,
};
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
// Checkbox state always returned, even if cancel clicked.
checkValue.value = args.getProperty("checked");
checkValue.value = args.checked;
},
confirm : function (title, text) {
if (!title)
title = PromptUtils.getLocalizedString("Confirm");
let args = this.newPropBag();
args.setProperty("promptType", "confirm");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("ok", false);
let args = {
promptType: "confirm",
title: title,
text: text,
ok: false,
};
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
// Did user click Ok or Cancel?
return args.getProperty("ok");
return args.ok;
},
confirmCheck : function (title, text, checkLabel, checkValue) {
if (!title)
title = PromptUtils.getLocalizedString("ConfirmCheck");
let args = this.newPropBag();
args.setProperty("promptType", "confirmCheck");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("checkLabel", checkLabel);
args.setProperty("checked", checkValue.value);
args.setProperty("ok", false);
let args = {
promptType: "confirmCheck",
title: title,
text: text,
checkLabel: checkLabel,
checked: checkValue.value,
ok: false,
};
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
// Checkbox state always returned, even if cancel clicked.
checkValue.value = args.getProperty("checked");
checkValue.value = args.checked;
// Did user click Ok or Cancel?
return args.getProperty("ok");
return args.ok;
},
confirmEx : function (title, text, flags, button0, button1, button2,
@ -489,60 +513,62 @@ ModalPrompter.prototype = {
if (!title)
title = PromptUtils.getLocalizedString("Confirm");
let args = this.newPropBag();
args.setProperty("promptType", "confirmEx");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("checkLabel", checkLabel);
args.setProperty("checked", checkValue.value);
args.setProperty("ok", false);
args.setProperty("buttonNumClicked", 1);
let args = {
promptType: "confirmEx",
title: title,
text: text,
checkLabel: checkLabel,
checked: checkValue.value,
ok: false,
buttonNumClicked: 1,
};
let [label0, label1, label2, defaultButtonNum, isDelayEnabled] =
PromptUtils.confirmExHelper(flags, button0, button1, button2);
args.setProperty("defaultButtonNum", defaultButtonNum);
args.setProperty("enableDelay", isDelayEnabled);
args.defaultButtonNum = defaultButtonNum;
args.enableDelay = isDelayEnabled;
if (label0) {
args.setProperty("button0Label", label0);
args.button0Label = label0;
if (label1) {
args.setProperty("button1Label", label1);
args.button1Label = label1;
if (label2) {
args.setProperty("button2Label", label2);
args.button2Label = label2;
}
}
}
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
// Checkbox state always returned, even if cancel clicked.
checkValue.value = args.getProperty("checked");
checkValue.value = args.checked;
// Get the number of the button the user clicked.
return args.getProperty("buttonNumClicked");
return args.buttonNumClicked;
},
nsIPrompt_prompt : function (title, text, value, checkLabel, checkValue) {
if (!title)
title = PromptUtils.getLocalizedString("Prompt");
let args = this.newPropBag();
args.setProperty("promptType", "prompt");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("value", value.value);
args.setProperty("checkLabel", checkLabel);
args.setProperty("checked", checkValue.value);
args.setProperty("ok", false);
let args = {
promptType: "prompt",
title: title,
text: text,
value: value.value,
checkLabel: checkLabel,
checked: checkValue.value,
ok: false,
};
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
// Did user click Ok or Cancel?
let ok = args.getProperty("ok");
let ok = args.ok;
if (ok) {
checkValue.value = args.getProperty("checked");
value.value = args.getProperty("value");
checkValue.value = args.checked;
value.value = args.value;
}
return ok;
@ -552,24 +578,25 @@ ModalPrompter.prototype = {
if (!title)
title = PromptUtils.getLocalizedString("PromptUsernameAndPassword2");
let args = this.newPropBag();
args.setProperty("promptType", "promptUserAndPass");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("user", user.value);
args.setProperty("pass", pass.value);
args.setProperty("checkLabel", checkLabel);
args.setProperty("checked", checkValue.value);
args.setProperty("ok", false);
let args = {
promptType: "promptUserAndPass",
title: title,
text: text,
user: user.value,
pass: pass.value,
checkLabel: checkLabel,
checked: checkValue.value,
ok: false,
};
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
// Did user click Ok or Cancel?
let ok = args.getProperty("ok");
let ok = args.ok;
if (ok) {
checkValue.value = args.getProperty("checked");
user.value = args.getProperty("user");
pass.value = args.getProperty("pass");
checkValue.value = args.checked;
user.value = args.user;
pass.value = args.pass;
}
return ok;
@ -579,22 +606,23 @@ ModalPrompter.prototype = {
if (!title)
title = PromptUtils.getLocalizedString("PromptPassword2");
let args = this.newPropBag();
args.setProperty("promptType", "promptPassword");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("pass", pass.value);
args.setProperty("checkLabel", checkLabel);
args.setProperty("checked", checkValue.value);
args.setProperty("ok", false);
let args = {
promptType: "promptPassword",
title: title,
text: text,
pass: pass.value,
checkLabel: checkLabel,
checked: checkValue.value,
ok: false,
}
this.openPrompt(COMMON_DIALOG, args);
this.openPrompt(args);
// Did user click Ok or Cancel?
let ok = args.getProperty("ok");
let ok = args.ok;
if (ok) {
checkValue.value = args.getProperty("checked");
pass.value = args.getProperty("pass");
checkValue.value = args.checked;
pass.value = args.pass;
}
return ok;
@ -604,19 +632,21 @@ ModalPrompter.prototype = {
if (!title)
title = PromptUtils.getLocalizedString("Select");
let args = this.newPropBag();
args.setProperty("promptType", "select");
args.setProperty("title", title);
args.setProperty("text", text);
args.setProperty("list", list);
args.setProperty("ok", false);
let args = {
promptType: "select",
title: title,
text: text,
list: list,
selected: -1,
ok: false,
};
this.openPrompt(SELECT_DIALOG, args);
this.openPrompt(args);
// Did user click Ok or Cancel?
let ok = args.getProperty("ok");
let ok = args.ok;
if (ok)
selected.value = args.getProperty("selected");
selected.value = args.selected;
return ok;
},

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

@ -24,6 +24,20 @@ let prompter = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService2);
let ioService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
let pollTimer;
function pollDialog(dialog) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
if (dialog.getButton("accept").disabled)
return;
ok(true, "dialog button is enabled now");
pollTimer.cancel();
pollTimer = null;
dialog.acceptDialog();
didDialog = true;
}
function checkExpectedState(doc, state) {
let msg = doc.getElementById("info.body").textContent;
@ -654,6 +668,27 @@ function handleDialog(doc, testNum) {
checkExpectedState(doc, state);
break;
case 30:
// ConfirmEx (with delay, ok)
state = {
msg : "This is the confirmEx delay text.",
title : "TestTitle",
iconClass : "question-icon",
textHidden : true,
passHidden : true,
checkHidden : true,
textValue : "",
passValue : "",
checkMsg : "",
checked : false,
};
is(dialog.getButton("accept").label, "OK", "Checking accept-button label");
is(dialog.getButton("cancel").label, "Cancel", "Checking cancel-button label");
is(dialog.getButton("accept").disabled, true, "Checking accept-button is disabled");
is(dialog.getButton("cancel").disabled, false, "Checking cancel-button isn't disabled ");
checkExpectedState(doc, state);
break;
case 100:
// PromptAuth (no realm, ok, with checkbox)
@ -711,6 +746,14 @@ function handleDialog(doc, testNum) {
if (testNum == 28) {
dialog._doButtonCommand("extra1");
} else if (testNum == 30) {
// Buttons are disabled at the moment, poll until they're reenabled.
// Can't use setInterval here, because the window's in a modal state
// and thus DOM events are suppressed.
pollTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
pollTimer.initWithCallback(function() { pollDialog(dialog); },
100, Ci.nsITimer.TYPE_REPEATING_SLACK);
return;
} else {
if (clickOK)
dialog.acceptDialog();
@ -1049,6 +1092,15 @@ prompter.alert(null, "TestTitle", "This is the alert text.");
ok(didDialog, "handleDialog was invoked");
// ===== test 30 =====
// ConfirmEx (delay, ok)
testNum++;
startCallbackTimer();
flags = (Ci.nsIPromptService.STD_OK_CANCEL_BUTTONS | Ci.nsIPromptService.BUTTON_DELAY_ENABLE);
clickedButton = prompter.confirmEx(window, "TestTitle", "This is the confirmEx delay text.", flags, null, null, null, null, {});
is(clickedButton, 0, "checked expected button num click");
ok(didDialog, "handleDialog was invoked");
// promptAuth already tested via password manager but do a few specific things here.

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

@ -294,7 +294,8 @@ nsFormFillController::SetPopupOpen(PRBool aPopupOpen)
NS_ENSURE_STATE(presShell);
presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
// mFocusedPopup can be destroyed after ScrollContentIntoView, see bug 420089
if (mFocusedPopup)
mFocusedPopup->OpenAutocompletePopup(this, mFocusedInput);

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

@ -259,6 +259,7 @@
</setter>
</property>
<field name="_newElementCount">0</field>
<method name="_getToolbarItem">
<parameter name="aId"/>
<body>
@ -273,7 +274,10 @@
case "spring":
case "spacer":
newItem = document.createElementNS(XUL_NS, "toolbar" + aId);
newItem.id = aId + Date.now() + this.childNodes.length;
// Due to timers resolution Date.now() can be the same for
// elements created in small timeframes. So ids are
// differentiated through a unique count suffix.
newItem.id = aId + Date.now() + (++this._newElementCount);
if (aId == "spring")
newItem.flex = 1;
break;

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

@ -22,6 +22,19 @@ btnPageCSS=CSS
tipPageCSS=Log CSS parsing errors
btnPageJS=JS
tipPageJS=Log JavaScript exceptions
# LOCALIZATION NOTE (btnPageWebDeveloper):
#
# This is used as the text of the "Web Developer" button on the toolbar. It
# shows or hides messages that the web developer inserted on the page for
# debugging purposes, using calls such console.log() and console.error(). You
# may wish to localize this as "Page" if that is clearer in your locale. See
# bug 601667 for more information.
btnPageWebDeveloper=Web Developer
# LOCALIZATION NOTE (tipPageWebDeveloper):
#
# This is used as the text of the tool tip for the "Web Developer" button on
# the toolbar.
tipPageWebDeveloper=Log messages sent to the "console" object
btnConsoleErrors=Errors
tipConsoleErrors=Log calls to console.error()
btnConsoleInfo=Info
@ -35,6 +48,11 @@ tipGlobal=Toggle Global Message logging
localConsole=Local Console
clearConsoleCmd.label=Clear Console
clearConsoleCmd.accesskey=e
# LOCALIZATION NOTE (btnClear):
#
# This is used as the text of the "Clear" button for the toolbar. It clears the
# contents of the console.
btnClear=Clear
stringFilter=Filter
close.button=Close
close.accesskey=C

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

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="addon-test-pref-window">
<label value="Oh hai!"/>
</window>
<?xml version="1.0"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="addon-test-pref-window">
<label value="Oh hai!"/>
</window>

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

@ -1,77 +1,78 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 557943 - Searching for addons can result in wrong results
var gManagerWindow;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "Microsoft .NET Framework Assistant",
description: "",
version: "6.66"
}, {
id: "addon2@tests.mozilla.org",
name: "AwesomeNet Addon",
description: ""
}, {
id: "addon3@tests.mozilla.org",
name: "Dictionnaire MySpell en Francais (réforme 1990)",
description: ""
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, function() {
finish();
});
}
function perform_search(aQuery, aCallback) {
var searchBox = gManagerWindow.document.getElementById("header-search");
searchBox.value = aQuery;
EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow);
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
var list = gManagerWindow.document.getElementById("search-list");
var rows = list.getElementsByTagName("richlistitem");
aCallback(rows);
});
}
add_test(function() {
perform_search(".net", function(aRows) {
is(aRows.length, 1, "Should only get one result");
is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result");
run_next_test();
});
});
add_test(function() {
perform_search("réf", function(aRows) {
is(aRows.length, 1, "Should only get one result");
is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result");
run_next_test();
});
});
add_test(function() {
perform_search("javascript:void()", function(aRows) {
is(aRows.length, 0, "Should not get any results");
run_next_test();
});
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 557943 - Searching for addons can result in wrong results
var gManagerWindow;
var gProvider;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "Microsoft .NET Framework Assistant",
description: "",
version: "6.66"
}, {
id: "addon2@tests.mozilla.org",
name: "AwesomeNet Addon",
description: ""
}, {
id: "addon3@tests.mozilla.org",
name: "Dictionnaire MySpell en Francais (réforme 1990)",
description: ""
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, function() {
finish();
});
}
function perform_search(aQuery, aCallback) {
var searchBox = gManagerWindow.document.getElementById("header-search");
searchBox.value = aQuery;
EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow);
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
var list = gManagerWindow.document.getElementById("search-list");
var rows = list.getElementsByTagName("richlistitem");
aCallback(rows);
});
}
add_test(function() {
perform_search(".net", function(aRows) {
is(aRows.length, 1, "Should only get one result");
is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result");
run_next_test();
});
});
add_test(function() {
perform_search("réf", function(aRows) {
is(aRows.length, 1, "Should only get one result");
is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result");
run_next_test();
});
});
add_test(function() {
perform_search("javascript:void()", function(aRows) {
is(aRows.length, 0, "Should not get any results");
run_next_test();
});
});

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

@ -119,7 +119,8 @@ function open_compatibility_window(aInactiveAddonIds, aCallback) {
info("Compatibility dialog opened");
function page_shown(aEvent) {
info("Page " + aEvent.target.id + " shown");
if (aEvent.target.pageid)
info("Page " + aEvent.target.pageid + " shown");
}
win.addEventListener("pageshow", page_shown, false);

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

@ -7,7 +7,9 @@
*/
function test() {
requestLongerTimeout(2);
// Set the timeout to 300 seconds since this test can easily take 220 seconds
// to run on a Windows debug build when it runs in a tab.
requestLongerTimeout(10);
waitForExplicitFinish();

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

@ -1,159 +1,159 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests bug 567127 - Add install button to the add-ons manager
var gFilePickerFiles = [];
var gMockFilePickerFactory;
var gMockFilePickerFactoryCID;
var gManagerWindow;
function MockFilePicker() { }
MockFilePicker.prototype = {
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFilePicker]),
init: function(aParent, aTitle, aMode) { },
appendFilters: function(aFilterMask) { },
appendFilter: function(aTitle, aFilter) { },
defaultString: "",
defaultExtension: "",
filterIndex: 0,
displayDirectory: null,
file: null,
fileURL: null,
get files() {
var i = 0;
return {
getNext: function() gFilePickerFiles[i++],
hasMoreElements: function() gFilePickerFiles.length > i
};
},
show: function() {
return gFilePickerFiles.length == 0 ?
Components.interfaces.nsIFilePicker.returnCancel :
Components.interfaces.nsIFilePicker.returnOK;
}
};
// This listens for the next opened window and checks it is of the right url.
// opencallback is called when the new window is fully loaded
// closecallback is called when the window is closed
function WindowOpenListener(url, opencallback, closecallback) {
this.url = url;
this.opencallback = opencallback;
this.closecallback = closecallback;
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.addListener(this);
}
WindowOpenListener.prototype = {
url: null,
opencallback: null,
closecallback: null,
window: null,
domwindow: null,
handleEvent: function(event) {
is(this.domwindow.document.location.href, this.url, "Should have opened the correct window");
this.domwindow.removeEventListener("load", this, false);
// Allow any other load handlers to execute
var self = this;
executeSoon(function() { self.opencallback(self.domwindow); } );
},
onWindowTitleChange: function(window, title) {
},
onOpenWindow: function(window) {
if (this.window)
return;
this.window = window;
this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowInternal);
this.domwindow.addEventListener("load", this, false);
},
onCloseWindow: function(window) {
if (this.window != window)
return;
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.removeListener(this);
this.opencallback = null;
this.window = null;
this.domwindow = null;
// Let the window close complete
executeSoon(this.closecallback);
this.closecallback = null;
}
};
function test_confirmation(aWindow, aExpectedURLs) {
var list = aWindow.document.getElementById("itemList");
is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs");
aExpectedURLs.forEach(function(aURL) {
var node = list.firstChild;
while (node) {
if (node.url == aURL) {
ok(true, "Should have seen " + aURL + " in the list");
return;
}
node = node.nextSibling;
}
ok(false, "Should have seen " + aURL + " in the list");
});
aWindow.document.documentElement.cancelDialog();
}
function test() {
waitForExplicitFinish();
gMockFilePickerFactoryCID = Components.ID("{4f595df2-9108-42c6-9910-0dc392a310c9}");
gMockFilePickerFactory = XPCOMUtils._getFactory(MockFilePicker);
var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compReg.registerFactory(gMockFilePickerFactoryCID,
"Mock FilePicker",
"@mozilla.org/filepicker;1",
gMockFilePickerFactory);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compReg.unregisterFactory(gMockFilePickerFactoryCID,
gMockFilePickerFactory);
close_manager(gManagerWindow, function() {
finish();
});
}
add_test(function() {
var filePaths = [
get_addon_file_url("browser_bug567127_1.xpi"),
get_addon_file_url("browser_bug567127_2.xpi")
];
gFilePickerFiles = filePaths.map(function(aPath) aPath.file);
new WindowOpenListener(INSTALL_URI, function(aWindow) {
test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec));
}, run_next_test);
gManagerWindow.gViewController.doCommand("cmd_installFromFile");
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests bug 567127 - Add install button to the add-ons manager
var gFilePickerFiles = [];
var gMockFilePickerFactory;
var gMockFilePickerFactoryCID;
var gManagerWindow;
function MockFilePicker() { }
MockFilePicker.prototype = {
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIFilePicker]),
init: function(aParent, aTitle, aMode) { },
appendFilters: function(aFilterMask) { },
appendFilter: function(aTitle, aFilter) { },
defaultString: "",
defaultExtension: "",
filterIndex: 0,
displayDirectory: null,
file: null,
fileURL: null,
get files() {
var i = 0;
return {
getNext: function() gFilePickerFiles[i++],
hasMoreElements: function() gFilePickerFiles.length > i
};
},
show: function() {
return gFilePickerFiles.length == 0 ?
Components.interfaces.nsIFilePicker.returnCancel :
Components.interfaces.nsIFilePicker.returnOK;
}
};
// This listens for the next opened window and checks it is of the right url.
// opencallback is called when the new window is fully loaded
// closecallback is called when the window is closed
function WindowOpenListener(url, opencallback, closecallback) {
this.url = url;
this.opencallback = opencallback;
this.closecallback = closecallback;
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.addListener(this);
}
WindowOpenListener.prototype = {
url: null,
opencallback: null,
closecallback: null,
window: null,
domwindow: null,
handleEvent: function(event) {
is(this.domwindow.document.location.href, this.url, "Should have opened the correct window");
this.domwindow.removeEventListener("load", this, false);
// Allow any other load handlers to execute
var self = this;
executeSoon(function() { self.opencallback(self.domwindow); } );
},
onWindowTitleChange: function(window, title) {
},
onOpenWindow: function(window) {
if (this.window)
return;
this.window = window;
this.domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowInternal);
this.domwindow.addEventListener("load", this, false);
},
onCloseWindow: function(window) {
if (this.window != window)
return;
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.removeListener(this);
this.opencallback = null;
this.window = null;
this.domwindow = null;
// Let the window close complete
executeSoon(this.closecallback);
this.closecallback = null;
}
};
function test_confirmation(aWindow, aExpectedURLs) {
var list = aWindow.document.getElementById("itemList");
is(list.childNodes.length, aExpectedURLs.length, "Should be the right number of installs");
aExpectedURLs.forEach(function(aURL) {
var node = list.firstChild;
while (node) {
if (node.url == aURL) {
ok(true, "Should have seen " + aURL + " in the list");
return;
}
node = node.nextSibling;
}
ok(false, "Should have seen " + aURL + " in the list");
});
aWindow.document.documentElement.cancelDialog();
}
function test() {
waitForExplicitFinish();
gMockFilePickerFactoryCID = Components.ID("{4f595df2-9108-42c6-9910-0dc392a310c9}");
gMockFilePickerFactory = XPCOMUtils._getFactory(MockFilePicker);
var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compReg.registerFactory(gMockFilePickerFactoryCID,
"Mock FilePicker",
"@mozilla.org/filepicker;1",
gMockFilePickerFactory);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
var compReg = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compReg.unregisterFactory(gMockFilePickerFactoryCID,
gMockFilePickerFactory);
close_manager(gManagerWindow, function() {
finish();
});
}
add_test(function() {
var filePaths = [
get_addon_file_url("browser_bug567127_1.xpi"),
get_addon_file_url("browser_bug567127_2.xpi")
];
gFilePickerFiles = filePaths.map(function(aPath) aPath.file);
new WindowOpenListener(INSTALL_URI, function(aWindow) {
test_confirmation(aWindow, filePaths.map(function(aPath) aPath.spec));
}, run_next_test);
gManagerWindow.gViewController.doCommand("cmd_installFromFile");
});

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

@ -1,129 +1,129 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults)
const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL";
const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
const SEARCH_URL = TESTROOT + "browser_searching.xml";
const SEARCH_EXPECTED_TOTAL = 100;
const SEARCH_QUERY = "search";
var gManagerWindow;
function test() {
Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
waitForExplicitFinish();
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
// Test generates a lot of available installs so just cancel them all
AddonManager.getAllInstalls(function(aInstalls) {
aInstalls.forEach(function(aInstall) {
aInstall.cancel();
});
close_manager(gManagerWindow, finish);
});
}
function search(aRemoteSearch, aCallback) {
var searchBox = gManagerWindow.document.getElementById("header-search");
searchBox.value = SEARCH_QUERY;
EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
if (aRemoteSearch)
var filter = gManagerWindow.document.getElementById("search-filter-remote");
else
var filter = gManagerWindow.document.getElementById("search-filter-local");
EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
executeSoon(aCallback);
});
}
function check_allresultslink(aShouldShow) {
var list = gManagerWindow.document.getElementById("search-list");
var link = gManagerWindow.document.getElementById("search-allresults-link");
is(link.parentNode, list.lastChild, "Footer should be at the end of the richlistbox");
if (aShouldShow) {
is_element_visible(link, "All Results link should be visible");
is(link.value, "See all " + SEARCH_EXPECTED_TOTAL + " results", "All Results link should show the correct message");
var scope = {};
Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope);
is(link.href, scope.AddonRepository.getSearchURL(SEARCH_QUERY), "All Results link should have the correct href");
} else {
is_element_hidden(link, "All Results link should be hidden");
}
}
add_test(function() {
info("Searching locally");
search(false, function() {
check_allresultslink(false);
restart_manager(gManagerWindow, null, function(aManager) {
gManagerWindow = aManager;
run_next_test();
});
});
});
add_test(function() {
info("Searching remotely - more results than cap");
Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
search(true, function() {
check_allresultslink(true);
restart_manager(gManagerWindow, null, function(aManager) {
gManagerWindow = aManager;
run_next_test();
});
});
});
add_test(function() {
info("Searching remotely - less results than cap");
Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200);
search(true, function() {
check_allresultslink(false);
restart_manager(gManagerWindow, null, function(aManager) {
gManagerWindow = aManager;
run_next_test();
});
});
});
add_test(function() {
info("Searching remotely - more results than cap");
Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
search(true, function() {
check_allresultslink(true);
run_next_test();
});
});
add_test(function() {
info("Switching views");
gManagerWindow.loadView("addons://list/extension");
wait_for_view_load(gManagerWindow, function() {
info("Re-loading previous search");
search(true, function() {
check_allresultslink(true);
run_next_test();
});
});
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 581076 - No "See all results" link present when searching for add-ons and not all are displayed (extensions.getAddons.maxResults)
const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL";
const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
const SEARCH_URL = TESTROOT + "browser_searching.xml";
const SEARCH_EXPECTED_TOTAL = 100;
const SEARCH_QUERY = "search";
var gManagerWindow;
function test() {
Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
waitForExplicitFinish();
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
// Test generates a lot of available installs so just cancel them all
AddonManager.getAllInstalls(function(aInstalls) {
aInstalls.forEach(function(aInstall) {
aInstall.cancel();
});
close_manager(gManagerWindow, finish);
});
}
function search(aRemoteSearch, aCallback) {
var searchBox = gManagerWindow.document.getElementById("header-search");
searchBox.value = SEARCH_QUERY;
EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
if (aRemoteSearch)
var filter = gManagerWindow.document.getElementById("search-filter-remote");
else
var filter = gManagerWindow.document.getElementById("search-filter-local");
EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
executeSoon(aCallback);
});
}
function check_allresultslink(aShouldShow) {
var list = gManagerWindow.document.getElementById("search-list");
var link = gManagerWindow.document.getElementById("search-allresults-link");
is(link.parentNode, list.lastChild, "Footer should be at the end of the richlistbox");
if (aShouldShow) {
is_element_visible(link, "All Results link should be visible");
is(link.value, "See all " + SEARCH_EXPECTED_TOTAL + " results", "All Results link should show the correct message");
var scope = {};
Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope);
is(link.href, scope.AddonRepository.getSearchURL(SEARCH_QUERY), "All Results link should have the correct href");
} else {
is_element_hidden(link, "All Results link should be hidden");
}
}
add_test(function() {
info("Searching locally");
search(false, function() {
check_allresultslink(false);
restart_manager(gManagerWindow, null, function(aManager) {
gManagerWindow = aManager;
run_next_test();
});
});
});
add_test(function() {
info("Searching remotely - more results than cap");
Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
search(true, function() {
check_allresultslink(true);
restart_manager(gManagerWindow, null, function(aManager) {
gManagerWindow = aManager;
run_next_test();
});
});
});
add_test(function() {
info("Searching remotely - less results than cap");
Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 200);
search(true, function() {
check_allresultslink(false);
restart_manager(gManagerWindow, null, function(aManager) {
gManagerWindow = aManager;
run_next_test();
});
});
});
add_test(function() {
info("Searching remotely - more results than cap");
Services.prefs.setIntPref(PREF_GETADDONS_MAXRESULTS, 3);
search(true, function() {
check_allresultslink(true);
run_next_test();
});
});
add_test(function() {
info("Switching views");
gManagerWindow.loadView("addons://list/extension");
wait_for_view_load(gManagerWindow, function() {
info("Re-loading previous search");
search(true, function() {
check_allresultslink(true);
run_next_test();
});
});
});

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

@ -1,152 +1,152 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 587970 - Provide ability "Update all now" within 'Available Updates' screen
var gManagerWindow;
var gProvider;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "addon 1",
version: "1.0",
applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
}, {
id: "addon2@tests.mozilla.org",
name: "addon 2",
version: "2.0",
applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
}]);
open_manager("addons://updates/available", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, finish);
}
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
is(list.childNodes.length, 0, "Available updates list should be empty");
var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
is_element_visible(emptyNotice, "Empty notice should be visible");
var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
is_element_hidden(updateSelected, "Update Selected button should be hidden");
info("Adding updates");
gProvider.createInstalls([{
name: "addon 1",
version: "1.1",
existingAddon: gProvider.addons[0]
}, {
name: "addon 2",
version: "2.1",
existingAddon: gProvider.addons[1]
}]);
function wait_for_refresh() {
if (list.childNodes.length == 2 &&
list.childNodes[0].mManualUpdate &&
list.childNodes[1].mManualUpdate) {
run_next_test();
} else {
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
}
}
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
is(list.childNodes.length, 2, "Available updates list should have 2 items");
var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
isnot(item2, null, "Item for addon2@tests.mozilla.org should be in list");
var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
is_element_hidden(emptyNotice, "Empty notice should be hidden");
var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
is_element_visible(updateSelected, "Update Selected button should be visible");
is(updateSelected.disabled, false, "Update Selected button should be enabled by default");
is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2");
info("Unchecking Include Update checkbox for addon1");
EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
is(updateSelected.disabled, false, "Update Selected button should still be enabled");
info("Unchecking Include Update checkbox for addon2");
EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
is(item2._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon2");
is(updateSelected.disabled, true, "Update Selected button should now be disabled");
info("Checking Include Update checkbox for addon2");
EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
is(item2._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon2");
is(updateSelected.disabled, false, "Update Selected button should now be enabled");
var listener = {
onInstallEnded: function() {
gProvider.installs[1].removeTestListener(listener);
is(gProvider.installs[0].state, AddonManager.STATE_AVAILABLE, "addon1 should not have been upgraded");
is(gProvider.installs[1].state, AddonManager.STATE_INSTALLED, "addon2 should have been upgraded");
}
}
gProvider.installs[1].addTestListener(listener);
info("Clicking Update Selected button");
EventUtils.synthesizeMouse(updateSelected, 2, 2, { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
function wait_for_refresh() {
var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
if (item.mManualUpdate) {
run_next_test();
} else {
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
}
}
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
}, true);
});
add_test(function() {
var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
is(updateSelected.disabled, false, "Update Selected button should now be enabled");
var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
info("Unchecking Include Update checkbox for addon1");
EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
is(updateSelected.disabled, true, "Update Selected button should now be disabled");
run_next_test();
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 587970 - Provide ability "Update all now" within 'Available Updates' screen
var gManagerWindow;
var gProvider;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "addon 1",
version: "1.0",
applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
}, {
id: "addon2@tests.mozilla.org",
name: "addon 2",
version: "2.0",
applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
}]);
open_manager("addons://updates/available", function(aWindow) {
gManagerWindow = aWindow;
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, finish);
}
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
is(list.childNodes.length, 0, "Available updates list should be empty");
var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
is_element_visible(emptyNotice, "Empty notice should be visible");
var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
is_element_hidden(updateSelected, "Update Selected button should be hidden");
info("Adding updates");
gProvider.createInstalls([{
name: "addon 1",
version: "1.1",
existingAddon: gProvider.addons[0]
}, {
name: "addon 2",
version: "2.1",
existingAddon: gProvider.addons[1]
}]);
function wait_for_refresh() {
if (list.childNodes.length == 2 &&
list.childNodes[0].mManualUpdate &&
list.childNodes[1].mManualUpdate) {
run_next_test();
} else {
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
}
}
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
is(list.childNodes.length, 2, "Available updates list should have 2 items");
var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
var item2 = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
isnot(item2, null, "Item for addon2@tests.mozilla.org should be in list");
var emptyNotice = gManagerWindow.document.getElementById("empty-availableUpdates-msg");
is_element_hidden(emptyNotice, "Empty notice should be hidden");
var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
is_element_visible(updateSelected, "Update Selected button should be visible");
is(updateSelected.disabled, false, "Update Selected button should be enabled by default");
is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
is(item2._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon2");
info("Unchecking Include Update checkbox for addon1");
EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
is(updateSelected.disabled, false, "Update Selected button should still be enabled");
info("Unchecking Include Update checkbox for addon2");
EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
is(item2._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon2");
is(updateSelected.disabled, true, "Update Selected button should now be disabled");
info("Checking Include Update checkbox for addon2");
EventUtils.synthesizeMouse(item2._includeUpdate, 2, 2, { }, gManagerWindow);
is(item2._includeUpdate.checked, true, "Include Update checkbox should now be be checked for addon2");
is(updateSelected.disabled, false, "Update Selected button should now be enabled");
var listener = {
onInstallEnded: function() {
gProvider.installs[1].removeTestListener(listener);
is(gProvider.installs[0].state, AddonManager.STATE_AVAILABLE, "addon1 should not have been upgraded");
is(gProvider.installs[1].state, AddonManager.STATE_INSTALLED, "addon2 should have been upgraded");
}
}
gProvider.installs[1].addTestListener(listener);
info("Clicking Update Selected button");
EventUtils.synthesizeMouse(updateSelected, 2, 2, { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
function wait_for_refresh() {
var item = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
if (item.mManualUpdate) {
run_next_test();
} else {
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
}
}
info("Waiting for pane to refresh");
setTimeout(wait_for_refresh, 10);
}, true);
});
add_test(function() {
var updateSelected = gManagerWindow.document.getElementById("update-selected-btn");
is(updateSelected.disabled, false, "Update Selected button should now be enabled");
var item1 = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
isnot(item1, null, "Item for addon1@tests.mozilla.org should be in list");
is(item1._includeUpdate.checked, true, "Include Update checkbox should be checked by default for addon1");
info("Unchecking Include Update checkbox for addon1");
EventUtils.synthesizeMouse(item1._includeUpdate, 2, 2, { }, gManagerWindow);
is(item1._includeUpdate.checked, false, "Include Update checkbox should now be be unchecked for addon1");
is(updateSelected.disabled, true, "Update Selected button should now be disabled");
run_next_test();
});

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

@ -1,351 +1,351 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 591465 - Context menu of add-ons miss context related state change entries
const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
const SEARCH_URL = TESTROOT + "browser_bug591465.xml";
const SEARCH_QUERY = "SEARCH";
var gManagerWindow;
var gProvider;
var gContextMenu;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "addon 1",
version: "1.0"
}, {
id: "addon2@tests.mozilla.org",
name: "addon 2",
version: "1.0",
_userDisabled: true
}, {
id: "theme1@tests.mozilla.org",
name: "theme 1",
version: "1.0",
type: "theme"
}, {
id: "theme2@tests.mozilla.org",
name: "theme 2",
version: "1.0",
type: "theme",
_userDisabled: true
}, {
id: "theme3@tests.mozilla.org",
name: "theme 3",
version: "1.0",
type: "theme",
permissions: 0
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
gContextMenu = aWindow.document.getElementById("addonitem-popup");
run_next_test();
});
}
function end_test() {
Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
close_manager(gManagerWindow, finish);
}
function check_contextmenu(aIsTheme, aIsEnabled, aIsRemote, aIsDetails, aIsSingleItemCase) {
if (aIsTheme || aIsEnabled || aIsRemote)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableItem"),
"'Enable' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_enableItem"),
"'Enable' should be visible");
if (aIsTheme || !aIsEnabled || aIsRemote)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableItem"),
"'Disable' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_disableItem"),
"'Disable' should be visible");
if (!aIsTheme || aIsEnabled || aIsRemote || aIsSingleItemCase)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableTheme"),
"'Wear Theme' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_enableTheme"),
"'Wear Theme' should be visible");
if (!aIsTheme || !aIsEnabled || aIsRemote || aIsSingleItemCase)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableTheme"),
"'Stop Wearing Theme' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_disableTheme"),
"'Stop Wearing Theme' should be visible");
if (aIsRemote)
is_element_visible(gManagerWindow.document.getElementById("menuitem_installItem"),
"'Install' should be visible");
else
is_element_hidden(gManagerWindow.document.getElementById("menuitem_installItem"),
"'Install' should be hidden");
if (aIsDetails)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_showDetails"),
"'Show More Information' should be hidden in details view");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_showDetails"),
"'Show More Information' should be visible in list view");
if (aIsSingleItemCase)
is_element_hidden(gManagerWindow.document.getElementById("addonitem-menuseparator"),
"Menu separator should be hidden with only one menu item");
else
is_element_visible(gManagerWindow.document.getElementById("addonitem-menuseparator"),
"Menu separator should be visible with multiple menu items");
}
add_test(function() {
var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
isnot(el, null, "Should have found addon element");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, true, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled extension item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
add_test(function() {
var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled extension item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
add_test(function() {
gManagerWindow.loadView("addons://list/theme");
wait_for_view_load(gManagerWindow, function() {
var el = get_addon_element(gManagerWindow, "theme1@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, true, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled theme item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
var el = get_addon_element(gManagerWindow, "theme2@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, false, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled theme item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
add_test(function() {
gManagerWindow.loadView("addons://detail/addon1@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, true, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled extension, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/addon2@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled extension, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/theme1@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, true, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled theme, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/theme2@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, false, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled theme, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/theme3@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, true, false, true, true);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu with single menu item on enabled theme, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
info("Searching for remote addons");
Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
var searchBox = gManagerWindow.document.getElementById("header-search");
searchBox.value = SEARCH_QUERY;
EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
var filter = gManagerWindow.document.getElementById("search-filter-remote");
EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
executeSoon(function() {
var el = get_addon_element(gManagerWindow, "remote1@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, true, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on remote extension item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/remote1@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, true, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on remote extension, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 591465 - Context menu of add-ons miss context related state change entries
const PREF_GETADDONS_MAXRESULTS = "extensions.getAddons.maxResults";
const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
const SEARCH_URL = TESTROOT + "browser_bug591465.xml";
const SEARCH_QUERY = "SEARCH";
var gManagerWindow;
var gProvider;
var gContextMenu;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "addon 1",
version: "1.0"
}, {
id: "addon2@tests.mozilla.org",
name: "addon 2",
version: "1.0",
_userDisabled: true
}, {
id: "theme1@tests.mozilla.org",
name: "theme 1",
version: "1.0",
type: "theme"
}, {
id: "theme2@tests.mozilla.org",
name: "theme 2",
version: "1.0",
type: "theme",
_userDisabled: true
}, {
id: "theme3@tests.mozilla.org",
name: "theme 3",
version: "1.0",
type: "theme",
permissions: 0
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
gContextMenu = aWindow.document.getElementById("addonitem-popup");
run_next_test();
});
}
function end_test() {
Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
close_manager(gManagerWindow, finish);
}
function check_contextmenu(aIsTheme, aIsEnabled, aIsRemote, aIsDetails, aIsSingleItemCase) {
if (aIsTheme || aIsEnabled || aIsRemote)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableItem"),
"'Enable' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_enableItem"),
"'Enable' should be visible");
if (aIsTheme || !aIsEnabled || aIsRemote)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableItem"),
"'Disable' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_disableItem"),
"'Disable' should be visible");
if (!aIsTheme || aIsEnabled || aIsRemote || aIsSingleItemCase)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_enableTheme"),
"'Wear Theme' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_enableTheme"),
"'Wear Theme' should be visible");
if (!aIsTheme || !aIsEnabled || aIsRemote || aIsSingleItemCase)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_disableTheme"),
"'Stop Wearing Theme' should be hidden");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_disableTheme"),
"'Stop Wearing Theme' should be visible");
if (aIsRemote)
is_element_visible(gManagerWindow.document.getElementById("menuitem_installItem"),
"'Install' should be visible");
else
is_element_hidden(gManagerWindow.document.getElementById("menuitem_installItem"),
"'Install' should be hidden");
if (aIsDetails)
is_element_hidden(gManagerWindow.document.getElementById("menuitem_showDetails"),
"'Show More Information' should be hidden in details view");
else
is_element_visible(gManagerWindow.document.getElementById("menuitem_showDetails"),
"'Show More Information' should be visible in list view");
if (aIsSingleItemCase)
is_element_hidden(gManagerWindow.document.getElementById("addonitem-menuseparator"),
"Menu separator should be hidden with only one menu item");
else
is_element_visible(gManagerWindow.document.getElementById("addonitem-menuseparator"),
"Menu separator should be visible with multiple menu items");
}
add_test(function() {
var el = get_addon_element(gManagerWindow, "addon1@tests.mozilla.org");
isnot(el, null, "Should have found addon element");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, true, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled extension item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
add_test(function() {
var el = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled extension item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
add_test(function() {
gManagerWindow.loadView("addons://list/theme");
wait_for_view_load(gManagerWindow, function() {
var el = get_addon_element(gManagerWindow, "theme1@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, true, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled theme item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
var el = get_addon_element(gManagerWindow, "theme2@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, false, false, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled theme item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
add_test(function() {
gManagerWindow.loadView("addons://detail/addon1@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, true, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled extension, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/addon2@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled extension, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/theme1@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, true, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on enabled theme, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/theme2@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, false, false, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on disabled theme, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/theme3@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(true, true, false, true, true);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu with single menu item on enabled theme, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
add_test(function() {
info("Searching for remote addons");
Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, SEARCH_URL);
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
var searchBox = gManagerWindow.document.getElementById("header-search");
searchBox.value = SEARCH_QUERY;
EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow);
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
wait_for_view_load(gManagerWindow, function() {
var filter = gManagerWindow.document.getElementById("search-filter-remote");
EventUtils.synthesizeMouseAtCenter(filter, { }, gManagerWindow);
executeSoon(function() {
var el = get_addon_element(gManagerWindow, "remote1@tests.mozilla.org");
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, true, false, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on remote extension item");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});
});
add_test(function() {
gManagerWindow.loadView("addons://detail/remote1@tests.mozilla.org");
wait_for_view_load(gManagerWindow, function() {
gContextMenu.addEventListener("popupshown", function() {
gContextMenu.removeEventListener("popupshown", arguments.callee, false);
check_contextmenu(false, false, true, true, false);
gContextMenu.hidePopup();
run_next_test();
}, false);
info("Opening context menu on remote extension, in detail view");
var el = gManagerWindow.document.querySelector("#detail-view .detail-view-container");
EventUtils.synthesizeMouse(el, 4, 4, { }, gManagerWindow);
EventUtils.synthesizeMouse(el, 4, 4, { type: "contextmenu", button: 2 }, gManagerWindow);
});
});

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

@ -10,6 +10,7 @@ const SEARCH_URL = TESTROOT + "browser_details.xml";
var gManagerWindow;
var gCategoryUtilities;
var gProvider;
var gApp = document.getElementById("bundle_brand").getString("brandShortName");
var gVersion = Services.appinfo.version;

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

@ -1,65 +1,65 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 566194 - safe mode / security & compatibility check status are not exposed in new addon manager UI
function test() {
waitForExplicitFinish();
run_next_test();
}
function end_test() {
finish();
}
add_test(function() {
info("Testing compatibility checking warning");
var version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
var pref = "extensions.checkCompatibility." + version;
info("Setting " + pref + " pref to false")
Services.prefs.setBoolPref(pref, false);
open_manager("addons://list/extension", function(aWindow) {
var label = aWindow.document.querySelector("#list-view label.global-warning-checkcompatibility");
is_element_visible(label, "Check Compatibility warning label should be visible");
var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility");
is_element_visible(button, "Check Compatibility warning button should be visible");
info("Clicking 'Enable' button");
EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
is(Services.prefs.prefHasUserValue(pref), false, "Check Compatability pref should be cleared");
is_element_hidden(label, "Check Compatibility warning label should be hidden");
is_element_hidden(button, "Check Compatibility warning button should be hidden");
close_manager(aWindow, function() {
run_next_test();
});
});
});
add_test(function() {
info("Testing update security checking warning");
var pref = "extensions.checkUpdateSecurity";
info("Setting " + pref + " pref to false")
Services.prefs.setBoolPref(pref, false);
open_manager(null, function(aWindow) {
var label = aWindow.document.querySelector("#list-view label.global-warning-updatesecurity");
is_element_visible(label, "Check Update Security warning label should be visible");
var button = aWindow.document.querySelector("#list-view button.global-warning-updatesecurity");
is_element_visible(button, "Check Update Security warning button should be visible");
info("Clicking 'Enable' button");
EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
is(Services.prefs.prefHasUserValue(pref), false, "Check Update Security pref should be cleared");
is_element_hidden(label, "Check Update Security warning label should be hidden");
is_element_hidden(button, "Check Update Security warning button should be hidden");
close_manager(aWindow, function() {
run_next_test();
});
});
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Bug 566194 - safe mode / security & compatibility check status are not exposed in new addon manager UI
function test() {
waitForExplicitFinish();
run_next_test();
}
function end_test() {
finish();
}
add_test(function() {
info("Testing compatibility checking warning");
var version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
var pref = "extensions.checkCompatibility." + version;
info("Setting " + pref + " pref to false")
Services.prefs.setBoolPref(pref, false);
open_manager("addons://list/extension", function(aWindow) {
var label = aWindow.document.querySelector("#list-view label.global-warning-checkcompatibility");
is_element_visible(label, "Check Compatibility warning label should be visible");
var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility");
is_element_visible(button, "Check Compatibility warning button should be visible");
info("Clicking 'Enable' button");
EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
is(Services.prefs.prefHasUserValue(pref), false, "Check Compatability pref should be cleared");
is_element_hidden(label, "Check Compatibility warning label should be hidden");
is_element_hidden(button, "Check Compatibility warning button should be hidden");
close_manager(aWindow, function() {
run_next_test();
});
});
});
add_test(function() {
info("Testing update security checking warning");
var pref = "extensions.checkUpdateSecurity";
info("Setting " + pref + " pref to false")
Services.prefs.setBoolPref(pref, false);
open_manager(null, function(aWindow) {
var label = aWindow.document.querySelector("#list-view label.global-warning-updatesecurity");
is_element_visible(label, "Check Update Security warning label should be visible");
var button = aWindow.document.querySelector("#list-view button.global-warning-updatesecurity");
is_element_visible(button, "Check Update Security warning button should be visible");
info("Clicking 'Enable' button");
EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
is(Services.prefs.prefHasUserValue(pref), false, "Check Update Security pref should be cleared");
is_element_hidden(label, "Check Update Security warning label should be hidden");
is_element_hidden(button, "Check Update Security warning button should be hidden");
close_manager(aWindow, function() {
run_next_test();
});
});
});

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

@ -1,188 +1,188 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests manual updates, including the Available Updates pane
var gProvider;
var gManagerWindow;
var gCategoryUtilities;
var gAvailableCategory;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "auto updating addon",
version: "1.0",
applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, function() {
finish();
});
}
add_test(function() {
gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available");
is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden");
gProvider.createAddons([{
id: "addon2@tests.mozilla.org",
name: "manually updating addon",
version: "1.0",
isCompatible: false,
blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED,
applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
}]);
is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible");
gAvailableCategory.addEventListener("CategoryVisible", function() {
gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should not be visible");
gAvailableCategory.addEventListener("CategoryVisible", function() {
gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should be visible");
run_next_test();
}, false);
gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
}, false);
gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE;
});
add_test(function() {
gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() {
gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false);
is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1");
run_next_test();
}, false);
gCategoryUtilities.openType("extension", function() {
gProvider.createInstalls([{
name: "manually updating addon (new and improved!)",
existingAddon: gProvider.addons[1],
version: "1.1",
releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null)
}]);
var item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
is(item._version.value, "1.0", "Should still show the old version in the normal list");
});
});
add_test(function() {
wait_for_view_load(gManagerWindow, function() {
is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/available", "Available Updates category should now be selected");
is(gManagerWindow.gViewController.currentViewId, "addons://updates/available", "Available Updates view should be the current view");
run_next_test();
}, true);
EventUtils.synthesizeMouseAtCenter(gAvailableCategory, { }, gManagerWindow);
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
is(list.itemCount, 1, "Should be 1 available update listed");
var item = list.firstChild;
is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon");
// for manual update items, update-related properties are updated asynchronously,
// so we poll for one of the expected changes to know when its done
function waitForAsyncInit() {
if (item._version.value == "1.1") {
run_next_test();
return;
}
info("Update item not initialized yet, checking again in 100ms");
setTimeout(waitForAsyncInit, 100);
}
waitForAsyncInit();
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
var item = list.firstChild;
is(item._version.value, "1.1", "Update item should have version number of the update");
var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix");
is_element_visible(postfix, "'Update' postfix should be visible");
is_element_visible(item._updateAvailable, "");
is_element_visible(item._relNotesToggle, "Release notes toggle should be visible");
is_element_hidden(item._warning, "Incompatible warning should be hidden");
is_element_hidden(item._error, "Blocklist error should be hidden");
info("Opening release notes");
item.addEventListener("RelNotesToggle", function() {
item.removeEventListener("RelNotesToggle", arguments.callee, false);
info("Release notes now open");
is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden");
is_element_visible(item._relNotesError, "Release notes error message should be visible");
is(item._relNotes.childElementCount, 0, "Release notes should be empty");
info("Closing release notes");
item.addEventListener("RelNotesToggle", function() {
item.removeEventListener("RelNotesToggle", arguments.callee, false);
info("Release notes now closed");
info("Setting Release notes URI to something that should load");
gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null)
info("Re-opening release notes");
item.addEventListener("RelNotesToggle", function() {
item.removeEventListener("RelNotesToggle", arguments.callee, false);
info("Release notes now open");
is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden");
is_element_hidden(item._relNotesError, "Release notes error message should be hidden");
isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container");
run_next_test();
}, false);
EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow);
is_element_visible(item._relNotesLoading, "Release notes loading message should be visible");
}, false);
EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow);
}, false);
EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow);
is_element_visible(item._relNotesLoading, "Release notes loading message should be visible");
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
var item = list.firstChild;
var updateBtn = item._updateBtn;
is_element_visible(updateBtn, "Update button should be visible");
var install = gProvider.installs[0];
var listener = {
onInstallStarted: function() {
info("Install started");
is_element_visible(item._installStatus, "Install progress widget should be visible");
},
onInstallEnded: function() {
install.removeTestListener(this);
info("install ended");
is_element_hidden(item._installStatus, "Install progress widget should be hidden");
run_next_test();
}
};
install.addTestListener(listener);
EventUtils.synthesizeMouseAtCenter(updateBtn, { }, gManagerWindow);
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests manual updates, including the Available Updates pane
var gProvider;
var gManagerWindow;
var gCategoryUtilities;
var gAvailableCategory;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "auto updating addon",
version: "1.0",
applyBackgroundUpdates: AddonManager.AUTOUPDATE_ENABLE
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, function() {
finish();
});
}
add_test(function() {
gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available");
is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden");
gProvider.createAddons([{
id: "addon2@tests.mozilla.org",
name: "manually updating addon",
version: "1.0",
isCompatible: false,
blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED,
applyBackgroundUpdates: AddonManager.AUTOUPDATE_DISABLE
}]);
is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible");
gAvailableCategory.addEventListener("CategoryVisible", function() {
gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should not be visible");
gAvailableCategory.addEventListener("CategoryVisible", function() {
gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should be visible");
run_next_test();
}, false);
gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
}, false);
gProvider.addons[1].applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE;
});
add_test(function() {
gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() {
gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false);
is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1");
run_next_test();
}, false);
gCategoryUtilities.openType("extension", function() {
gProvider.createInstalls([{
name: "manually updating addon (new and improved!)",
existingAddon: gProvider.addons[1],
version: "1.1",
releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null)
}]);
var item = get_addon_element(gManagerWindow, "addon2@tests.mozilla.org");
is(item._version.value, "1.0", "Should still show the old version in the normal list");
});
});
add_test(function() {
wait_for_view_load(gManagerWindow, function() {
is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/available", "Available Updates category should now be selected");
is(gManagerWindow.gViewController.currentViewId, "addons://updates/available", "Available Updates view should be the current view");
run_next_test();
}, true);
EventUtils.synthesizeMouseAtCenter(gAvailableCategory, { }, gManagerWindow);
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
is(list.itemCount, 1, "Should be 1 available update listed");
var item = list.firstChild;
is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon");
// for manual update items, update-related properties are updated asynchronously,
// so we poll for one of the expected changes to know when its done
function waitForAsyncInit() {
if (item._version.value == "1.1") {
run_next_test();
return;
}
info("Update item not initialized yet, checking again in 100ms");
setTimeout(waitForAsyncInit, 100);
}
waitForAsyncInit();
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
var item = list.firstChild;
is(item._version.value, "1.1", "Update item should have version number of the update");
var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix");
is_element_visible(postfix, "'Update' postfix should be visible");
is_element_visible(item._updateAvailable, "");
is_element_visible(item._relNotesToggle, "Release notes toggle should be visible");
is_element_hidden(item._warning, "Incompatible warning should be hidden");
is_element_hidden(item._error, "Blocklist error should be hidden");
info("Opening release notes");
item.addEventListener("RelNotesToggle", function() {
item.removeEventListener("RelNotesToggle", arguments.callee, false);
info("Release notes now open");
is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden");
is_element_visible(item._relNotesError, "Release notes error message should be visible");
is(item._relNotes.childElementCount, 0, "Release notes should be empty");
info("Closing release notes");
item.addEventListener("RelNotesToggle", function() {
item.removeEventListener("RelNotesToggle", arguments.callee, false);
info("Release notes now closed");
info("Setting Release notes URI to something that should load");
gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null)
info("Re-opening release notes");
item.addEventListener("RelNotesToggle", function() {
item.removeEventListener("RelNotesToggle", arguments.callee, false);
info("Release notes now open");
is_element_hidden(item._relNotesLoading, "Release notes loading message should be hidden");
is_element_hidden(item._relNotesError, "Release notes error message should be hidden");
isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container");
run_next_test();
}, false);
EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow);
is_element_visible(item._relNotesLoading, "Release notes loading message should be visible");
}, false);
EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow);
}, false);
EventUtils.synthesizeMouseAtCenter(item._relNotesToggle, { }, gManagerWindow);
is_element_visible(item._relNotesLoading, "Release notes loading message should be visible");
});
add_test(function() {
var list = gManagerWindow.document.getElementById("updates-list");
var item = list.firstChild;
var updateBtn = item._updateBtn;
is_element_visible(updateBtn, "Update button should be visible");
var install = gProvider.installs[0];
var listener = {
onInstallStarted: function() {
info("Install started");
is_element_visible(item._installStatus, "Install progress widget should be visible");
},
onInstallEnded: function() {
install.removeTestListener(this);
info("install ended");
is_element_hidden(item._installStatus, "Install progress widget should be hidden");
run_next_test();
}
};
install.addTestListener(listener);
EventUtils.synthesizeMouseAtCenter(updateBtn, { }, gManagerWindow);
});

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

@ -1,86 +1,86 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests the recent updates pane
var gProvider;
var gManagerWindow;
var gCategoryUtilities;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "updated 6 hours ago",
version: "1.0",
updateDate: new Date(Date.now() - (1000 * 60 * 60 * 6)),
releaseNotesURI: Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null)
}, {
id: "addon2@tests.mozilla.org",
name: "updated 5 seconds ago",
version: "1.0",
updateDate: new Date(Date.now() - (1000 * 5))
}, {
id: "addon3@tests.mozilla.org",
name: "updated 1 month ago",
version: "1.0",
updateDate: new Date(Date.now() - (1000 * 60 * 60 * 25 * 30))
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, function() {
finish();
});
}
add_test(function() {
info("Checking menuitem for Recent Updates opens that pane");
var recentCat = gManagerWindow.gCategories.get("addons://updates/recent");
is(gCategoryUtilities.isVisible(recentCat), false, "Recent Updates category should initially be hidden");
var utilsBtn = gManagerWindow.document.getElementById("header-utils-btn");
utilsBtn.addEventListener("popupshown", function() {
wait_for_view_load(gManagerWindow, function() {
is(gCategoryUtilities.isVisible(recentCat), true, "Recent Updates category should now be visible");
is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/recent", "Recent Updates category should now be selected");
is(gManagerWindow.gViewController.currentViewId, "addons://updates/recent", "Recent Updates view should be the current view");
run_next_test();
}, true);
var menuitem = gManagerWindow.document.getElementById("utils-viewUpdates");
EventUtils.synthesizeMouse(menuitem, 2, 2, { }, gManagerWindow);
}, false);
EventUtils.synthesizeMouse(utilsBtn, 2, 2, { }, gManagerWindow);
});
add_test(function() {
var updatesList = gManagerWindow.document.getElementById("updates-list");
var items = updatesList.getElementsByTagName("richlistitem");
var possible = ["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon2@tests.mozilla.org"];
var expected = ["addon2@tests.mozilla.org", "addon1@tests.mozilla.org"];
for (let i = 0; i < items.length; i++) {
let item = items[i];
let itemId = item.mAddon.id;
if (possible.indexOf(itemId) == -1)
continue; // skip over any other addons, such as shipped addons that would update on every build
isnot(expected.length, 0, "Should be expecting more items");
is(itemId, expected.shift(), "Should get expected item based on recenty of update");
if (itemId == "addon1@tests.mozilla.org")
is_element_visible(item._relNotesToggle, "Release notes toggle should be visible for addon with release notes");
else
is_element_hidden(item._relNotesToggle, "Release notes toggle should be hidden for addon with no release notes");
}
run_next_test();
});
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests the recent updates pane
var gProvider;
var gManagerWindow;
var gCategoryUtilities;
function test() {
waitForExplicitFinish();
gProvider = new MockProvider();
gProvider.createAddons([{
id: "addon1@tests.mozilla.org",
name: "updated 6 hours ago",
version: "1.0",
updateDate: new Date(Date.now() - (1000 * 60 * 60 * 6)),
releaseNotesURI: Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null)
}, {
id: "addon2@tests.mozilla.org",
name: "updated 5 seconds ago",
version: "1.0",
updateDate: new Date(Date.now() - (1000 * 5))
}, {
id: "addon3@tests.mozilla.org",
name: "updated 1 month ago",
version: "1.0",
updateDate: new Date(Date.now() - (1000 * 60 * 60 * 25 * 30))
}]);
open_manager("addons://list/extension", function(aWindow) {
gManagerWindow = aWindow;
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
run_next_test();
});
}
function end_test() {
close_manager(gManagerWindow, function() {
finish();
});
}
add_test(function() {
info("Checking menuitem for Recent Updates opens that pane");
var recentCat = gManagerWindow.gCategories.get("addons://updates/recent");
is(gCategoryUtilities.isVisible(recentCat), false, "Recent Updates category should initially be hidden");
var utilsBtn = gManagerWindow.document.getElementById("header-utils-btn");
utilsBtn.addEventListener("popupshown", function() {
wait_for_view_load(gManagerWindow, function() {
is(gCategoryUtilities.isVisible(recentCat), true, "Recent Updates category should now be visible");
is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/recent", "Recent Updates category should now be selected");
is(gManagerWindow.gViewController.currentViewId, "addons://updates/recent", "Recent Updates view should be the current view");
run_next_test();
}, true);
var menuitem = gManagerWindow.document.getElementById("utils-viewUpdates");
EventUtils.synthesizeMouse(menuitem, 2, 2, { }, gManagerWindow);
}, false);
EventUtils.synthesizeMouse(utilsBtn, 2, 2, { }, gManagerWindow);
});
add_test(function() {
var updatesList = gManagerWindow.document.getElementById("updates-list");
var items = updatesList.getElementsByTagName("richlistitem");
var possible = ["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon2@tests.mozilla.org"];
var expected = ["addon2@tests.mozilla.org", "addon1@tests.mozilla.org"];
for (let i = 0; i < items.length; i++) {
let item = items[i];
let itemId = item.mAddon.id;
if (possible.indexOf(itemId) == -1)
continue; // skip over any other addons, such as shipped addons that would update on every build
isnot(expected.length, 0, "Should be expecting more items");
is(itemId, expected.shift(), "Should get expected item based on recenty of update");
if (itemId == "addon1@tests.mozilla.org")
is_element_visible(item._relNotesToggle, "Release notes toggle should be visible for addon with release notes");
else
is_element_hidden(item._relNotesToggle, "Release notes toggle should be hidden for addon with no release notes");
}
run_next_test();
});

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

@ -393,8 +393,8 @@ CertOverrideListener.prototype = {
},
notifyCertProblem: function (socketInfo, sslStatus, targetHost) {
cert = sslStatus.QueryInterface(Components.interfaces.nsISSLStatus)
.serverCert;
var cert = sslStatus.QueryInterface(Components.interfaces.nsISSLStatus)
.serverCert;
var cos = Cc["@mozilla.org/security/certoverride;1"].
getService(Ci.nsICertOverrideService);
cos.rememberValidityOverride(this.host, -1, cert, this.bits, false);

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

@ -1,15 +1,15 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en-US" dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<h1>OMG, an update!!!!</h1>
<ul>
<li>Made everything more awesome</li>
<li>Added hot sauce</li>
</ul>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en-US" dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<h1>OMG, an update!!!!</h1>
<ul>
<li>Made everything more awesome</li>
<li>Added hot sauce</li>
</ul>
</body>
</html>

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

@ -12,6 +12,10 @@ const Ci = Components.interfaces;
const extDir = gProfD.clone();
extDir.append("extensions");
var gFastLoadService = AM_Cc["@mozilla.org/fast-load-service;1"].
getService(AM_Ci.nsIFastLoadService);
var gFastLoadFile = null;
/**
* Start the test by installing extensions.
*/
@ -27,10 +31,19 @@ function run_test() {
}
}, "startupcache-invalidate", false);
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
gFastLoadFile = gFastLoadService.newFastLoadFile("XUL");
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
startupManager();
// nsAppRunner takes care of clearing this when a new app is installed
do_check_true(gFastLoadFile.exists());
installAllFiles([do_get_addon("test_bug594058")], function() {
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
do_check_true(cachePurged);
cachePurged = false;
@ -47,15 +60,20 @@ function run_test() {
otherFile.lastModifiedTime = pastTime;
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
cachePurged = false;
otherFile.lastModifiedTime = pastTime + 5000;
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
do_check_true(cachePurged);
cachePurged = false;
restartManager();
do_check_true(!cachePurged);
do_check_true(gFastLoadFile.exists());
do_check_false(cachePurged);
do_test_finished();
});

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

@ -85,11 +85,19 @@ registerDirectory("XREUSysExt", userDir.parent);
const profileDir = gProfD.clone();
profileDir.append("extensions");
var gFastLoadService = AM_Cc["@mozilla.org/fast-load-service;1"].
getService(AM_Ci.nsIFastLoadService);
var gFastLoadFile = null;
// Set up the profile
function run_test() {
do_test_pending();
startupManager();
gFastLoadFile = gFastLoadService.newFastLoadFile("XUL");
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
"addon3@tests.mozilla.org",
@ -127,6 +135,9 @@ function run_test_1() {
writeInstallRDFForExtension(addon5, profileDir);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
"addon3@tests.mozilla.org",
@ -203,6 +214,8 @@ function run_test_2() {
dest.remove(true);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -257,6 +270,8 @@ function run_test_3() {
writeInstallRDFForExtension(addon3, profileDir, "addon4@tests.mozilla.org");
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -308,6 +323,8 @@ function run_test_4() {
Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_SYSTEM);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -340,6 +357,8 @@ function run_test_5() {
Services.prefs.setIntPref("extensions.enabledScopes", AddonManager.SCOPE_USER);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -378,6 +397,8 @@ function run_test_6() {
Services.prefs.clearUserPref("extensions.enabledScopes");
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -420,6 +441,8 @@ function run_test_7() {
dest.remove(true);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -467,6 +490,8 @@ function run_test_8() {
Services.prefs.setIntPref("extensions.enabledScopes", 0);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -508,6 +533,8 @@ function run_test_9() {
writeInstallRDFForExtension(addon2, profileDir);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -558,6 +585,8 @@ function run_test_10() {
writeInstallRDFForExtension(addon1, userDir);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",
@ -608,6 +637,8 @@ function run_test_11() {
dest.remove(true);
restartManager();
do_check_false(gFastLoadFile.exists());
gFastLoadFile.create(AM_Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
"addon2@tests.mozilla.org",

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

@ -1,5 +1,7 @@
// ----------------------------------------------------------------------------
// Test whether a request for auth for an XPI switches to the appropriate tab
var gNewTab;
function test() {
Harness.authenticationCallback = get_auth_info;
Harness.downloadFailedCallback = download_failed;

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

@ -27,10 +27,11 @@ function get_item(items, url) {
return items[i];
}
ok(false, "Item for " + url + " was not listed");
return null;
}
function confirm_install(window) {
items = window.document.getElementById("itemList").childNodes;
let items = window.document.getElementById("itemList").childNodes;
is(items.length, 2, "Should be 2 items listed in the confirmation dialog");
let item = get_item(items, TESTROOT + "signed.xpi");
if (item) {

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

@ -16,6 +16,7 @@ function get_item(items, name) {
return items[i];
}
ok(false, "Item for " + name + " was not listed");
return null;
}
function confirm_install(window) {

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