зеркало из https://github.com/mozilla/pjs.git
Merging mozilla-central to Places.
This commit is contained in:
Коммит
9bd9238f38
|
@ -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)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче