Merge TM -> JM

This commit is contained in:
Brian Hackett
2011-05-27 15:08:04 -07:00
488 changed files with 25567 additions and 19173 deletions

View File

@@ -199,23 +199,32 @@ private:
printf("uri: %s", spec); printf("uri: %s", spec);
#define NS_LOG_ACCDOC_TYPE(aDocument) \ #define NS_LOG_ACCDOC_TYPE(aDocument) \
PRBool isContent = nsCoreUtils::IsContentDocument(aDocument); \ if (aDocument->IsActive()) { \
printf("%s document", (isContent ? "content" : "chrome")); PRBool isContent = nsCoreUtils::IsContentDocument(aDocument); \
printf("%s document", (isContent ? "content" : "chrome")); \
} else { \
printf("document type: [failed]"); \
}
#define NS_LOG_ACCDOC_SHELLSTATE(aDocument) \ #define NS_LOG_ACCDOC_SHELLSTATE(aDocument) \
nsCOMPtr<nsISupports> container = aDocument->GetContainer(); \
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container); \
PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; \
docShell->GetBusyFlags(&busyFlags); \
nsCAutoString docShellBusy; \ nsCAutoString docShellBusy; \
if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) \ nsCOMPtr<nsISupports> container = aDocument->GetContainer(); \
docShellBusy.AppendLiteral("'none'"); \ if (container) { \
if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) \ nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container); \
docShellBusy.AppendLiteral("'busy'"); \ PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; \
if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) \ docShell->GetBusyFlags(&busyFlags); \
docShellBusy.AppendLiteral(", 'before page load'"); \ if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) \
if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) \ docShellBusy.AppendLiteral("'none'"); \
docShellBusy.AppendLiteral(", 'page loading'"); \ if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) \
docShellBusy.AppendLiteral("'busy'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) \
docShellBusy.AppendLiteral(", 'before page load'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) \
docShellBusy.AppendLiteral(", 'page loading'"); \
} \
else { \
docShellBusy.AppendLiteral("[failed]"); \
} \
printf("docshell busy: %s", docShellBusy.get()); printf("docshell busy: %s", docShellBusy.get());
#define NS_LOG_ACCDOC_DOCSTATES(aDocument) \ #define NS_LOG_ACCDOC_DOCSTATES(aDocument) \
@@ -336,20 +345,22 @@ private:
printf(" "); \ printf(" "); \
NS_LOG_ACCDOC_ADDRESS(aDocument, aDocAcc) \ NS_LOG_ACCDOC_ADDRESS(aDocument, aDocAcc) \
printf("\n "); \ printf("\n "); \
NS_LOG_ACCDOC_URI(aDocument) \ if (aDocument) { \
printf("\n "); \ NS_LOG_ACCDOC_URI(aDocument) \
NS_LOG_ACCDOC_SHELLSTATE(aDocument) \ printf("\n "); \
printf("; "); \ NS_LOG_ACCDOC_SHELLSTATE(aDocument) \
NS_LOG_ACCDOC_TYPE(aDocument) \ printf("; "); \
printf("\n "); \ NS_LOG_ACCDOC_TYPE(aDocument) \
NS_LOG_ACCDOC_DOCSTATES(aDocument) \ printf("\n "); \
printf("\n "); \ NS_LOG_ACCDOC_DOCSTATES(aDocument) \
NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \ printf("\n "); \
printf("\n "); \ NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \
NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \ printf("\n "); \
printf(", "); \ NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \
NS_LOG_ACCDOC_DOCPARENT(aDocument) \ printf(", "); \
printf("\n"); \ NS_LOG_ACCDOC_DOCPARENT(aDocument) \
printf("\n"); \
} \
} }
#define NS_LOG_ACCDOC_DOCINFO_END \ #define NS_LOG_ACCDOC_DOCINFO_END \
printf(" }\n"); printf(" }\n");

View File

@@ -160,7 +160,8 @@ nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIContent *aContent,
control->GetItemAtIndex(index, getter_AddRefs(currItem)); control->GetItemAtIndex(index, getter_AddRefs(currItem));
nsCOMPtr<nsINode> currNode(do_QueryInterface(currItem)); nsCOMPtr<nsINode> currNode(do_QueryInterface(currItem));
nsAccessible* itemAcc = GetAccService()->GetAccessible(currNode); nsAccessible* itemAcc = currNode ?
GetAccService()->GetAccessible(currNode) : nsnull;
if (!itemAcc || itemAcc->State() & states::INVISIBLE) { if (!itemAcc || itemAcc->State() & states::INVISIBLE) {
(*aSetSize)--; (*aSetSize)--;
@@ -201,7 +202,8 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
container->GetItemAtIndex(index, getter_AddRefs(item)); container->GetItemAtIndex(index, getter_AddRefs(item));
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item)); nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
nsAccessible* itemAcc = GetAccService()->GetAccessible(itemNode); nsAccessible* itemAcc = itemNode ?
GetAccService()->GetAccessible(itemNode) : nsnull;
if (itemAcc) { if (itemAcc) {
PRUint32 itemRole = Role(itemAcc); PRUint32 itemRole = Role(itemAcc);
@@ -220,8 +222,9 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
nsCOMPtr<nsIDOMXULElement> item; nsCOMPtr<nsIDOMXULElement> item;
container->GetItemAtIndex(index, getter_AddRefs(item)); container->GetItemAtIndex(index, getter_AddRefs(item));
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item)); nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
nsAccessible* itemAcc = GetAccService()->GetAccessible(itemNode); nsAccessible* itemAcc =
itemNode ? GetAccService()->GetAccessible(itemNode) : nsnull;
if (itemAcc) { if (itemAcc) {
PRUint32 itemRole = Role(itemAcc); PRUint32 itemRole = Role(itemAcc);

View File

@@ -842,6 +842,8 @@ nsAccessibilityService::GetAccessibleInShell(nsINode* aNode,
nsAccessible* nsAccessible*
nsAccessibilityService::GetAccessible(nsINode* aNode) nsAccessibilityService::GetAccessible(nsINode* aNode)
{ {
NS_PRECONDITION(aNode, "Getting an accessible for null node! Crash.");
nsDocAccessible* document = GetDocAccessible(aNode->GetOwnerDoc()); nsDocAccessible* document = GetDocAccessible(aNode->GetOwnerDoc());
return document ? document->GetAccessible(aNode) : nsnull; return document ? document->GetAccessible(aNode) : nsnull;
} }

View File

@@ -93,7 +93,7 @@ nsLeafAccessible::CacheChildren()
nsLinkableAccessible:: nsLinkableAccessible::
nsLinkableAccessible(nsIContent *aContent, nsIWeakReference *aShell) : nsLinkableAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
nsAccessibleWrap(aContent, aShell), nsAccessibleWrap(aContent, aShell),
mActionContent(nsnull), mActionAcc(nsnull),
mIsLink(PR_FALSE), mIsLink(PR_FALSE),
mIsOnclick(PR_FALSE) mIsOnclick(PR_FALSE)
{ {
@@ -107,11 +107,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsAccessibleWrap)
NS_IMETHODIMP NS_IMETHODIMP
nsLinkableAccessible::TakeFocus() nsLinkableAccessible::TakeFocus()
{ {
nsAccessible *actionAcc = GetActionAccessible(); return mActionAcc ? mActionAcc->TakeFocus() : nsAccessibleWrap::TakeFocus();
if (actionAcc)
return actionAcc->TakeFocus();
return nsAccessibleWrap::TakeFocus();
} }
PRUint64 PRUint64
@@ -120,8 +116,7 @@ nsLinkableAccessible::NativeState()
PRUint64 states = nsAccessibleWrap::NativeState(); PRUint64 states = nsAccessibleWrap::NativeState();
if (mIsLink) { if (mIsLink) {
states |= states::LINKED; states |= states::LINKED;
nsAccessible* actionAcc = GetActionAccessible(); if (mActionAcc->State() & states::TRAVERSED)
if (actionAcc->State() & states::TRAVERSED)
states |= states::TRAVERSED; states |= states::TRAVERSED;
} }
@@ -137,13 +132,7 @@ nsLinkableAccessible::GetValue(nsAString& aValue)
if (!aValue.IsEmpty()) if (!aValue.IsEmpty())
return NS_OK; return NS_OK;
if (mIsLink) { return mIsLink ? mActionAcc->GetValue(aValue) : NS_ERROR_NOT_IMPLEMENTED;
nsAccessible *actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->GetValue(aValue);
}
return NS_ERROR_NOT_IMPLEMENTED;
} }
@@ -152,7 +141,7 @@ nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
{ {
NS_ENSURE_ARG_POINTER(aNumActions); NS_ENSURE_ARG_POINTER(aNumActions);
*aNumActions = mActionContent ? 1 : 0; *aNumActions = mActionAcc ? 1 : 0;
return NS_OK; return NS_OK;
} }
@@ -182,11 +171,8 @@ nsLinkableAccessible::DoAction(PRUint8 aIndex)
if (aIndex != eAction_Jump) if (aIndex != eAction_Jump)
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
nsAccessible *actionAcc = GetActionAccessible(); return mActionAcc ? mActionAcc->DoAction(aIndex) :
if (actionAcc) nsAccessibleWrap::DoAction(aIndex);
return actionAcc->DoAction(aIndex);
return nsAccessibleWrap::DoAction(aIndex);
} }
NS_IMETHODIMP NS_IMETHODIMP
@@ -194,11 +180,8 @@ nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
{ {
aKeyboardShortcut.Truncate(); aKeyboardShortcut.Truncate();
nsAccessible *actionAcc = GetActionAccessible(); return mActionAcc ? mActionAcc->GetKeyboardShortcut(aKeyboardShortcut) :
if (actionAcc) nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
return actionAcc->GetKeyboardShortcut(aKeyboardShortcut);
return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -207,7 +190,9 @@ nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
void void
nsLinkableAccessible::Shutdown() nsLinkableAccessible::Shutdown()
{ {
mActionContent = nsnull; mIsLink = PR_FALSE;
mIsOnclick = PR_FALSE;
mActionAcc = nsnull;
nsAccessibleWrap::Shutdown(); nsAccessibleWrap::Shutdown();
} }
@@ -218,14 +203,11 @@ already_AddRefed<nsIURI>
nsLinkableAccessible::GetAnchorURI(PRUint32 aAnchorIndex) nsLinkableAccessible::GetAnchorURI(PRUint32 aAnchorIndex)
{ {
if (mIsLink) { if (mIsLink) {
nsAccessible* link = GetActionAccessible(); NS_ASSERTION(mActionAcc->IsHyperLink(),
if (link) { "nsIAccessibleHyperLink isn't implemented.");
NS_ASSERTION(link->IsHyperLink(),
"nsIAccessibleHyperLink isn't implemented.");
if (link->IsHyperLink()) if (mActionAcc->IsHyperLink())
return link->GetAnchorURI(aAnchorIndex); return mActionAcc->GetAnchorURI(aAnchorIndex);
}
} }
return nsnull; return nsnull;
@@ -241,55 +223,36 @@ nsLinkableAccessible::BindToParent(nsAccessible* aParent,
nsAccessibleWrap::BindToParent(aParent, aIndexInParent); nsAccessibleWrap::BindToParent(aParent, aIndexInParent);
// Cache action content. // Cache action content.
mActionContent = nsnull; mActionAcc = nsnull;
mIsLink = PR_FALSE; mIsLink = PR_FALSE;
mIsOnclick = PR_FALSE; mIsOnclick = PR_FALSE;
nsIContent* walkUpContent = mContent; if (nsCoreUtils::HasClickListener(mContent)) {
PRBool isOnclick = nsCoreUtils::HasClickListener(walkUpContent); mActionAcc = this;
if (isOnclick) {
mActionContent = walkUpContent;
mIsOnclick = PR_TRUE; mIsOnclick = PR_TRUE;
return; return;
} }
while ((walkUpContent = walkUpContent->GetParent())) { // XXX: The logic looks broken since the click listener may be registered
nsAccessible* walkUpAcc = // on non accessible node in parent chain but this node is skipped when tree
GetAccService()->GetAccessibleInWeakShell(walkUpContent, mWeakShell); // is traversed.
nsAccessible* walkUpAcc = this;
while ((walkUpAcc = walkUpAcc->GetParent()) && !walkUpAcc->IsDoc()) {
if (walkUpAcc && walkUpAcc->Role() == nsIAccessibleRole::ROLE_LINK && if (walkUpAcc && walkUpAcc->Role() == nsIAccessibleRole::ROLE_LINK &&
walkUpAcc->State() & states::LINKED) { walkUpAcc->State() & states::LINKED) {
mIsLink = PR_TRUE; mIsLink = PR_TRUE;
mActionContent = walkUpContent; mActionAcc = walkUpAcc;
return; return;
} }
isOnclick = nsCoreUtils::HasClickListener(walkUpContent); if (nsCoreUtils::HasClickListener(walkUpAcc->GetContent())) {
if (isOnclick) { mActionAcc = walkUpAcc;
mActionContent = walkUpContent;
mIsOnclick = PR_TRUE; mIsOnclick = PR_TRUE;
return; return;
} }
} }
} }
////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible: protected
nsAccessible *
nsLinkableAccessible::GetActionAccessible() const
{
// Return accessible for the action content if it's different from node of
// this accessible. If the action accessible is not null then it is used to
// redirect methods calls otherwise we use method implementation from the
// base class.
if (!mActionContent || mContent == mActionContent)
return nsnull;
return GetAccService()->GetAccessibleInWeakShell(mActionContent, mWeakShell);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// nsEnumRoleAccessible // nsEnumRoleAccessible
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -108,14 +108,10 @@ protected:
// nsAccessible // nsAccessible
virtual void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent); virtual void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
// nsLinkableAccessible
/** /**
* Return an accessible for cached action node. * Parent accessible that provides an action for this linkable accessible.
*/ */
nsAccessible *GetActionAccessible() const; nsAccessible* mActionAcc;
nsCOMPtr<nsIContent> mActionContent;
PRPackedBool mIsLink; PRPackedBool mIsLink;
PRPackedBool mIsOnclick; PRPackedBool mIsOnclick;
}; };

View File

@@ -493,12 +493,10 @@ nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
nsCAutoString path; nsCAutoString path;
uri->GetPath(path); uri->GetPath(path);
nsCAutoString::const_iterator start, end;
path.BeginReading(start);
path.EndReading(end);
NS_NAMED_LITERAL_CSTRING(neterror, "neterror"); NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
return FindInReadable(neterror, start, end); NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
} }
PRBool PRBool

View File

@@ -213,8 +213,8 @@ nsOuterDocAccessible::RemoveChild(nsAccessible *aAccessible)
return PR_FALSE; return PR_FALSE;
} }
NS_LOG_ACCDOCDESTROY("remove document from outerdoc", NS_LOG_ACCDOCDESTROY_FOR("remove document from outerdoc",
child->GetDocumentNode()) child->GetDocumentNode(), child)
NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this) NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this)
PRBool wasRemoved = nsAccessible::RemoveChild(child); PRBool wasRemoved = nsAccessible::RemoveChild(child);

View File

@@ -1014,7 +1014,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
} }
if (aType == eGetBefore) { if (aType == eGetBefore) {
endOffset = aOffset; finalEndOffset = aOffset;
} }
else { else {
// Start moving forward from the start so that we don't get // Start moving forward from the start so that we don't get

View File

@@ -192,11 +192,11 @@
/** /**
* Load wrong URI what results in error page loading. * Load wrong URI what results in error page loading.
*/ */
function loadErrorPageInvoker() function loadErrorPageInvoker(aURL, aURLDescr)
{ {
this.invoke = function loadErrorPageInvoker_invoke() this.invoke = function loadErrorPageInvoker_invoke()
{ {
gTabBrowser.loadURI("www.wronguri.wronguri"); gTabBrowser.loadURI(aURL);
} }
this.eventSeq = [ this.eventSeq = [
@@ -209,7 +209,7 @@
this.getID = function loadErrorPageInvoker_getID() this.getID = function loadErrorPageInvoker_getID()
{ {
return "load error page"; return "load error page: '" + aURLDescr + "'";
} }
} }
@@ -230,7 +230,11 @@
gQueue.push(new clickReloadBtnInvoker()); gQueue.push(new clickReloadBtnInvoker());
gQueue.push(new loadURIInvoker("about:mozilla")); gQueue.push(new loadURIInvoker("about:mozilla"));
gQueue.push(new reloadInvoker()); gQueue.push(new reloadInvoker());
gQueue.push(new loadErrorPageInvoker()); gQueue.push(new loadErrorPageInvoker("www.wronguri.wronguri",
"Server not found"));
gQueue.push(new loadErrorPageInvoker("https://nocert.example.com:443",
"Untrusted Connection"));
gQueue.onFinish = function() { window.close(); } gQueue.onFinish = function() { window.close(); }
gQueue.invoke(); gQueue.invoke();
} }

View File

@@ -50,8 +50,8 @@ _TEST_FILES = \
test_doc.html \ test_doc.html \
test_hypertext.html \ test_hypertext.html \
test_passwords.html \ test_passwords.html \
$(warning test_singleline.html disabled due to bug 652459) \ test_singleline.html \
$(warning test_whitespaces.html disabled due to bug 652459) \ test_whitespaces.html \
test_words.html \ test_words.html \
$(NULL) $(NULL)

View File

@@ -216,10 +216,10 @@
// BOUNDARY_WORD_START // BOUNDARY_WORD_START
testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0, testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0, testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo, "div", kTodo, kOk, kTodo,
@@ -231,10 +231,10 @@
"editable", kTodo, kOk, kTodo, "editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo); "textarea", kTodo, kOk, kTodo);
testTextBeforeOffset(6, BOUNDARY_WORD_START, "hello ", 0, 6, testTextBeforeOffset(6, BOUNDARY_WORD_START, "hello ", 0, 6,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(7, BOUNDARY_WORD_START, "hello ", 0, 6, testTextBeforeOffset(7, BOUNDARY_WORD_START, "hello ", 0, 6,
"input", kTodo, kTodo, kTodo, "input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo, "div", kTodo, kTodo, kTodo,
@@ -246,10 +246,10 @@
"editable", kTodo, kTodo, kTodo, "editable", kTodo, kTodo, kTodo,
"textarea", kTodo, kTodo, kTodo); "textarea", kTodo, kTodo, kTodo);
testTextBeforeOffset(9, BOUNDARY_WORD_START, "my ", 6, 9, testTextBeforeOffset(9, BOUNDARY_WORD_START, "my ", 6, 9,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(10, BOUNDARY_WORD_START, "my ", 6, 9, testTextBeforeOffset(10, BOUNDARY_WORD_START, "my ", 6, 9,
"input", kTodo, kTodo, kTodo, "input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo, "div", kTodo, kTodo, kTodo,
@@ -268,10 +268,10 @@
// BOUNDARY_WORD_END // BOUNDARY_WORD_END
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0, testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0, testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo, "div", kTodo, kOk, kTodo,
@@ -283,10 +283,10 @@
"editable", kTodo, kOk, kTodo, "editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo); "textarea", kTodo, kOk, kTodo);
testTextBeforeOffset(6, BOUNDARY_WORD_END, "hello ", 0, 6, testTextBeforeOffset(6, BOUNDARY_WORD_END, "hello ", 0, 6,
"input", kTodo, kTodo, kTodo, "input", kTodo, kTodo, kOk,
"div", kTodo, kTodo, kTodo, "div", kTodo, kTodo, kOk,
"editable", kTodo, kTodo, kTodo, "editable", kTodo, kTodo, kOk,
"textarea", kTodo, kTodo, kTodo); "textarea", kTodo, kTodo, kOk);
testTextBeforeOffset(7, BOUNDARY_WORD_END, "hello ", 0, 6, testTextBeforeOffset(7, BOUNDARY_WORD_END, "hello ", 0, 6,
"input", kTodo, kTodo, kTodo, "input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo, "div", kTodo, kTodo, kTodo,
@@ -320,10 +320,10 @@
// BOUNDARY_LINE_START // BOUNDARY_LINE_START
testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0, testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_LINE_START, "", 0, 0, testTextBeforeOffset(1, BOUNDARY_LINE_START, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo, "div", kTodo, kOk, kTodo,
@@ -342,10 +342,10 @@
// BOUNDARY_LINE_END // BOUNDARY_LINE_END
testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0, testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0, testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo, "div", kTodo, kOk, kTodo,

View File

@@ -196,10 +196,10 @@
// BOUNDARY_WORD_START // BOUNDARY_WORD_START
testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0, testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0, testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo, "div", kTodo, kOk, kTodo,
@@ -211,10 +211,10 @@
"editable", kTodo, kOk, kTodo, "editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo); "textarea", kTodo, kOk, kTodo);
testTextBeforeOffset(6, BOUNDARY_WORD_START, "Brave ", 0, 6, testTextBeforeOffset(6, BOUNDARY_WORD_START, "Brave ", 0, 6,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(9, BOUNDARY_WORD_START, "Brave ", 0, 6, testTextBeforeOffset(9, BOUNDARY_WORD_START, "Brave ", 0, 6,
"input", kTodo, kTodo, kTodo, "input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo, "div", kTodo, kTodo, kTodo,
@@ -226,10 +226,10 @@
"editable", kTodo, kTodo, kTodo, "editable", kTodo, kTodo, kTodo,
"textarea", kTodo, kTodo, kTodo); "textarea", kTodo, kTodo, kTodo);
testTextBeforeOffset(11, BOUNDARY_WORD_START, "Sir ", 6, 11, testTextBeforeOffset(11, BOUNDARY_WORD_START, "Sir ", 6, 11,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(15, BOUNDARY_WORD_START, "Sir ", 6, 11, testTextBeforeOffset(15, BOUNDARY_WORD_START, "Sir ", 6, 11,
"input", kTodo, kTodo, kTodo, "input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo, "div", kTodo, kTodo, kTodo,
@@ -251,10 +251,10 @@
"editable", kTodo, kTodo, kTodo, "editable", kTodo, kTodo, kTodo,
"textarea", kTodo, kTodo, kTodo); "textarea", kTodo, kTodo, kTodo);
testTextBeforeOffset(19, BOUNDARY_WORD_START, "Robin ", 11, 19, testTextBeforeOffset(19, BOUNDARY_WORD_START, "Robin ", 11, 19,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(20, BOUNDARY_WORD_START, "Robin ", 11, 19, testTextBeforeOffset(20, BOUNDARY_WORD_START, "Robin ", 11, 19,
"input", kTodo, kTodo, kTodo, "input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo, "div", kTodo, kTodo, kTodo,
@@ -268,10 +268,10 @@
// BOUNDARY_WORD_END // BOUNDARY_WORD_END
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0, testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kOk, kOk, kOk,
"div", kTodo, kOk, kTodo, "div", kOk, kOk, kOk,
"editable", kTodo, kOk, kTodo, "editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo); "textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0, testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo, "input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo, "div", kTodo, kOk, kTodo,

View File

@@ -1005,6 +1005,19 @@ pref("devtools.chrome.enabled", false);
// Change to -1 if you do not want the Web Console to remember its last height. // Change to -1 if you do not want the Web Console to remember its last height.
pref("devtools.hud.height", 0); pref("devtools.hud.height", 0);
// Remember the Web Console position. Possible values:
// above - above the web page,
// below - below the web page,
// window - in a separate window/popup panel.
pref("devtools.webconsole.position", "above");
// The number of lines that are displayed in the web console for the Net,
// CSS, JS and Web Developer categories.
pref("devtools.hud.loglimit.network", 200);
pref("devtools.hud.loglimit.cssparser", 200);
pref("devtools.hud.loglimit.exception", 200);
pref("devtools.hud.loglimit.console", 200);
// Whether the character encoding menu is under the main Firefox button. This // Whether the character encoding menu is under the main Firefox button. This
// preference is a string so that localizers can alter it. // preference is a string so that localizers can alter it.
pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties"); pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");

View File

@@ -462,7 +462,6 @@ statuspanel {
margin-top: -3em; margin-top: -3em;
left: 0; left: 0;
max-width: 50%; max-width: 50%;
-moz-transition: opacity 100ms ease-out;
} }
statuspanel:-moz-locale-dir(ltr)[mirror], statuspanel:-moz-locale-dir(ltr)[mirror],
@@ -482,6 +481,7 @@ statuspanel[type=status] {
} }
statuspanel[type=overLink] { statuspanel[type=overLink] {
-moz-transition: opacity 100ms ease-out;
direction: ltr; direction: ltr;
} }

View File

@@ -1385,7 +1385,7 @@ function prepareForStartup() {
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true); gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
#ifdef XP_MACOSX #ifdef XP_MACOSX
gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true); gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true);
#endif #endif
Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false); Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
@@ -6698,12 +6698,15 @@ var gPluginHandler = {
handleEvent : function(event) { handleEvent : function(event) {
let self = gPluginHandler; let self = gPluginHandler;
let plugin = event.target; let plugin = event.target;
let hideBarPrefName; let doc = plugin.ownerDocument;
// We're expecting the target to be a plugin. // We're expecting the target to be a plugin.
if (!(plugin instanceof Ci.nsIObjectLoadingContent)) if (!(plugin instanceof Ci.nsIObjectLoadingContent))
return; return;
// Force a style flush, so that we ensure our binding is attached.
plugin.clientTop;
switch (event.type) { switch (event.type) {
case "PluginCrashed": case "PluginCrashed":
self.pluginInstanceCrashed(plugin, event); self.pluginInstanceCrashed(plugin, event);
@@ -6713,32 +6716,38 @@ var gPluginHandler = {
// For non-object plugin tags, register a click handler to install the // For non-object plugin tags, register a click handler to install the
// plugin. Object tags can, and often do, deal with that themselves, // plugin. Object tags can, and often do, deal with that themselves,
// so don't stomp on the page developers toes. // so don't stomp on the page developers toes.
if (!(plugin instanceof HTMLObjectElement)) if (!(plugin instanceof HTMLObjectElement)) {
self.addLinkClickCallback(plugin, "installSinglePlugin"); // We don't yet check to see if there's actually an installer available.
let installStatus = doc.getAnonymousElementByAttribute(plugin, "class", "installStatus");
installStatus.setAttribute("status", "ready");
let iconStatus = doc.getAnonymousElementByAttribute(plugin, "class", "icon");
iconStatus.setAttribute("status", "ready");
let installLink = doc.getAnonymousElementByAttribute(plugin, "class", "installPluginLink");
self.addLinkClickCallback(installLink, "installSinglePlugin", plugin);
}
/* FALLTHRU */ /* FALLTHRU */
case "PluginBlocklisted": case "PluginBlocklisted":
case "PluginOutdated": case "PluginOutdated":
hideBarPrefName = event.type == "PluginOutdated" ?
"plugins.hide_infobar_for_outdated_plugin" :
"plugins.hide_infobar_for_missing_plugin";
if (gPrefService.getBoolPref(hideBarPrefName))
return;
self.pluginUnavailable(plugin, event.type);
break;
#ifdef XP_MACOSX #ifdef XP_MACOSX
case "npapi-carbon-event-model-failure": case "npapi-carbon-event-model-failure":
hideBarPrefName = "plugins.hide_infobar_for_carbon_failure_plugin"; #endif
if (gPrefService.getBoolPref(hideBarPrefName))
return;
self.pluginUnavailable(plugin, event.type); self.pluginUnavailable(plugin, event.type);
break; break;
#endif
case "PluginDisabled": case "PluginDisabled":
self.addLinkClickCallback(plugin, "managePlugins"); let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
self.addLinkClickCallback(manageLink, "managePlugins");
break; break;
} }
// Hide the in-content UI if it's too big. The crashed plugin handler already did this.
if (event.type != "PluginCrashed") {
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
if (self.isTooSmall(plugin, overlay))
overlay.style.visibility = "hidden";
}
}, },
newPluginInstalled : function(event) { newPluginInstalled : function(event) {
@@ -6757,10 +6766,10 @@ var gPluginHandler = {
}, },
// Callback for user clicking on a missing (unsupported) plugin. // Callback for user clicking on a missing (unsupported) plugin.
installSinglePlugin: function (aEvent) { installSinglePlugin: function (plugin) {
var missingPluginsArray = {}; var missingPluginsArray = {};
var pluginInfo = getPluginInfo(aEvent.target); var pluginInfo = getPluginInfo(plugin);
missingPluginsArray[pluginInfo.mimetype] = pluginInfo; missingPluginsArray[pluginInfo.mimetype] = pluginInfo;
openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul", openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
@@ -6810,9 +6819,6 @@ var gPluginHandler = {
let blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins"); let blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins");
let missingNotification = notificationBox.getNotificationWithValue("missing-plugins"); let missingNotification = notificationBox.getNotificationWithValue("missing-plugins");
// If there is already an outdated plugin notification then do nothing
if (outdatedNotification)
return;
function showBlocklistInfo() { function showBlocklistInfo() {
var url = formatURL("extensions.blocklist.detailsURL", true); var url = formatURL("extensions.blocklist.detailsURL", true);
@@ -6844,7 +6850,7 @@ var gPluginHandler = {
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]. let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
createInstance(Ci.nsISupportsPRBool); createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null); Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null);
// Something aborted the quit process. // Something aborted the quit process.
if (cancelQuit.data) if (cancelQuit.data)
return; return;
@@ -6908,10 +6914,17 @@ var gPluginHandler = {
} }
#endif #endif
}; };
// If there is already an outdated plugin notification then do nothing
if (outdatedNotification)
return;
#ifdef XP_MACOSX #ifdef XP_MACOSX
if (eventType == "npapi-carbon-event-model-failure") { if (eventType == "npapi-carbon-event-model-failure") {
if (gPrefService.getBoolPref("plugins.hide_infobar_for_carbon_failure_plugin"))
return;
let carbonFailureNotification = let carbonFailureNotification =
notificationBox.getNotificationWithValue("carbon-failure-plugins"); notificationBox.getNotificationWithValue("carbon-failure-plugins");
if (carbonFailureNotification) if (carbonFailureNotification)
@@ -6923,11 +6936,18 @@ var gPluginHandler = {
eventType = "PluginNotFound"; eventType = "PluginNotFound";
} }
#endif #endif
if (eventType == "PluginBlocklisted") { if (eventType == "PluginBlocklisted") {
if (gPrefService.getBoolPref("plugins.hide_infobar_for_missing_plugin")) // XXX add a new pref?
return;
if (blockedNotification || missingNotification) if (blockedNotification || missingNotification)
return; return;
} }
else if (eventType == "PluginOutdated") { else if (eventType == "PluginOutdated") {
if (gPrefService.getBoolPref("plugins.hide_infobar_for_outdated_plugin"))
return;
// Cancel any notification about blocklisting/missing plugins // Cancel any notification about blocklisting/missing plugins
if (blockedNotification) if (blockedNotification)
blockedNotification.close(); blockedNotification.close();
@@ -6935,6 +6955,9 @@ var gPluginHandler = {
missingNotification.close(); missingNotification.close();
} }
else if (eventType == "PluginNotFound") { else if (eventType == "PluginNotFound") {
if (gPrefService.getBoolPref("plugins.hide_infobar_for_missing_plugin"))
return;
if (missingNotification) if (missingNotification)
return; return;
@@ -6990,9 +7013,6 @@ var gPluginHandler = {
// Remap the plugin name to a more user-presentable form. // Remap the plugin name to a more user-presentable form.
pluginName = this.makeNicePluginName(pluginName, pluginFilename); pluginName = this.makeNicePluginName(pluginName, pluginFilename);
// Force a style flush, so that we ensure our binding is attached.
plugin.clientTop;
let messageString = gNavigatorBundle.getFormattedString("crashedpluginsMessage.title", [pluginName]); let messageString = gNavigatorBundle.getFormattedString("crashedpluginsMessage.title", [pluginName]);
// //
@@ -7000,12 +7020,6 @@ var gPluginHandler = {
// //
let doc = plugin.ownerDocument; let doc = plugin.ownerDocument;
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox"); let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
// The binding has role="link" here, since missing/disabled/blocked
// plugin UI has a onclick handler on the whole thing. This isn't needed
// for the plugin-crashed UI, because we use actual HTML links in the text.
overlay.removeAttribute("role");
let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus"); let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
let status; let status;

View File

@@ -58,7 +58,7 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource:///modules/PropertyPanel.jsm"); Cu.import("resource:///modules/PropertyPanel.jsm");
const SCRATCHPAD_CONTEXT_CONTENT = 1; const SCRATCHPAD_CONTEXT_CONTENT = 1;
const SCRATCHPAD_CONTEXT_CHROME = 2; const SCRATCHPAD_CONTEXT_BROWSER = 2;
const SCRATCHPAD_WINDOW_URL = "chrome://browser/content/scratchpad.xul"; const SCRATCHPAD_WINDOW_URL = "chrome://browser/content/scratchpad.xul";
const SCRATCHPAD_L10N = "chrome://browser/locale/scratchpad.properties"; const SCRATCHPAD_L10N = "chrome://browser/locale/scratchpad.properties";
const SCRATCHPAD_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no"; const SCRATCHPAD_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
@@ -75,7 +75,7 @@ var Scratchpad = {
* Possible values: * Possible values:
* - SCRATCHPAD_CONTEXT_CONTENT to execute code in the context of the current * - SCRATCHPAD_CONTEXT_CONTENT to execute code in the context of the current
* tab content window object. * tab content window object.
* - SCRATCHPAD_CONTEXT_CHROME to execute code in the context of the * - SCRATCHPAD_CONTEXT_BROWSER to execute code in the context of the
* currently active chrome window object. * currently active chrome window object.
*/ */
executionContext: SCRATCHPAD_CONTEXT_CONTENT, executionContext: SCRATCHPAD_CONTEXT_CONTENT,
@@ -121,6 +121,11 @@ var Scratchpad = {
return recentWin ? recentWin.gBrowser : null; return recentWin ? recentWin.gBrowser : null;
}, },
insertIntro: function SP_insertIntro()
{
this.textbox.value = this.strings.GetStringFromName("scratchpadIntro");
},
/** /**
* Cached Cu.Sandbox object for the active tab content window object. * Cached Cu.Sandbox object for the active tab content window object.
*/ */
@@ -129,8 +134,9 @@ var Scratchpad = {
/** /**
* Get the Cu.Sandbox object for the active tab content window object. Note * Get the Cu.Sandbox object for the active tab content window object. Note
* that the returned object is cached for later reuse. The cached object is * that the returned object is cached for later reuse. The cached object is
* kept only for the current browser window and it is reset for each context * kept only for the current location in the current tab of the current
* switch or navigator:browser window switch. * browser window and it is reset for each context switch,
* navigator:browser window switch, tab switch or navigation.
*/ */
get contentSandbox() get contentSandbox()
{ {
@@ -141,12 +147,16 @@ var Scratchpad = {
} }
if (!this._contentSandbox || if (!this._contentSandbox ||
this.browserWindow != this._previousBrowserWindow) { this.browserWindow != this._previousBrowserWindow ||
this._previousBrowser != this.gBrowser.selectedBrowser ||
this._previousLocation != this.gBrowser.contentWindow.location.href) {
let contentWindow = this.gBrowser.selectedBrowser.contentWindow; let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
this._contentSandbox = new Cu.Sandbox(contentWindow, this._contentSandbox = new Cu.Sandbox(contentWindow,
{ sandboxPrototype: contentWindow, wantXrays: false }); { sandboxPrototype: contentWindow, wantXrays: false });
this._previousBrowserWindow = this.browserWindow; this._previousBrowserWindow = this.browserWindow;
this._previousBrowser = this.gBrowser.selectedBrowser;
this._previousLocation = contentWindow.location.href;
} }
return this._contentSandbox; return this._contentSandbox;
@@ -283,7 +293,7 @@ var Scratchpad = {
* Execute the selected text (if any) or the entire textbox content in the * Execute the selected text (if any) or the entire textbox content in the
* current context. * current context.
*/ */
execute: function SP_execute() run: function SP_run()
{ {
let selection = this.selectedText || this.textbox.value; let selection = this.selectedText || this.textbox.value;
let result = this.evalForContext(selection); let result = this.evalForContext(selection);
@@ -298,7 +308,7 @@ var Scratchpad = {
*/ */
inspect: function SP_inspect() inspect: function SP_inspect()
{ {
let [selection, result] = this.execute(); let [selection, result] = this.run();
if (result) { if (result) {
this.openPropertyPanel(selection, result); this.openPropertyPanel(selection, result);
@@ -307,11 +317,11 @@ var Scratchpad = {
/** /**
* Execute the selected text (if any) or the entire textbox content in the * Execute the selected text (if any) or the entire textbox content in the
* current context. The evaluation result is "printed" in the textbox after * current context. The evaluation result is inserted into the textbox after
* the selected text, or at the end of the textbox value if there is no * the selected text, or at the end of the textbox value if there is no
* selected text. * selected text.
*/ */
print: function SP_print() display: function SP_display()
{ {
let selectionStart = this.textbox.selectionStart; let selectionStart = this.textbox.selectionStart;
let selectionEnd = this.textbox.selectionEnd; let selectionEnd = this.textbox.selectionEnd;
@@ -319,7 +329,7 @@ var Scratchpad = {
selectionEnd = this.textbox.value.length; selectionEnd = this.textbox.value.length;
} }
let [selection, result] = this.execute(); let [selection, result] = this.run();
if (!result) { if (!result) {
return; return;
} }
@@ -556,23 +566,23 @@ var Scratchpad = {
setContentContext: function SP_setContentContext() setContentContext: function SP_setContentContext()
{ {
let content = document.getElementById("sp-menu-content"); let content = document.getElementById("sp-menu-content");
document.getElementById("sp-menu-chrome").removeAttribute("checked"); document.getElementById("sp-menu-browser").removeAttribute("checked");
content.setAttribute("checked", true); content.setAttribute("checked", true);
this.statusbarStatus.label = content.getAttribute("label");
this.executionContext = SCRATCHPAD_CONTEXT_CONTENT; this.executionContext = SCRATCHPAD_CONTEXT_CONTENT;
this.statusbarStatus.label = content.getAttribute("label");
this.resetContext(); this.resetContext();
}, },
/** /**
* Set the current execution context to be the most recent chrome window. * Set the current execution context to be the most recent chrome window.
*/ */
setChromeContext: function SP_setChromeContext() setBrowserContext: function SP_setBrowserContext()
{ {
let chrome = document.getElementById("sp-menu-chrome"); let browser = document.getElementById("sp-menu-browser");
document.getElementById("sp-menu-content").removeAttribute("checked"); document.getElementById("sp-menu-content").removeAttribute("checked");
chrome.setAttribute("checked", true); browser.setAttribute("checked", true);
this.statusbarStatus.label = chrome.getAttribute("label"); this.executionContext = SCRATCHPAD_CONTEXT_BROWSER;
this.executionContext = SCRATCHPAD_CONTEXT_CHROME; this.statusbarStatus.label = browser.getAttribute("label");
this.resetContext(); this.resetContext();
}, },
@@ -584,6 +594,8 @@ var Scratchpad = {
this._chromeSandbox = null; this._chromeSandbox = null;
this._contentSandbox = null; this._contentSandbox = null;
this._previousWindow = null; this._previousWindow = null;
this._previousBrowser = null;
this._previousLocation = null;
}, },
/** /**
@@ -604,10 +616,10 @@ var Scratchpad = {
*/ */
onLoad: function SP_onLoad() onLoad: function SP_onLoad()
{ {
let chromeContextMenu = document.getElementById("sp-menu-chrome"); let chromeContextMenu = document.getElementById("sp-menu-browser");
let errorConsoleMenu = document.getElementById("sp-menu-errorConsole"); let errorConsoleMenu = document.getElementById("sp-menu-errorConsole");
let errorConsoleCommand = document.getElementById("sp-cmd-errorConsole"); let errorConsoleCommand = document.getElementById("sp-cmd-errorConsole");
let chromeContextCommand = document.getElementById("sp-cmd-chromeContext"); let chromeContextCommand = document.getElementById("sp-cmd-browserContext");
let chrome = Services.prefs.getBoolPref(DEVTOOLS_CHROME_ENABLED); let chrome = Services.prefs.getBoolPref(DEVTOOLS_CHROME_ENABLED);
if (chrome) { if (chrome) {
@@ -616,6 +628,7 @@ var Scratchpad = {
errorConsoleCommand.removeAttribute("disabled"); errorConsoleCommand.removeAttribute("disabled");
chromeContextCommand.removeAttribute("disabled"); chromeContextCommand.removeAttribute("disabled");
} }
this.insertIntro();
}, },
}; };

View File

@@ -70,11 +70,11 @@
--> -->
<command id="sp-cmd-close" oncommand="window.close();"/> <command id="sp-cmd-close" oncommand="window.close();"/>
<command id="sp-cmd-execute" oncommand="Scratchpad.execute();"/> <command id="sp-cmd-run" oncommand="Scratchpad.run();"/>
<command id="sp-cmd-inspect" oncommand="Scratchpad.inspect();"/> <command id="sp-cmd-inspect" oncommand="Scratchpad.inspect();"/>
<command id="sp-cmd-print" oncommand="Scratchpad.print();"/> <command id="sp-cmd-display" oncommand="Scratchpad.display();"/>
<command id="sp-cmd-contentContext" oncommand="Scratchpad.setContentContext();"/> <command id="sp-cmd-contentContext" oncommand="Scratchpad.setContentContext();"/>
<command id="sp-cmd-chromeContext" oncommand="Scratchpad.setChromeContext();" disabled="true"/> <command id="sp-cmd-browserContext" oncommand="Scratchpad.setBrowserContext();" disabled="true"/>
<command id="sp-cmd-resetContext" oncommand="Scratchpad.resetContext();"/> <command id="sp-cmd-resetContext" oncommand="Scratchpad.resetContext();"/>
<command id="sp-cmd-errorConsole" oncommand="Scratchpad.openErrorConsole();" disabled="true"/> <command id="sp-cmd-errorConsole" oncommand="Scratchpad.openErrorConsole();" disabled="true"/>
<command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/> <command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/>
@@ -118,17 +118,17 @@
<key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/> <key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/>
<key id="key_undo" key="&undoCmd.key;" modifiers="accel"/> <key id="key_undo" key="&undoCmd.key;" modifiers="accel"/>
<key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift"/> <key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift"/>
<key id="sp-key-execute" <key id="sp-key-run"
key="&execute.key;" key="&run.key;"
command="sp-cmd-execute" command="sp-cmd-run"
modifiers="accel"/> modifiers="accel"/>
<key id="sp-key-inspect" <key id="sp-key-inspect"
key="&inspect.key;" key="&inspect.key;"
command="sp-cmd-inspect" command="sp-cmd-inspect"
modifiers="accel"/> modifiers="accel"/>
<key id="sp-key-print" <key id="sp-key-display"
key="&print.key;" key="&display.key;"
command="sp-cmd-print" command="sp-cmd-display"
modifiers="accel"/> modifiers="accel"/>
<key id="sp-key-errorConsole" <key id="sp-key-errorConsole"
key="&errorConsoleCmd.commandkey;" key="&errorConsoleCmd.commandkey;"
@@ -220,7 +220,6 @@
key="key_selectAll" key="key_selectAll"
accesskey="&selectAllCmd.accesskey;" accesskey="&selectAllCmd.accesskey;"
command="cmd_selectAll"/> command="cmd_selectAll"/>
<menuseparator/>
<!-- TODO: bug 650345 - implement search and replace <!-- TODO: bug 650345 - implement search and replace
<menuitem id="sp-menu-find" <menuitem id="sp-menu-find"
@@ -238,38 +237,44 @@
<menuseparator id="sp-execute-separator"/> <menuseparator id="sp-execute-separator"/>
--> -->
<menuitem id="sp-text-execute" </menupopup>
label="&execute.label;" </menu>
accesskey="&execute.accesskey;"
key="sp-key-execute" <menu id="sp-execute-menu" label="&executeMenu.label;"
command="sp-cmd-execute"/> accesskey="&executeMenu.accesskey;">
<menupopup id="sp-menu_executepopup">
<menuitem id="sp-text-run"
label="&run.label;"
accesskey="&run.accesskey;"
key="sp-key-run"
command="sp-cmd-run"/>
<menuitem id="sp-text-inspect" <menuitem id="sp-text-inspect"
label="&inspect.label;" label="&inspect.label;"
accesskey="&inspect.accesskey;" accesskey="&inspect.accesskey;"
key="sp-key-inspect" key="sp-key-inspect"
command="sp-cmd-inspect"/> command="sp-cmd-inspect"/>
<menuitem id="sp-text-print" <menuitem id="sp-text-display"
label="&print.label;" label="&display.label;"
accesskey="&print.accesskey;" accesskey="&display.accesskey;"
key="sp-key-print" key="sp-key-display"
command="sp-cmd-print"/> command="sp-cmd-display"/>
</menupopup> </menupopup>
</menu> </menu>
<menu id="sp-context-menu" <menu id="sp-environment-menu"
label="&contextMenu.label;" label="&environmentMenu.label;"
accesskey="&contextMenu.accesskey;"> accesskey="&environmentMenu.accesskey;">
<menupopup id="sp-menu-context"> <menupopup id="sp-menu-environment">
<menuitem id="sp-menu-content" <menuitem id="sp-menu-content"
label="&contentContext.label;" label="&contentContext.label;"
accesskey="&contentContext.accesskey;" accesskey="&contentContext.accesskey;"
command="sp-cmd-contentContext" command="sp-cmd-contentContext"
checked="true" checked="true"
type="radio"/> type="radio"/>
<menuitem id="sp-menu-chrome" hidden="true" <menuitem id="sp-menu-browser" hidden="true"
command="sp-cmd-chromeContext" command="sp-cmd-browserContext"
label="&chromeContext.label;" label="&browserContext.label;"
accesskey="&chromeContext.accesskey;" accesskey="&browserContext.accesskey;"
type="radio"/> type="radio"/>
<menuseparator/> <menuseparator/>
<menuitem id="sp-menu-resetContext" <menuitem id="sp-menu-resetContext"
@@ -306,21 +311,21 @@
<menuseparator/> <menuseparator/>
<menuitem id="menu_selectAll"/> <menuitem id="menu_selectAll"/>
<menuseparator/> <menuseparator/>
<menuitem id="sp-text-execute" <menuitem id="sp-text-run"
label="&execute.label;" label="&run.label;"
accesskey="&execute.accesskey;" accesskey="&run.accesskey;"
key="sp-key-execute" key="sp-key-run"
command="sp-cmd-execute"/> command="sp-cmd-run"/>
<menuitem id="sp-text-inspect" <menuitem id="sp-text-inspect"
label="&inspect.label;" label="&inspect.label;"
accesskey="&inspect.accesskey;" accesskey="&inspect.accesskey;"
key="sp-key-inspect" key="sp-key-inspect"
command="sp-cmd-inspect"/> command="sp-cmd-inspect"/>
<menuitem id="sp-text-print" <menuitem id="sp-text-display"
label="&print.label;" label="&display.label;"
accesskey="&print.accesskey;" accesskey="&display.accesskey;"
key="sp-key-print" key="sp-key-display"
command="sp-cmd-print"/> command="sp-cmd-display"/>
</menupopup> </menupopup>
</popupset> </popupset>
@@ -328,7 +333,7 @@
multiline="true" multiline="true"
flex="1" flex="1"
context="scratchpad-text-popup" context="scratchpad-text-popup"
placeholder="&textbox.placeholder;" /> placeholder="&textbox.placeholder1;" />
<statusbar id="scratchpad-statusbar" align="end"> <statusbar id="scratchpad-statusbar" align="end">
<statusbarpanel id="scratchpad-status" <statusbarpanel id="scratchpad-status"
label="&contentContext.label;" label="&contentContext.label;"

View File

@@ -2902,7 +2902,7 @@
tabWidth += "px"; tabWidth += "px";
for (let i = numPinned; i < tabs.length; i++) { for (let i = numPinned; i < tabs.length; i++) {
let tab = tabs[i]; let tab = tabs[i];
tab.style.maxWidth = tabWidth; tab.style.setProperty("max-width", tabWidth, "important");
if (!isEndTab) { // keep tabs the same width if (!isEndTab) { // keep tabs the same width
tab.style.MozTransition = "none"; tab.style.MozTransition = "none";
tab.clientTop; // flush styles to skip animation; see bug 649247 tab.clientTop; // flush styles to skip animation; see bug 649247

View File

@@ -194,6 +194,7 @@ _BROWSER_FILES = \
browser_inspector_treePanel_result.html \ browser_inspector_treePanel_result.html \
browser_scratchpad_initialization.js \ browser_scratchpad_initialization.js \
browser_scratchpad_contexts.js \ browser_scratchpad_contexts.js \
browser_scratchpad_tab_switch.js \
browser_scratchpad_execute_print.js \ browser_scratchpad_execute_print.js \
browser_scratchpad_inspect.js \ browser_scratchpad_inspect.js \
browser_scratchpad_files.js \ browser_scratchpad_files.js \

View File

@@ -127,7 +127,12 @@ function test3() {
new TabOpenListener("about:addons", test4, prepareTest5); new TabOpenListener("about:addons", test4, prepareTest5);
EventUtils.synthesizeMouse(gTestBrowser.contentDocument.getElementById("test"), var pluginNode = gTestBrowser.contentDocument.getElementById("test");
ok(pluginNode, "Test 3, Found plugin in page");
var manageLink = gTestBrowser.contentDocument.getAnonymousElementByAttribute(pluginNode, "class", "managePluginsLink");
ok(manageLink, "Test 3, found 'manage' link in plugin-problem binding");
EventUtils.synthesizeMouse(manageLink,
5, 5, {}, gTestBrowser.contentWindow); 5, 5, {}, gTestBrowser.contentWindow);
} }

View File

@@ -36,7 +36,7 @@ function runTests()
ok(sp, "Scratchpad object exists in new window"); ok(sp, "Scratchpad object exists in new window");
let chromeContextMenu = gScratchpadWindow.document. let chromeContextMenu = gScratchpadWindow.document.
getElementById("sp-menu-chrome"); getElementById("sp-menu-browser");
ok(chromeContextMenu, "Chrome context menuitem element exists"); ok(chromeContextMenu, "Chrome context menuitem element exists");
ok(!chromeContextMenu.hasAttribute("hidden"), ok(!chromeContextMenu.hasAttribute("hidden"),
"Chrome context menuitem is visible"); "Chrome context menuitem is visible");
@@ -54,7 +54,7 @@ function runTests()
"Error console menuitem is visible"); "Error console menuitem is visible");
let chromeContextCommand = gScratchpadWindow.document. let chromeContextCommand = gScratchpadWindow.document.
getElementById("sp-cmd-chromeContext"); getElementById("sp-cmd-browserContext");
ok(chromeContextCommand, "Chrome context command element exists"); ok(chromeContextCommand, "Chrome context command element exists");
ok(!chromeContextCommand.hasAttribute("disabled"), ok(!chromeContextCommand.hasAttribute("disabled"),
"Chrome context command is disabled"); "Chrome context command is disabled");

View File

@@ -27,11 +27,11 @@ function runTests()
let sp = gScratchpadWindow.Scratchpad; let sp = gScratchpadWindow.Scratchpad;
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content"); let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
let chromeMenu = gScratchpadWindow.document.getElementById("sp-menu-chrome"); let chromeMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
let statusbar = sp.statusbarStatus; let statusbar = sp.statusbarStatus;
ok(contentMenu, "found #sp-menu-content"); ok(contentMenu, "found #sp-menu-content");
ok(chromeMenu, "found #sp-menu-chrome"); ok(chromeMenu, "found #sp-menu-browser");
ok(statusbar, "found Scratchpad.statusbarStatus"); ok(statusbar, "found Scratchpad.statusbarStatus");
sp.setContentContext(); sp.setContentContext();
@@ -54,14 +54,14 @@ function runTests()
ok(!content.wrappedJSObject.foobarBug636725, ok(!content.wrappedJSObject.foobarBug636725,
"no content.foobarBug636725"); "no content.foobarBug636725");
sp.execute(); sp.run();
is(content.wrappedJSObject.foobarBug636725, "aloha", is(content.wrappedJSObject.foobarBug636725, "aloha",
"content.foobarBug636725 has been set"); "content.foobarBug636725 has been set");
sp.setChromeContext(); sp.setBrowserContext();
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CHROME, is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_BROWSER,
"executionContext is chrome"); "executionContext is chrome");
is(chromeMenu.getAttribute("checked"), "true", is(chromeMenu.getAttribute("checked"), "true",
@@ -77,37 +77,37 @@ function runTests()
ok(!window.foobarBug636725, "no window.foobarBug636725"); ok(!window.foobarBug636725, "no window.foobarBug636725");
sp.execute(); sp.run();
is(window.foobarBug636725, "aloha2", "window.foobarBug636725 has been set"); is(window.foobarBug636725, "aloha2", "window.foobarBug636725 has been set");
sp.textbox.value = "window.gBrowser"; sp.textbox.value = "window.gBrowser";
is(typeof sp.execute()[1].addTab, "function", is(typeof sp.run()[1].addTab, "function",
"chrome context has access to chrome objects"); "chrome context has access to chrome objects");
// Check that the sandbox is cached. // Check that the sandbox is cached.
sp.textbox.value = "typeof foobarBug636725cache;"; sp.textbox.value = "typeof foobarBug636725cache;";
is(sp.execute()[1], "undefined", "global variable does not exist"); is(sp.run()[1], "undefined", "global variable does not exist");
sp.textbox.value = "var foobarBug636725cache = 'foo';"; sp.textbox.value = "var foobarBug636725cache = 'foo';";
sp.execute(); sp.run();
sp.textbox.value = "typeof foobarBug636725cache;"; sp.textbox.value = "typeof foobarBug636725cache;";
is(sp.execute()[1], "string", is(sp.run()[1], "string",
"global variable exists across two different executions"); "global variable exists across two different executions");
sp.resetContext(); sp.resetContext();
is(sp.execute()[1], "undefined", is(sp.run()[1], "undefined",
"global variable no longer exists after calling resetContext()"); "global variable no longer exists after calling resetContext()");
sp.textbox.value = "var foobarBug636725cache2 = 'foo';"; sp.textbox.value = "var foobarBug636725cache2 = 'foo';";
sp.execute(); sp.run();
sp.textbox.value = "typeof foobarBug636725cache2;"; sp.textbox.value = "typeof foobarBug636725cache2;";
is(sp.execute()[1], "string", is(sp.run()[1], "string",
"global variable exists across two different executions"); "global variable exists across two different executions");
sp.setContentContext(); sp.setContentContext();
@@ -115,7 +115,7 @@ function runTests()
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT, is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
"executionContext is content"); "executionContext is content");
is(sp.execute()[1], "undefined", is(sp.run()[1], "undefined",
"global variable no longer exists after changing the context"); "global variable no longer exists after changing the context");
gScratchpadWindow.close(); gScratchpadWindow.close();

View File

@@ -17,7 +17,7 @@ function test()
gScratchpadWindow.addEventListener("load", runTests, false); gScratchpadWindow.addEventListener("load", runTests, false);
}, true); }, true);
content.location = "data:text/html,<p>test execute() and print() in Scratchpad"; content.location = "data:text/html,<p>test run() and display() in Scratchpad";
} }
function runTests() function runTests()
@@ -31,7 +31,7 @@ function runTests()
ok(sp.textbox, "textbox exists"); ok(sp.textbox, "textbox exists");
sp.textbox.value = "++window.foobarBug636725"; sp.textbox.value = "++window.foobarBug636725";
let exec = sp.execute(); let exec = sp.run();
is(exec[0], sp.textbox.value, "execute()[0] is correct"); is(exec[0], sp.textbox.value, "execute()[0] is correct");
is(exec[1], content.wrappedJSObject.foobarBug636725, is(exec[1], content.wrappedJSObject.foobarBug636725,
"execute()[1] is correct"); "execute()[1] is correct");
@@ -42,7 +42,7 @@ function runTests()
is(content.wrappedJSObject.foobarBug636725, 2, is(content.wrappedJSObject.foobarBug636725, 2,
"execute() updated window.foobarBug636725"); "execute() updated window.foobarBug636725");
sp.print(); sp.display();
is(content.wrappedJSObject.foobarBug636725, 3, is(content.wrappedJSObject.foobarBug636725, 3,
"print() updated window.foobarBug636725"); "print() updated window.foobarBug636725");
@@ -69,7 +69,7 @@ function runTests()
is(sp.textbox.selectionStart, 0, "selectionStart is 0"); is(sp.textbox.selectionStart, 0, "selectionStart is 0");
is(sp.textbox.selectionEnd, 29, "selectionEnd is 29"); is(sp.textbox.selectionEnd, 29, "selectionEnd is 29");
exec = sp.execute(); exec = sp.run();
is(exec[0], "window.foobarBug636725 = 'a';", is(exec[0], "window.foobarBug636725 = 'a';",
"execute()[0] is correct"); "execute()[0] is correct");
@@ -88,7 +88,7 @@ function runTests()
sp.selectRange(0, 22); sp.selectRange(0, 22);
sp.print(); sp.display();
is(content.wrappedJSObject.foobarBug636725, "a", is(content.wrappedJSObject.foobarBug636725, "a",
"print() worked for the selected range"); "print() worked for the selected range");

View File

@@ -28,12 +28,12 @@ function runTests()
let sp = gScratchpadWindow.Scratchpad; let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window"); ok(sp, "Scratchpad object exists in new window");
is(typeof sp.execute, "function", "Scratchpad.execute() exists"); is(typeof sp.run, "function", "Scratchpad.run() exists");
is(typeof sp.inspect, "function", "Scratchpad.inspect() exists"); is(typeof sp.inspect, "function", "Scratchpad.inspect() exists");
is(typeof sp.print, "function", "Scratchpad.print() exists"); is(typeof sp.display, "function", "Scratchpad.display() exists");
let chromeContextMenu = gScratchpadWindow.document. let chromeContextMenu = gScratchpadWindow.document.
getElementById("sp-menu-chrome"); getElementById("sp-menu-browser");
ok(chromeContextMenu, "Chrome context menuitem element exists"); ok(chromeContextMenu, "Chrome context menuitem element exists");
is(chromeContextMenu.getAttribute("hidden"), "true", is(chromeContextMenu.getAttribute("hidden"), "true",
"Chrome context menuitem is hidden"); "Chrome context menuitem is hidden");
@@ -51,7 +51,7 @@ function runTests()
"Error console menu item is hidden"); "Error console menu item is hidden");
let chromeContextCommand = gScratchpadWindow.document. let chromeContextCommand = gScratchpadWindow.document.
getElementById("sp-cmd-chromeContext"); getElementById("sp-cmd-browserContext");
ok(chromeContextCommand, "Chrome context command element exists"); ok(chromeContextCommand, "Chrome context command element exists");
is(chromeContextCommand.getAttribute("disabled"), "true", is(chromeContextCommand.getAttribute("disabled"), "true",
"Chrome context command is disabled"); "Chrome context command is disabled");

View File

@@ -0,0 +1,111 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Reference to the Scratchpad chrome window object.
let gScratchpadWindow;
let tab1;
let tab2;
let sp;
function test()
{
waitForExplicitFinish();
tab1 = gBrowser.addTab();
gBrowser.selectedTab = tab1;
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
tab2 = gBrowser.addTab();
gBrowser.selectedTab = tab2;
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
gScratchpadWindow = Scratchpad.openScratchpad();
gScratchpadWindow.addEventListener("load", runTests, false);
}, true);
content.location = "data:text/html,test context switch in Scratchpad tab 2";
}, true);
content.location = "data:text/html,test context switch in Scratchpad tab 1";
}
function runTests()
{
gScratchpadWindow.removeEventListener("load", runTests, true);
sp = gScratchpadWindow.Scratchpad;
let contentMenu = gScratchpadWindow.document.getElementById("sp-menu-content");
let browserMenu = gScratchpadWindow.document.getElementById("sp-menu-browser");
let statusbar = sp.statusbarStatus;
ok(contentMenu, "found #sp-menu-content");
ok(browserMenu, "found #sp-menu-browser");
ok(statusbar, "found Scratchpad.statusbarStatus");
sp.setContentContext();
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
"executionContext is content");
is(contentMenu.getAttribute("checked"), "true",
"content menuitem is checked");
ok(!browserMenu.hasAttribute("checked"),
"chrome menuitem is not checked");
is(statusbar.getAttribute("label"), contentMenu.getAttribute("label"),
"statusbar label is correct");
ok(sp.textbox, "textbox exists");
sp.textbox.value = "window.foosbug653108 = 'aloha';";
ok(!content.wrappedJSObject.foosbug653108,
"no content.foosbug653108");
sp.run();
is(content.wrappedJSObject.foosbug653108, "aloha",
"content.foosbug653108 has been set");
gBrowser.tabContainer.addEventListener("TabSelect", runTests2, true);
gBrowser.selectedTab = tab1;
}
function runTests2() {
gBrowser.tabContainer.removeEventListener("TabSelect", runTests2, true);
ok(!window.foosbug653108, "no window.foosbug653108");
sp.textbox.value = "window.foosbug653108";
let result = sp.run();
isnot(result, "aloha", "window.foosbug653108 is not aloha");
sp.textbox.value = "window.foosbug653108 = 'ahoyhoy';";
sp.run();
is(content.wrappedJSObject.foosbug653108, "ahoyhoy",
"content.foosbug653108 has been set 2");
gBrowser.selectedBrowser.addEventListener("load", runTests3, true);
content.location = "data:text/html,test context switch in Scratchpad location 2";
}
function runTests3() {
gBrowser.selectedBrowser.removeEventListener("load", runTests3, true);
// Check that the sandbox is not cached.
sp.textbox.value = "typeof foosbug653108;";
is(sp.run()[1], "undefined", "global variable does not exist");
gScratchpadWindow.close();
gScratchpadWindow = null;
tab1 = null;
tab2 = null;
sp = null;
gBrowser.removeCurrentTab();
gBrowser.removeCurrentTab();
finish();
}

View File

@@ -33,10 +33,11 @@ function runTests()
"sp-menu-open": "openFile", "sp-menu-open": "openFile",
"sp-menu-save": "saveFile", "sp-menu-save": "saveFile",
"sp-menu-saveas": "saveFileAs", "sp-menu-saveas": "saveFileAs",
"sp-text-execute": "execute", "sp-text-run": "run",
"sp-text-inspect": "inspect", "sp-text-inspect": "inspect",
"sp-text-display": "display",
"sp-menu-content": "setContentContext", "sp-menu-content": "setContentContext",
"sp-menu-chrome": "setChromeContext", "sp-menu-browser": "setBrowserContext",
"sp-menu-resetContext": "resetContext", "sp-menu-resetContext": "resetContext",
"sp-menu-errorConsole": "openErrorConsole", "sp-menu-errorConsole": "openErrorConsole",
"sp-menu-webConsole": "openWebConsole", "sp-menu-webConsole": "openWebConsole",

View File

@@ -1,5 +1,5 @@
<html> <html>
<body> <body>
<embed id="test" style="width: 100px; height: 100px" type="application/x-test"> <embed id="test" style="width: 200px; height: 200px" type="application/x-test">
</body> </body>
</html> </html>

View File

@@ -587,12 +587,10 @@ let AboutPermissions = {
for each (let site in this._sites) { for each (let site in this._sites) {
if (site.host.hasRootDomain(aHost)) { if (site.host.hasRootDomain(aHost)) {
if (site == this._selectedSite) { if (site == this._selectedSite) {
// Clear site data from the DOM to maximize privacy. // Replace site-specific interface with "All Sites" interface.
document.getElementById("site-label").value = ""; this.sitesList.selectedItem = document.getElementById("all-sites-item");
document.getElementById("permissions-box").hidden = true;
this._selectedSite = null;
} }
this.sitesList.removeChild(site.listitem); this.sitesList.removeChild(site.listitem);
delete this._sites[site.host]; delete this._sites[site.host];
} }
@@ -604,6 +602,8 @@ let AboutPermissions = {
*/ */
onSitesListSelect: function(event) { onSitesListSelect: function(event) {
if (event.target.selectedItem.id == "all-sites-item") { if (event.target.selectedItem.id == "all-sites-item") {
// Clear the header label value from the previously selected site.
document.getElementById("site-label").value = "";
this.manageDefaultPermissions(); this.manageDefaultPermissions();
return; return;
} }
@@ -641,8 +641,6 @@ let AboutPermissions = {
this.updatePasswordsCount(); this.updatePasswordsCount();
this.updateCookiesCount(); this.updateCookiesCount();
document.getElementById("permissions-box").hidden = false;
}, },
/** /**

View File

@@ -74,7 +74,7 @@
</richlistbox> </richlistbox>
</vbox> </vbox>
<vbox id="permissions-box" hidden="true" flex="1"> <vbox id="permissions-box" flex="1">
<deck id="header-deck"> <deck id="header-deck">
<hbox id="site-header" class="pref-item" align="center"> <hbox id="site-header" class="pref-item" align="center">

View File

@@ -240,6 +240,10 @@ var tests = [
is(gSiteLabel.value, "", "site label cleared"); is(gSiteLabel.value, "", "site label cleared");
let allSitesItem = gBrowser.contentDocument.getElementById("all-sites-item");
is(gSitesList.selectedItem, allSitesItem,
"all sites item selected after forgetting selected site");
// check to make sure site is gone from sites list // check to make sure site is gone from sites list
let testSiteItem = getSiteItem(TEST_URI_2.host); let testSiteItem = getSiteItem(TEST_URI_2.host);
ok(!testSiteItem, "site removed from sites list"); ok(!testSiteItem, "site removed from sites list");

View File

@@ -61,33 +61,58 @@
<!ENTITY selectAllCmd.key "A"> <!ENTITY selectAllCmd.key "A">
<!ENTITY selectAllCmd.accesskey "A"> <!ENTITY selectAllCmd.accesskey "A">
<!ENTITY execute.label "Execute"> <!ENTITY run.label "Run">
<!ENTITY execute.accesskey "E"> <!ENTITY run.accesskey "R">
<!ENTITY execute.key "t"> <!ENTITY run.key "r">
<!ENTITY inspect.label "Inspect"> <!ENTITY inspect.label "Inspect">
<!ENTITY inspect.accesskey "I"> <!ENTITY inspect.accesskey "I">
<!ENTITY inspect.key "i"> <!ENTITY inspect.key "i">
<!ENTITY print.label "Print"> <!ENTITY display.label "Display">
<!ENTITY print.accesskey "p"> <!ENTITY display.accesskey "D">
<!ENTITY print.key "r"> <!ENTITY display.key "l">
<!-- LOCALIZATION NOTE (environmentMenu.label, accesskey): This menu item was
- renamed from "Context" to avoid confusion with the right-click context
- menu in the text area. It refers to the JavaScript Environment (or context)
- the user is evaluating against. I.e., Content (current tab) or Chrome
- (browser).
-->
<!ENTITY environmentMenu.label "Environment">
<!ENTITY environmentMenu.accesskey "N">
<!-- LOCALIZATION NOTE (contextMenu.label, accesskey): No longer used.
<!ENTITY contextMenu.label "Context"> <!ENTITY contextMenu.label "Context">
<!ENTITY contextMenu.accesskey "C"> <!ENTITY contextMenu.accesskey "C">
-->
<!ENTITY contentContext.label "Content"> <!ENTITY contentContext.label "Content">
<!ENTITY contentContext.accesskey "C"> <!ENTITY contentContext.accesskey "C">
<!-- LOCALIZATION NOTE (browserContext.label, accesskey): This menu item is used
- to select an execution environment for the browser window itself as opposed
- to content. This is a feature for browser and addon developers and only
- enabled via the devtools.chrome.enabled preference. Formerly, this label
- was called "Chrome".
-->
<!ENTITY browserContext.label "Browser">
<!ENTITY browserContext.accesskey "B">
<!-- LOCALIZATION NOTE (chromeContext.label, accesskey): No longer used.
<!ENTITY chromeContext.label "Chrome"> <!ENTITY chromeContext.label "Chrome">
<!ENTITY chromeContext.accesskey "H"> <!ENTITY chromeContext.accesskey "H">
-->
<!-- LOCALIZATION NOTE (resetContext.label): This command allows the developer <!-- LOCALIZATION NOTE (resetContext.label): This command allows the developer
- to reset/clear the global object of the context where the code executes. - to reset/clear the global object of the environment where the code executes.
--> -->
<!ENTITY resetContext.label "Reset"> <!ENTITY resetContext.label "Reset">
<!ENTITY resetContext.accesskey "R"> <!ENTITY resetContext.accesskey "R">
<!ENTITY executeMenu.label "Execute">
<!ENTITY executeMenu.accesskey "X">
<!ENTITY toolsMenu.label "Tools"> <!ENTITY toolsMenu.label "Tools">
<!ENTITY toolsMenu.accesskey "T"> <!ENTITY toolsMenu.accesskey "T">
@@ -99,5 +124,9 @@
<!ENTITY webConsoleCmd.accesskey "W"> <!ENTITY webConsoleCmd.accesskey "W">
<!ENTITY webConsoleCmd.commandkey "k"> <!ENTITY webConsoleCmd.commandkey "k">
<!ENTITY textbox.placeholder "// Enter some JavaScript, select it, right click and select Execute, Inspect or Print."> <!-- LOCALIZATION NOTE (textbox.placeholder1): This is some placeholder text
- that appears when the Scratchpad's text area is empty and unfocused.
- It should be a one-line JavaScript comment, i.e., preceded by '//'
-->
<!ENTITY textbox.placeholder1 "// Enter some JavaScript, select it, right click and select Run, Inspect or Display.">

View File

@@ -28,3 +28,8 @@ saveFileAs=Save File As
# LOCALIZATION NOTE (saveFile.failed): This is the message displayed when file # LOCALIZATION NOTE (saveFile.failed): This is the message displayed when file
# save fails. # save fails.
saveFile.failed=The file save operation failed. saveFile.failed=The file save operation failed.
# LOCALIZATION NOTE (scratchpadIntro): This is a multi-line comment explaining
# how to use the Scratchpad. Note that this should be a valid JavaScript
# comment inside /* and */.
scratchpadIntro=/*\n * This is a JavaScript Scratchpad.\n *\n * Enter some JavaScript, then Right Click or choose from the Execute Menu:\n * 1. Run to evaluate the selected text,\n * 2. Inspect to bring up an Object Inspector on the result, or,\n * 3. Display to insert the result in a comment after the selection.\n */\n\n

View File

@@ -441,20 +441,23 @@ function FindProxyForURL(url, host)
var isHttp = matches[1] == 'http'; var isHttp = matches[1] == 'http';
var isHttps = matches[1] == 'https'; var isHttps = matches[1] == 'https';
var isWebSocket = matches[1] == 'ws'; var isWebSocket = matches[1] == 'ws';
var isWebSocketSSL = matches[1] == 'wss';
if (!matches[3]) if (!matches[3])
{ {
if (isHttp | isWebSocket) matches[3] = '80'; if (isHttp | isWebSocket) matches[3] = '80';
if (isHttps) matches[3] = '443'; if (isHttps | isWebSocketSSL) matches[3] = '443';
} }
if (isWebSocket) if (isWebSocket)
matches[1] = 'http'; matches[1] = 'http';
if (isWebSocketSSL)
matches[1] = 'https';
var origin = matches[1] + '://' + matches[2] + ':' + matches[3]; var origin = matches[1] + '://' + matches[2] + ':' + matches[3];
if (origins.indexOf(origin) < 0) if (origins.indexOf(origin) < 0)
return 'DIRECT'; return 'DIRECT';
if (isHttp) if (isHttp)
return 'PROXY %(remote)s:%(httpport)s'; return 'PROXY %(remote)s:%(httpport)s';
if (isHttps || isWebSocket) if (isHttps || isWebSocket || isWebSocketSSL)
return 'PROXY %(remote)s:%(sslport)s'; return 'PROXY %(remote)s:%(sslport)s';
return 'DIRECT'; return 'DIRECT';
}""" % { "origins": origins, }""" % { "origins": origins,

View File

@@ -150,6 +150,19 @@ nsNullPrincipalURI::SetPath(const nsACString &aPath)
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
} }
NS_IMETHODIMP
nsNullPrincipalURI::GetRef(nsACString &_ref)
{
_ref.Truncate();
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsNullPrincipalURI::SetRef(const nsACString &aRef)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP NS_IMETHODIMP
nsNullPrincipalURI::GetPrePath(nsACString &_prePath) nsNullPrincipalURI::GetPrePath(nsACString &_prePath)
{ {
@@ -224,11 +237,18 @@ nsNullPrincipalURI::Clone(nsIURI **_newURI)
{ {
nsCOMPtr<nsIURI> uri = nsCOMPtr<nsIURI> uri =
new nsNullPrincipalURI(mScheme + NS_LITERAL_CSTRING(":") + mPath); new nsNullPrincipalURI(mScheme + NS_LITERAL_CSTRING(":") + mPath);
NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
uri.forget(_newURI); uri.forget(_newURI);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsNullPrincipalURI::CloneIgnoringRef(nsIURI **_newURI)
{
// GetRef/SetRef not supported by nsNullPrincipalURI, so
// CloneIgnoringRef() is the same as Clone().
return Clone(_newURI);
}
NS_IMETHODIMP NS_IMETHODIMP
nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals) nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals)
{ {
@@ -243,6 +263,14 @@ nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsNullPrincipalURI::EqualsExceptRef(nsIURI *aOther, PRBool *_equals)
{
// GetRef/SetRef not supported by nsNullPrincipalURI, so
// EqualsExceptRef() is the same as Equals().
return Equals(aOther, _equals);
}
NS_IMETHODIMP NS_IMETHODIMP
nsNullPrincipalURI::Resolve(const nsACString &aRelativePath, nsNullPrincipalURI::Resolve(const nsACString &aRelativePath,
nsACString &_resolvedURI) nsACString &_resolvedURI)

View File

@@ -2027,8 +2027,8 @@ case "$target" in
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer" MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
fi fi
_PEDANTIC= _PEDANTIC=
CFLAGS="$CFLAGS -fpascal-strings -fno-common" CFLAGS="$CFLAGS -fno-common"
CXXFLAGS="$CXXFLAGS -fpascal-strings -fno-common" CXXFLAGS="$CXXFLAGS -fno-common"
DLL_SUFFIX=".dylib" DLL_SUFFIX=".dylib"
DSO_LDOPTS='' DSO_LDOPTS=''
STRIP="$STRIP -x -S" STRIP="$STRIP -x -S"
@@ -4861,7 +4861,7 @@ NSS_DISABLE_DBM=
NECKO_WIFI=1 NECKO_WIFI=1
NECKO_COOKIES=1 NECKO_COOKIES=1
NECKO_DISK_CACHE=1 NECKO_DISK_CACHE=1
NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource wyciwyg" NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg"
USE_ARM_KUSER= USE_ARM_KUSER=
BUILD_CTYPES=1 BUILD_CTYPES=1
XPC_IDISPATCH_SUPPORT= XPC_IDISPATCH_SUPPORT=

View File

@@ -40,6 +40,7 @@
#define nsDOMFile_h__ #define nsDOMFile_h__
#include "nsICharsetDetectionObserver.h" #include "nsICharsetDetectionObserver.h"
#include "nsIFile.h"
#include "nsIDOMFile.h" #include "nsIDOMFile.h"
#include "nsIDOMFileList.h" #include "nsIDOMFileList.h"
#include "nsIDOMFileError.h" #include "nsIDOMFileError.h"
@@ -56,9 +57,12 @@
class nsIFile; class nsIFile;
class nsIInputStream; class nsIInputStream;
class nsIClassInfo; class nsIClassInfo;
class nsIBlobBuilder;
nsresult NS_NewBlobBuilder(nsISupports* *aSupports);
void ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd);
class nsDOMFile : public nsIDOMFile, class nsDOMFile : public nsIDOMFile,
public nsIDOMBlob_MOZILLA_2_0_BRANCH,
public nsIXHRSendable, public nsIXHRSendable,
public nsICharsetDetectionObserver, public nsICharsetDetectionObserver,
public nsIJSNativeInitializer public nsIJSNativeInitializer
@@ -67,7 +71,6 @@ public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIDOMBLOB NS_DECL_NSIDOMBLOB
NS_DECL_NSIDOMFILE NS_DECL_NSIDOMFILE
NS_DECL_NSIDOMBLOB_MOZILLA_2_0_BRANCH
NS_DECL_NSIXHRSENDABLE NS_DECL_NSIXHRSENDABLE
nsDOMFile(nsIFile *aFile, const nsAString& aContentType) nsDOMFile(nsIFile *aFile, const nsAString& aContentType)

View File

@@ -37,37 +37,33 @@
#include "domstubs.idl" #include "domstubs.idl"
%{C++
#include "jsapi.h"
%}
interface nsIDOMFileError; interface nsIDOMFileError;
interface nsIInputStream; interface nsIInputStream;
interface nsIURI; interface nsIURI;
interface nsIPrincipal; interface nsIPrincipal;
interface nsIDOMBlob; interface nsIDOMBlob;
[scriptable, uuid(5822776a-049c-4de7-adb6-dd9efc39d082)] [scriptable, uuid(d5237f31-443a-460b-9e42-449a135346f0)]
interface nsIDOMBlob : nsISupports interface nsIDOMBlob : nsISupports
{ {
readonly attribute unsigned long long size; readonly attribute unsigned long long size;
readonly attribute DOMString type; readonly attribute DOMString type;
[noscript] nsIDOMBlob slice(in unsigned long long start,
in unsigned long long length,
[optional] in DOMString contentType);
[noscript] readonly attribute nsIInputStream internalStream; [noscript] readonly attribute nsIInputStream internalStream;
// The caller is responsible for releasing the internalUrl from the // The caller is responsible for releasing the internalUrl from the
// moz-filedata: protocol handler // moz-filedata: protocol handler
[noscript] DOMString getInternalUrl(in nsIPrincipal principal); [noscript] DOMString getInternalUrl(in nsIPrincipal principal);
};
[scriptable, uuid(cb5b4191-a555-4e57-b8d2-88091184b59f)]
interface nsIDOMBlob_MOZILLA_2_0_BRANCH : nsISupports
{
[optional_argc] nsIDOMBlob mozSlice(in long long start, [optional_argc] nsIDOMBlob mozSlice(in long long start,
[optional] in long long end, [optional] in long long end,
[optional] in DOMString contentType); [optional] in DOMString contentType);
}; };
[scriptable, uuid(ae1405b0-e411-481e-9606-b29ec7982687)] [scriptable, uuid(91c9ebd9-2a4a-4a38-9412-ef492a2799be)]
interface nsIDOMFile : nsIDOMBlob interface nsIDOMFile : nsIDOMBlob
{ {
readonly attribute DOMString name; readonly attribute DOMString name;
@@ -84,3 +80,10 @@ interface nsIDOMFile : nsIDOMBlob
DOMString getAsDataURL(); // raises(FileException) on retrieval DOMString getAsDataURL(); // raises(FileException) on retrieval
DOMString getAsBinary(); // raises(FileException) on retrieval DOMString getAsBinary(); // raises(FileException) on retrieval
}; };
[scriptable, uuid(c4a77171-039b-4f84-97f9-820fb51626af)]
interface nsIDOMBlobBuilder : nsISupports
{
nsIDOMBlob getBlob([optional] in DOMString contentType);
[implicit_jscontext] void append(in jsval data);
};

View File

@@ -51,7 +51,7 @@ interface nsIDOMClientRect;
/** /**
* This interface represents a content node that loads objects. * This interface represents a content node that loads objects.
*/ */
[scriptable, uuid(9558649a-7255-4b00-afb4-1171e9cdcead)] [scriptable, uuid(107e8048-d00f-4711-bd21-97184ccae0b1)]
interface nsIObjectLoadingContent : nsISupports interface nsIObjectLoadingContent : nsISupports
{ {
const unsigned long TYPE_LOADING = 0; const unsigned long TYPE_LOADING = 0;
@@ -113,14 +113,6 @@ interface nsIObjectLoadingContent : nsISupports
*/ */
[noscript] void hasNewFrame(in nsIObjectFrame aFrame); [noscript] void hasNewFrame(in nsIObjectFrame aFrame);
/**
* Tells the object to paint directly in this location ignoring any
* positioning information that may have been provided otherwise
*/
void setAbsoluteScreenPosition(in nsIDOMElement element,
in nsIDOMClientRect position,
in nsIDOMClientRect clip);
/** /**
* If this object is in going to be printed, this method * If this object is in going to be printed, this method
* returns the nsIObjectFrame object which should be used when * returns the nsIObjectFrame object which should be used when

View File

@@ -51,10 +51,11 @@ interface nsPIDOMWindow;
* http://dev.w3.org/html5/websockets/ * http://dev.w3.org/html5/websockets/
* *
*/ */
[scriptable, uuid(4403cd57-07fc-477f-a062-d6ba7dd0781b)] [scriptable, uuid(431aea4c-568a-470e-b876-c57a29ff0fc6)]
interface nsIWebSocket : nsISupports interface nsIWebSocket : nsISupports
{ {
readonly attribute DOMString url; readonly attribute DOMString url;
readonly attribute DOMString protocol;
//ready state //ready state
const unsigned short CONNECTING = 0; const unsigned short CONNECTING = 0;

View File

@@ -307,13 +307,12 @@ nsresult
Link::SetHash(const nsAString &aHash) Link::SetHash(const nsAString &aHash)
{ {
nsCOMPtr<nsIURI> uri(GetURIToMutate()); nsCOMPtr<nsIURI> uri(GetURIToMutate());
nsCOMPtr<nsIURL> url(do_QueryInterface(uri)); if (!uri) {
if (!url) {
// Ignore failures to be compatible with NS4. // Ignore failures to be compatible with NS4.
return NS_OK; return NS_OK;
} }
(void)url->SetRef(NS_ConvertUTF16toUTF8(aHash)); (void)uri->SetRef(NS_ConvertUTF16toUTF8(aHash));
SetHrefAttribute(uri); SetHrefAttribute(uri);
return NS_OK; return NS_OK;
} }
@@ -444,15 +443,14 @@ Link::GetHash(nsAString &_hash)
_hash.Truncate(); _hash.Truncate();
nsCOMPtr<nsIURI> uri(GetURI()); nsCOMPtr<nsIURI> uri(GetURI());
nsCOMPtr<nsIURL> url(do_QueryInterface(uri)); if (!uri) {
if (!url) { // Do not throw! Not having a valid URI should result in an empty
// Do not throw! Not having a valid URI or URL should result in an empty
// string. // string.
return NS_OK; return NS_OK;
} }
nsCAutoString ref; nsCAutoString ref;
nsresult rv = url->GetRef(ref); nsresult rv = uri->GetRef(ref);
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) { if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes! NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
_hash.Assign(PRUnichar('#')); _hash.Assign(PRUnichar('#'));

View File

@@ -92,6 +92,7 @@ CPPSRCS = \
nsDataDocumentContentPolicy.cpp \ nsDataDocumentContentPolicy.cpp \
nsDOMAttribute.cpp \ nsDOMAttribute.cpp \
nsDOMAttributeMap.cpp \ nsDOMAttributeMap.cpp \
nsDOMBlobBuilder.cpp \
nsDOMDocumentType.cpp \ nsDOMDocumentType.cpp \
nsDOMEventTargetWrapperCache.cpp \ nsDOMEventTargetWrapperCache.cpp \
nsDOMFile.cpp \ nsDOMFile.cpp \

View File

@@ -0,0 +1,399 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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 Mozilla File API.
*
* The Initial Developer of the Original Code is
* Kyle Huey <me@kylehuey.com>
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 "jstypedarray.h"
#include "nsAutoPtr.h"
#include "nsDOMClassInfo.h"
#include "nsDOMFile.h"
#include "nsIMultiplexInputStream.h"
#include "nsStringStream.h"
#include "nsTArray.h"
#include "nsJSUtils.h"
#include "nsContentUtils.h"
#include "CheckedInt.h"
// XXXkhuey shamelessly stolen from VideoUtils.h. We should patch NSPR.
#define PR_INT64_MAX (~((PRInt64)(1) << 63))
#define PR_INT64_MIN (-PR_INT64_MAX - 1)
using namespace mozilla;
class nsDOMMultipartBlob : public nsDOMFile
{
public:
nsDOMMultipartBlob(nsTArray<nsCOMPtr<nsIDOMBlob> > aBlobs,
const nsAString& aContentType)
: nsDOMFile(nsnull, aContentType),
mBlobs(aBlobs)
{
mIsFullFile = false;
mStart = 0;
mLength = 0;
}
NS_IMETHOD GetSize(PRUint64*);
NS_IMETHOD GetInternalStream(nsIInputStream**);
NS_IMETHOD MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType, PRUint8 optional_argc,
nsIDOMBlob **aBlob);
protected:
nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
};
NS_IMETHODIMP
nsDOMMultipartBlob::GetSize(PRUint64* aLength)
{
nsresult rv;
*aLength = 0;
if (mLength) {
*aLength = mLength;
return NS_OK;
}
CheckedUint64 length = 0;
PRUint32 i;
PRUint32 len = mBlobs.Length();
for (i = 0; i < len; i++) {
nsIDOMBlob* blob = mBlobs.ElementAt(i).get();
PRUint64 l = 0;
rv = blob->GetSize(&l);
NS_ENSURE_SUCCESS(rv, rv);
length += l;
}
if (!length.valid())
return NS_ERROR_FAILURE;
mLength = length.value();
*aLength = mLength;
return NS_OK;
}
NS_IMETHODIMP
nsDOMMultipartBlob::GetInternalStream(nsIInputStream** aStream)
{
nsresult rv;
*aStream = nsnull;
nsCOMPtr<nsIMultiplexInputStream> stream =
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE);
PRUint32 i;
for (i = 0; i < mBlobs.Length(); i++) {
nsCOMPtr<nsIInputStream> scratchStream;
nsIDOMBlob* blob = mBlobs.ElementAt(i).get();
rv = blob->GetInternalStream(getter_AddRefs(scratchStream));
NS_ENSURE_SUCCESS(rv, rv);
rv = stream->AppendStream(scratchStream);
NS_ENSURE_SUCCESS(rv, rv);
}
return CallQueryInterface(stream, aStream);
}
NS_IMETHODIMP
nsDOMMultipartBlob::MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType,
PRUint8 optional_argc,
nsIDOMBlob **aBlob)
{
nsresult rv;
*aBlob = nsnull;
// Truncate aStart and aEnd so that we stay within this file.
PRUint64 thisLength;
rv = GetSize(&thisLength);
NS_ENSURE_SUCCESS(rv, rv);
if (!optional_argc) {
aEnd = (PRInt64)thisLength;
}
ParseSize((PRInt64)thisLength, aStart, aEnd);
// If we clamped to nothing we create an empty blob
nsTArray<nsCOMPtr<nsIDOMBlob> > blobs;
PRInt64 length = aEnd - aStart;
PRUint64 finalLength = length;
PRUint64 skipStart = aStart;
NS_ABORT_IF_FALSE(aStart + length <= thisLength, "Er, what?");
// Prune the list of blobs if we can
PRUint32 i;
for (i = 0; length && skipStart && i < mBlobs.Length(); i++) {
nsIDOMBlob* blob = mBlobs[i].get();
PRUint64 l;
rv = blob->GetSize(&l);
NS_ENSURE_SUCCESS(rv, rv);
if (skipStart < l) {
PRInt64 upperBound = NS_MIN<PRInt64>(l - skipStart, length);
nsCOMPtr<nsIDOMBlob> firstBlob;
rv = mBlobs.ElementAt(i)->MozSlice(skipStart, skipStart + upperBound,
aContentType, 2,
getter_AddRefs(firstBlob));
NS_ENSURE_SUCCESS(rv, rv);
// Avoid wrapping a single blob inside an nsDOMMultipartBlob
if (length == upperBound) {
firstBlob.forget(aBlob);
return NS_OK;
}
blobs.AppendElement(firstBlob);
length -= upperBound;
i++;
break;
}
skipStart -= l;
}
// Now append enough blobs until we're done
for (; length && i < mBlobs.Length(); i++) {
nsIDOMBlob* blob = mBlobs[i].get();
PRUint64 l;
rv = blob->GetSize(&l);
NS_ENSURE_SUCCESS(rv, rv);
if (length < l) {
nsCOMPtr<nsIDOMBlob> lastBlob;
rv = mBlobs.ElementAt(i)->MozSlice(0, length, aContentType, 2,
getter_AddRefs(lastBlob));
NS_ENSURE_SUCCESS(rv, rv);
blobs.AppendElement(lastBlob);
} else {
blobs.AppendElement(blob);
}
length -= NS_MIN<PRInt64>(l, length);
}
// we can create our blob now
nsCOMPtr<nsIDOMBlob> blob = new nsDOMMultipartBlob(blobs, aContentType);
blob.forget(aBlob);
return NS_OK;
}
class nsDOMBlobBuilder : public nsIDOMBlobBuilder
{
public:
nsDOMBlobBuilder()
: mData(nsnull), mDataLen(0), mDataBufferLen(0)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMBLOBBUILDER
protected:
nsresult AppendVoidPtr(void* aData, PRUint32 aLength);
nsresult AppendString(JSString* aString, JSContext* aCx);
nsresult AppendBlob(nsIDOMBlob* aBlob);
nsresult AppendArrayBuffer(js::ArrayBuffer* aBuffer);
bool ExpandBufferSize(PRUint64 aSize)
{
if (mDataBufferLen >= mDataLen + aSize) {
mDataLen += aSize;
return true;
}
// Start at 1 or we'll loop forever.
CheckedUint32 bufferLen = NS_MAX<PRUint32>(mDataBufferLen, 1);
while (bufferLen.valid() && bufferLen.value() < mDataLen + aSize)
bufferLen *= 2;
if (!bufferLen.valid())
return false;
// PR_ memory functions are still fallible
void* data = PR_Realloc(mData, bufferLen.value());
if (!data)
return false;
mData = data;
mDataBufferLen = bufferLen.value();
mDataLen += aSize;
return true;
}
void Flush() {
if (mData) {
// If we have some data, create a blob for it
// and put it on the stack
nsCOMPtr<nsIDOMBlob> blob =
new nsDOMMemoryFile(mData, mDataLen, EmptyString(), EmptyString());
mBlobs.AppendElement(blob);
mData = nsnull; // The nsDOMMemoryFile takes ownership of the buffer
mDataLen = 0;
mDataBufferLen = 0;
}
}
nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
void* mData;
PRUint64 mDataLen;
PRUint64 mDataBufferLen;
};
DOMCI_DATA(MozBlobBuilder, nsDOMBlobBuilder)
NS_IMPL_ADDREF(nsDOMBlobBuilder)
NS_IMPL_RELEASE(nsDOMBlobBuilder)
NS_INTERFACE_MAP_BEGIN(nsDOMBlobBuilder)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlobBuilder)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozBlobBuilder)
NS_INTERFACE_MAP_END
nsresult
nsDOMBlobBuilder::AppendVoidPtr(void* aData, PRUint32 aLength)
{
NS_ENSURE_ARG_POINTER(aData);
PRUint64 offset = mDataLen;
if (!ExpandBufferSize(aLength))
return NS_ERROR_OUT_OF_MEMORY;
memcpy((char*)mData + offset, aData, aLength);
return NS_OK;
}
nsresult
nsDOMBlobBuilder::AppendString(JSString* aString, JSContext* aCx)
{
nsDependentJSString xpcomStr;
if (!xpcomStr.init(aCx, aString)) {
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
NS_ConvertUTF16toUTF8 utf8Str(xpcomStr);
return AppendVoidPtr((void*)utf8Str.Data(),
utf8Str.Length());
}
nsresult
nsDOMBlobBuilder::AppendBlob(nsIDOMBlob* aBlob)
{
NS_ENSURE_ARG_POINTER(aBlob);
Flush();
mBlobs.AppendElement(aBlob);
return NS_OK;
}
nsresult
nsDOMBlobBuilder::AppendArrayBuffer(js::ArrayBuffer* aBuffer)
{
return AppendVoidPtr(aBuffer->data, aBuffer->byteLength);
}
/* nsIDOMBlob getBlob ([optional] in DOMString contentType); */
NS_IMETHODIMP
nsDOMBlobBuilder::GetBlob(const nsAString& aContentType,
nsIDOMBlob** aBlob)
{
NS_ENSURE_ARG(aBlob);
Flush();
nsCOMPtr<nsIDOMBlob> blob = new nsDOMMultipartBlob(mBlobs,
aContentType);
blob.forget(aBlob);
// NB: This is a willful violation of the spec. The spec says that
// the existing contents of the BlobBuilder should be included
// in the next blob produced. This seems silly and has been raised
// on the WHATWG listserv.
mBlobs.Clear();
return NS_OK;
}
/* [implicit_jscontext] void append (in jsval data); */
NS_IMETHODIMP
nsDOMBlobBuilder::Append(const jsval& aData, JSContext* aCx)
{
// We need to figure out what our jsval is
// Is it an object?
if (JSVAL_IS_OBJECT(aData)) {
JSObject* obj = JSVAL_TO_OBJECT(aData);
NS_ASSERTION(obj, "Er, what?");
// Is it a Blob?
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
nsContentUtils::XPConnect()->
GetNativeOfWrapper(aCx, obj));
if (blob)
return AppendBlob(blob);
// Is it an array buffer?
if (js_IsArrayBuffer(obj)) {
js::ArrayBuffer* buffer = js::ArrayBuffer::fromJSObject(obj);
if (buffer)
return AppendArrayBuffer(buffer);
}
}
// If it's not a Blob or an ArrayBuffer, coerce it to a string
JSString* str = JS_ValueToString(aCx, aData);
NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
return AppendString(str, aCx);
}
nsresult NS_NewBlobBuilder(nsISupports* *aSupports)
{
nsDOMBlobBuilder* builder = new nsDOMBlobBuilder();
return CallQueryInterface(builder, aSupports);
}

View File

@@ -49,7 +49,6 @@
#include "nsIConverterInputStream.h" #include "nsIConverterInputStream.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
#include "nsIFile.h"
#include "nsIFileStreams.h" #include "nsIFileStreams.h"
#include "nsIInputStream.h" #include "nsIInputStream.h"
#include "nsIIPCSerializable.h" #include "nsIIPCSerializable.h"
@@ -140,7 +139,6 @@ DOMCI_DATA(Blob, nsDOMFile)
NS_INTERFACE_MAP_BEGIN(nsDOMFile) NS_INTERFACE_MAP_BEGIN(nsDOMFile)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob) NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFullFile) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFullFile)
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable) NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver) NS_INTERFACE_MAP_ENTRY(nsICharsetDetectionObserver)
@@ -293,13 +291,6 @@ ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd)
} }
} }
NS_IMETHODIMP
nsDOMFile::Slice(PRUint64 aStart, PRUint64 aLength,
const nsAString& aContentType, nsIDOMBlob **aBlob)
{
return MozSlice(aStart, aStart + aLength, aContentType, 2, aBlob);
}
NS_IMETHODIMP NS_IMETHODIMP
nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd, nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
const nsAString& aContentType, PRUint8 optional_argc, const nsAString& aContentType, PRUint8 optional_argc,
@@ -307,7 +298,7 @@ nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
{ {
*aBlob = nsnull; *aBlob = nsnull;
// Truncate aLength and aStart so that we stay within this file. // Truncate aStart and aEnd so that we stay within this file.
PRUint64 thisLength; PRUint64 thisLength;
nsresult rv = GetSize(&thisLength); nsresult rv = GetSize(&thisLength);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);

View File

@@ -694,14 +694,10 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
// First, make sure we strip the ref from aURI. // First, make sure we strip the ref from aURI.
nsCOMPtr<nsIURI> clone; nsCOMPtr<nsIURI> clone;
aURI->Clone(getter_AddRefs(clone)); nsresult rv = aURI->CloneIgnoringRef(getter_AddRefs(clone));
if (!clone) { if (NS_FAILED(rv) || !clone) {
return nsnull; return nsnull;
} }
nsCOMPtr<nsIURL> url(do_QueryInterface(clone));
if (url) {
url->SetRef(EmptyCString());
}
ExternalResource* resource; ExternalResource* resource;
mMap.Get(clone, &resource); mMap.Get(clone, &resource);
@@ -712,14 +708,11 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
nsRefPtr<PendingLoad> load; nsRefPtr<PendingLoad> load;
mPendingLoads.Get(clone, getter_AddRefs(load)); mPendingLoads.Get(clone, getter_AddRefs(load));
if (load) { if (load) {
NS_ADDREF(*aPendingLoad = load); load.forget(aPendingLoad);
return nsnull; return nsnull;
} }
load = new PendingLoad(aDisplayDocument); load = new PendingLoad(aDisplayDocument);
if (!load) {
return nsnull;
}
if (!mPendingLoads.Put(clone, load)) { if (!mPendingLoads.Put(clone, load)) {
return nsnull; return nsnull;
@@ -730,7 +723,7 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
// chances are it failed for good reasons (security check, etc). // chances are it failed for good reasons (security check, etc).
AddExternalResource(clone, nsnull, nsnull, aDisplayDocument); AddExternalResource(clone, nsnull, nsnull, aDisplayDocument);
} else { } else {
NS_ADDREF(*aPendingLoad = load); load.forget(aPendingLoad);
} }
return nsnull; return nsnull;

View File

@@ -147,12 +147,15 @@ public:
NS_DECL_NSISERIALIZABLE NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO NS_DECL_NSICLASSINFO
// Override Clone() and Equals() // Override CloneInternal() and EqualsInternal()
NS_IMETHOD Clone(nsIURI** aClone); virtual nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
NS_IMETHOD Equals(nsIURI* aOther, PRBool *aResult); nsIURI** aClone);
virtual nsresult EqualsInternal(nsIURI* aOther,
RefHandlingEnum aRefHandlingMode,
PRBool* aResult);
// Override StartClone to hand back a nsFileDataURI // Override StartClone to hand back a nsFileDataURI
virtual nsSimpleURI* StartClone() virtual nsSimpleURI* StartClone(RefHandlingEnum /* unused */)
{ return new nsFileDataURI(); } { return new nsFileDataURI(); }
nsCOMPtr<nsIPrincipal> mPrincipal; nsCOMPtr<nsIPrincipal> mPrincipal;
@@ -213,12 +216,13 @@ nsFileDataURI::Write(nsIObjectOutputStream* aStream)
} }
// nsIURI methods: // nsIURI methods:
nsresult
NS_IMETHODIMP nsFileDataURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
nsFileDataURI::Clone(nsIURI** aClone) nsIURI** aClone)
{ {
nsCOMPtr<nsIURI> simpleClone; nsCOMPtr<nsIURI> simpleClone;
nsresult rv = nsSimpleURI::Clone(getter_AddRefs(simpleClone)); nsresult rv =
nsSimpleURI::CloneInternal(aRefHandlingMode, getter_AddRefs(simpleClone));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG #ifdef DEBUG
@@ -236,8 +240,10 @@ nsFileDataURI::Clone(nsIURI** aClone)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP /* virtual */ nsresult
nsFileDataURI::Equals(nsIURI* aOther, PRBool *aResult) nsFileDataURI::EqualsInternal(nsIURI* aOther,
nsSimpleURI::RefHandlingEnum aRefHandlingMode,
PRBool* aResult)
{ {
if (!aOther) { if (!aOther) {
*aResult = PR_FALSE; *aResult = PR_FALSE;
@@ -258,7 +264,8 @@ nsFileDataURI::Equals(nsIURI* aOther, PRBool *aResult)
return NS_OK; return NS_OK;
} }
return nsSimpleURI::Equals(otherFileDataUri, aResult); return nsSimpleURI::EqualsInternal(otherFileDataUri, aRefHandlingMode,
aResult);
} }
// nsIClassInfo methods: // nsIClassInfo methods:

View File

@@ -1580,18 +1580,6 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
} }
// Bug 136580: Check for recursive frame loading // Bug 136580: Check for recursive frame loading
// pre-grab these for speed
nsCOMPtr<nsIURI> cloneURI;
rv = aURI->Clone(getter_AddRefs(cloneURI));
NS_ENSURE_SUCCESS(rv, rv);
// Bug 98158/193011: We need to ignore data after the #
nsCOMPtr<nsIURL> cloneURL(do_QueryInterface(cloneURI)); // QI can fail
if (cloneURL) {
rv = cloneURL->SetRef(EmptyCString());
NS_ENSURE_SUCCESS(rv,rv);
}
PRInt32 matchCount = 0; PRInt32 matchCount = 0;
treeItem->GetSameTypeParent(getter_AddRefs(parentAsItem)); treeItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
while (parentAsItem) { while (parentAsItem) {
@@ -1602,17 +1590,9 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
nsCOMPtr<nsIURI> parentURI; nsCOMPtr<nsIURI> parentURI;
parentAsNav->GetCurrentURI(getter_AddRefs(parentURI)); parentAsNav->GetCurrentURI(getter_AddRefs(parentURI));
if (parentURI) { if (parentURI) {
nsCOMPtr<nsIURI> parentClone; // Bug 98158/193011: We need to ignore data after the #
rv = parentURI->Clone(getter_AddRefs(parentClone));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURL> parentURL(do_QueryInterface(parentClone));
if (parentURL) {
rv = parentURL->SetRef(EmptyCString());
NS_ENSURE_SUCCESS(rv,rv);
}
PRBool equal; PRBool equal;
rv = cloneURI->Equals(parentClone, &equal); rv = aURI->EqualsExceptRef(parentURI, &equal);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (equal) { if (equal) {

View File

@@ -2161,6 +2161,7 @@ nsNodeSelectorTearoff::QuerySelectorAll(const nsAString& aSelector,
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsGenericElement::nsDOMSlots::nsDOMSlots() nsGenericElement::nsDOMSlots::nsDOMSlots()
: nsINode::nsSlots(), : nsINode::nsSlots(),
mDataset(nsnull),
mBindingParent(nsnull) mBindingParent(nsnull)
{ {
} }

View File

@@ -66,6 +66,7 @@
#include "nsIDOMNodeSelector.h" #include "nsIDOMNodeSelector.h"
#include "nsIDOMXPathNSResolver.h" #include "nsIDOMXPathNSResolver.h"
#include "nsPresContext.h" #include "nsPresContext.h"
#include "nsIDOMDOMStringMap.h"
#ifdef MOZ_SMIL #ifdef MOZ_SMIL
#include "nsISMILAttr.h" #include "nsISMILAttr.h"
@@ -934,9 +935,16 @@ public:
/** /**
* The .style attribute (an interface that forwards to the actual * The .style attribute (an interface that forwards to the actual
* style rules) * style rules)
* @see nsGenericHTMLElement::GetStyle */ * @see nsGenericHTMLElement::GetStyle
*/
nsCOMPtr<nsICSSDeclaration> mStyle; nsCOMPtr<nsICSSDeclaration> mStyle;
/**
* The .dataset attribute.
* @see nsGenericHTMLElement::GetDataset
*/
nsIDOMDOMStringMap* mDataset; // [Weak]
/** /**
* SMIL Overridde style rules (for SMIL animation of CSS properties) * SMIL Overridde style rules (for SMIL animation of CSS properties)
* @see nsIContent::GetSMILOverrideStyle * @see nsIContent::GetSMILOverrideStyle

View File

@@ -380,6 +380,7 @@ GK_ATOM(flip, "flip")
GK_ATOM(floating, "floating") GK_ATOM(floating, "floating")
GK_ATOM(floatList, "Float-list") GK_ATOM(floatList, "Float-list")
GK_ATOM(floor, "floor") GK_ATOM(floor, "floor")
GK_ATOM(flowlength, "flowlength")
GK_ATOM(focus, "focus") GK_ATOM(focus, "focus")
GK_ATOM(following, "following") GK_ATOM(following, "following")
GK_ATOM(followingSibling, "following-sibling") GK_ATOM(followingSibling, "following-sibling")

View File

@@ -423,11 +423,12 @@ IsSupportedImage(const nsCString& aMimeType)
static PRBool static PRBool
IsSupportedPlugin(const nsCString& aMIMEType) IsSupportedPlugin(const nsCString& aMIMEType)
{ {
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
if (!host) { nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
return PR_FALSE; return PR_FALSE;
} }
nsresult rv = host->IsPluginEnabledForType(aMIMEType.get()); nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get());
return NS_SUCCEEDED(rv); return NS_SUCCEEDED(rv);
} }
@@ -458,13 +459,18 @@ IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
nsCAutoString ext; nsCAutoString ext;
GetExtensionFromURI(uri, ext); GetExtensionFromURI(uri, ext);
if (ext.IsEmpty()) if (ext.IsEmpty()) {
return PR_FALSE; return PR_FALSE;
}
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
return PR_FALSE;
}
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
const char* typeFromExt; const char* typeFromExt;
if (host && if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
NS_SUCCEEDED(host->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
mimeType = typeFromExt; mimeType = typeFromExt;
return PR_TRUE; return PR_TRUE;
} }
@@ -1722,8 +1728,8 @@ nsresult
nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID, nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
nsACString& aType) nsACString& aType)
{ {
// Need a plugin host for any class id support nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) { if (!pluginHost) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
@@ -1962,11 +1968,13 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
/* static */ PluginSupportState /* static */ PluginSupportState
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType) nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
{ {
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)); nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
if (!host) { nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
return ePluginUnsupported; return ePluginUnsupported;
} }
nsresult rv = host->IsPluginEnabledForType(aContentType.get());
nsresult rv = pluginHost->IsPluginEnabledForType(aContentType.get());
if (rv == NS_ERROR_PLUGIN_DISABLED) if (rv == NS_ERROR_PLUGIN_DISABLED)
return ePluginDisabled; return ePluginDisabled;
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED) if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
@@ -2008,18 +2016,6 @@ nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element,
nsIDOMClientRect* position,
nsIDOMClientRect* clip)
{
nsIObjectFrame* frame = GetExistingFrame(eFlushLayout);
if (!frame)
return NS_ERROR_NOT_AVAILABLE;
return frame->SetAbsoluteScreenPosition(element, position, clip);
}
NS_IMETHODIMP NS_IMETHODIMP
nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag, nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
const nsAString& pluginDumpID, const nsAString& pluginDumpID,

View File

@@ -40,7 +40,6 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsBindingManager.h" #include "nsBindingManager.h"
#include "nsIURL.h"
#include "nsEscape.h" #include "nsEscape.h"
#include "nsXBLPrototypeBinding.h" #include "nsXBLPrototypeBinding.h"
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
@@ -48,50 +47,23 @@
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
static PRBool EqualExceptRef(nsIURL* aURL1, nsIURL* aURL2)
{
nsCOMPtr<nsIURI> u1;
nsCOMPtr<nsIURI> u2;
nsresult rv = aURL1->Clone(getter_AddRefs(u1));
if (NS_SUCCEEDED(rv)) {
rv = aURL2->Clone(getter_AddRefs(u2));
}
if (NS_FAILED(rv))
return PR_FALSE;
nsCOMPtr<nsIURL> url1 = do_QueryInterface(u1);
nsCOMPtr<nsIURL> url2 = do_QueryInterface(u2);
if (!url1 || !url2) {
NS_WARNING("Cloning a URL produced a non-URL");
return PR_FALSE;
}
url1->SetRef(EmptyCString());
url2->SetRef(EmptyCString());
PRBool equal;
rv = url1->Equals(url2, &equal);
return NS_SUCCEEDED(rv) && equal;
}
void void
nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI, nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
PRBool aWatch, PRBool aReferenceImage) PRBool aWatch, PRBool aReferenceImage)
{ {
NS_ABORT_IF_FALSE(aFromContent, "Reset() expects non-null content pointer");
NS_ABORT_IF_FALSE(aURI, "Reset() expects non-null URI for referenced elem");
Unlink(); Unlink();
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (!url)
return;
nsCAutoString refPart; nsCAutoString refPart;
url->GetRef(refPart); aURI->GetRef(refPart);
// Unescape %-escapes in the reference. The result will be in the // Unescape %-escapes in the reference. The result will be in the
// origin charset of the URL, hopefully... // origin charset of the URL, hopefully...
NS_UnescapeURL(refPart); NS_UnescapeURL(refPart);
nsCAutoString charset; nsCAutoString charset;
url->GetOriginCharset(charset); aURI->GetOriginCharset(charset);
nsAutoString ref; nsAutoString ref;
nsresult rv = nsContentUtils::ConvertStringFromCharset(charset, refPart, ref); nsresult rv = nsContentUtils::ConvertStringFromCharset(charset, refPart, ref);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@@ -109,9 +81,10 @@ nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
if (bindingParent) { if (bindingParent) {
nsXBLBinding* binding = doc->BindingManager()->GetBinding(bindingParent); nsXBLBinding* binding = doc->BindingManager()->GetBinding(bindingParent);
if (binding) { if (binding) {
nsCOMPtr<nsIURL> bindingDocumentURL = PRBool isEqualExceptRef;
do_QueryInterface(binding->PrototypeBinding()->DocURI()); rv = aURI->EqualsExceptRef(binding->PrototypeBinding()->DocURI(),
if (EqualExceptRef(url, bindingDocumentURL)) { &isEqualExceptRef);
if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
// XXX sXBL/XBL2 issue // XXX sXBL/XBL2 issue
// Our content is an anonymous XBL element from a binding inside the // Our content is an anonymous XBL element from a binding inside the
// same document that the referenced URI points to. In order to avoid // same document that the referenced URI points to. In order to avoid
@@ -139,13 +112,12 @@ nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
} }
} }
nsCOMPtr<nsIURL> documentURL = do_QueryInterface(doc->GetDocumentURI()); PRBool isEqualExceptRef;
// We've already checked that |url| is an nsIURL. So if the document URI is rv = aURI->EqualsExceptRef(doc->GetDocumentURI(), &isEqualExceptRef);
// not an nsIURL then |url| is certainly not going to be pointing to the same if (NS_FAILED(rv) || !isEqualExceptRef) {
// document as the document URI.
if (!documentURL || !EqualExceptRef(url, documentURL)) {
nsRefPtr<nsIDocument::ExternalResourceLoad> load; nsRefPtr<nsIDocument::ExternalResourceLoad> load;
doc = doc->RequestExternalResource(url, aFromContent, getter_AddRefs(load)); doc = doc->RequestExternalResource(aURI, aFromContent,
getter_AddRefs(load));
if (!doc) { if (!doc) {
if (!load || !aWatch) { if (!load || !aWatch) {
// Nothing will ever happen here // Nothing will ever happen here

File diff suppressed because it is too large Load Diff

View File

@@ -50,7 +50,6 @@
#include "nsIDOMEventListener.h" #include "nsIDOMEventListener.h"
#include "nsDOMEventTargetWrapperCache.h" #include "nsDOMEventTargetWrapperCache.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsIProxiedProtocolHandler.h"
#define DEFAULT_WS_SCHEME_PORT 80 #define DEFAULT_WS_SCHEME_PORT 80
#define DEFAULT_WSS_SCHEME_PORT 443 #define DEFAULT_WSS_SCHEME_PORT 443
@@ -101,8 +100,6 @@ public:
PRBool aWantsUntrusted, PRBool aWantsUntrusted,
PRUint8 optional_argc); PRUint8 optional_argc);
static void ReleaseGlobals();
// Determine if preferences allow WebSocket // Determine if preferences allow WebSocket
static PRBool PrefEnabled(); static PRBool PrefEnabled();
@@ -116,7 +113,7 @@ protected:
nsresult EstablishConnection(); nsresult EstablishConnection();
nsresult CreateAndDispatchSimpleEvent(const nsString& aName); nsresult CreateAndDispatchSimpleEvent(const nsString& aName);
nsresult CreateAndDispatchMessageEvent(nsCString *aData); nsresult CreateAndDispatchMessageEvent(const nsACString& aData);
nsresult CreateAndDispatchCloseEvent(PRBool aWasClean); nsresult CreateAndDispatchCloseEvent(PRBool aWasClean);
// called from mConnection accordingly to the situation // called from mConnection accordingly to the situation
@@ -147,7 +144,8 @@ protected:
nsCString mAsciiHost; // hostname nsCString mAsciiHost; // hostname
PRUint32 mPort; PRUint32 mPort;
nsCString mResource; // [filepath[?query]] nsCString mResource; // [filepath[?query]]
nsCString mOrigin; nsString mUTF16Origin;
nsCOMPtr<nsIURI> mURI; nsCOMPtr<nsIURI> mURI;
nsCString mProtocol; nsCString mProtocol;
@@ -175,44 +173,4 @@ private:
nsWebSocket& operator=(const nsWebSocket& x); nsWebSocket& operator=(const nsWebSocket& x);
}; };
#define NS_WSPROTOCOLHANDLER_CONTRACTID \
NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ws"
#define NS_WSSPROTOCOLHANDLER_CONTRACTID \
NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "wss"
#define NS_WSPROTOCOLHANDLER_CID \
{ /* a4e6aa3b-b6db-4809-aa11-e292e074cbc4 */ \
0xa4e6aa3b, \
0xb6db, \
0x4809, \
{0xaa, 0x11, 0xe2, 0x92, 0xe0, 0x74, 0xcb, 0xc4} \
}
#define NS_WSSPROTOCOLHANDLER_CID \
{ /* c6531804-b5c8-4a53-80bf-e339b82d3161 */ \
0xc6531804, \
0xb5c8, \
0x4a53, \
{0x80, 0xbf, 0xe3, 0x39, 0xb8, 0x2d, 0x31, 0x61} \
}
class nsWSProtocolHandler: public nsIProxiedProtocolHandler
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
NS_DECL_NSIPROXIEDPROTOCOLHANDLER
nsWSProtocolHandler() {};
};
class nsWSSProtocolHandler: public nsWSProtocolHandler
{
public:
NS_IMETHOD GetScheme(nsACString & aScheme);
NS_IMETHOD GetDefaultPort(PRInt32 *aDefaultPort);
nsWSSProtocolHandler() {};
};
#endif #endif

View File

@@ -481,6 +481,8 @@ _TEST_FILES2 = \
bug638112-response.txt \ bug638112-response.txt \
bug638112.sjs \ bug638112.sjs \
test_bug656283.html \ test_bug656283.html \
test_blobbuilder.html \
fileutils.js \
$(NULL) $(NULL)
# This test fails on the Mac for some reason # This test fails on the Mac for some reason

View File

@@ -6,6 +6,9 @@ import sys
# see the list of tests in test_websocket.html # see the list of tests in test_websocket.html
def web_socket_do_extra_handshake(request): def web_socket_do_extra_handshake(request):
# must set request.ws_protocol to the selected version from ws_requested_protocols
request.ws_protocol = request.ws_requested_protocols[0]
if request.ws_protocol == "test 2.1": if request.ws_protocol == "test 2.1":
time.sleep(5) time.sleep(5)
pass pass
@@ -42,6 +45,7 @@ def web_socket_transfer_data(request):
if msgutil.receive_message(request) == "5": if msgutil.receive_message(request) == "5":
resp = "あいうえお" resp = "あいうえお"
msgutil.send_message(request, resp.decode('utf-8')) msgutil.send_message(request, resp.decode('utf-8'))
msgutil.close_connection(request)
elif request.ws_protocol == "test 7": elif request.ws_protocol == "test 7":
try: try:
while not request.client_terminated: while not request.client_terminated:
@@ -62,6 +66,9 @@ def web_socket_transfer_data(request):
if msgutil.receive_message(request) == "client data": if msgutil.receive_message(request) == "client data":
resp = "server data" resp = "server data"
msgutil.send_message(request, resp.decode('utf-8')) msgutil.send_message(request, resp.decode('utf-8'))
msgutil.close_connection(request)
elif request.ws_protocol == "test 12":
msgutil.close_connection(request)
elif request.ws_protocol == "test 13": elif request.ws_protocol == "test 13":
# first one binary message containing the byte 0x61 ('a') # first one binary message containing the byte 0x61 ('a')
request.connection.write('\xff\x01\x61') request.connection.write('\xff\x01\x61')
@@ -69,7 +76,7 @@ def web_socket_transfer_data(request):
request.connection.write('\x01\x61\xff') request.connection.write('\x01\x61\xff')
msgutil.close_connection(request) msgutil.close_connection(request)
elif request.ws_protocol == "test 14": elif request.ws_protocol == "test 14":
request.connection.write('\xff\x00') msgutil.close_connection(request)
msgutil.send_message(request, "server data") msgutil.send_message(request, "server data")
elif request.ws_protocol == "test 15": elif request.ws_protocol == "test 15":
msgutil.close_connection(request, True) msgutil.close_connection(request, True)

View File

@@ -1,6 +1,9 @@
from mod_pywebsocket import msgutil from mod_pywebsocket import msgutil
def web_socket_do_extra_handshake(request): def web_socket_do_extra_handshake(request):
# must set request.ws_protocol to the selected version from ws_requested_protocols
request.ws_protocol = request.ws_requested_protocols[0]
if (request.ws_protocol == 'error'): if (request.ws_protocol == 'error'):
raise ValueError('Error') raise ValueError('Error')
pass pass

View File

@@ -0,0 +1,272 @@
// Utility functions
var testRanCounter = 0;
var expectedTestCount = 0;
function testHasRun() {
//alert(testRanCounter);
++testRanCounter;
if (testRanCounter == expectedTestCount) {
SimpleTest.finish();
}
}
function testFile(file, contents, test) {
SimpleTest.requestLongerTimeout(2);
// Load file using FileReader
var r = new FileReader();
r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test);
r.readAsBinaryString(file);
expectedTestCount++;
// Load file using URL.createObjectURL and XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("GET", URL.createObjectURL(file));
xhr.onload = getXHRLoadHandler(contents, contents.length, false,
"XMLHttpRequest load of " + test);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send();
expectedTestCount++;
// Send file to server using FormData and XMLHttpRequest
xhr = new XMLHttpRequest();
xhr.onload = function(event) {
checkMPSubmission(JSON.parse(event.target.responseText),
[{ name: "hello", value: "world"},
{ name: "myfile",
value: contents,
fileName: file.name || "",
contentType: file.type || "application/octet-stream" }]);
testHasRun();
}
xhr.open("POST", "../../html/content/test/form_submit_server.sjs");
var fd = new FormData;
fd.append("hello", "world");
fd.append("myfile", file);
xhr.send(fd);
expectedTestCount++;
// Send file to server using plain XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("POST", "file_XHRSendData.sjs");
xhr.onload = function (event) {
is(event.target.getResponseHeader("Result-Content-Type"),
file.type ? file.type : null,
"request content-type in XMLHttpRequest send of " + test);
is(event.target.getResponseHeader("Result-Content-Length"),
file.size,
"request content-length in XMLHttpRequest send of " + test);
};
xhr.addEventListener("load",
getXHRLoadHandler(contents, contents.length, true,
"XMLHttpRequest send of " + test),
false);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send(file);
expectedTestCount++;
}
function getFileReaderLoadHandler(expectedResult, expectedLength, testName) {
return function (event) {
is(event.target.readyState, FileReader.DONE,
"[FileReader] readyState in test " + testName);
is(event.target.error, null,
"[FileReader] no error in test " + testName);
// Do not use |is(event.target.result, expectedResult, "...");| that may output raw binary data.
is(event.target.result.length, expectedResult.length,
"[FileReader] Length of result in test " + testName);
ok(event.target.result == expectedResult,
"[FileReader] Content of result in test " + testName);
is(event.lengthComputable, true,
"[FileReader] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[FileReader] Loaded length in test " + testName);
is(event.total, expectedLength,
"[FileReader] Total length in test " + testName);
testHasRun();
}
}
function getXHRLoadHandler(expectedResult, expectedLength, statusWorking, testName) {
return function (event) {
is(event.target.readyState, 4,
"[XHR] readyState in test " + testName);
if (statusWorking) {
is(event.target.status, 200,
"[XHR] no error in test " + testName);
}
else {
todo(event.target.status, 200,
"[XHR] no error in test " + testName);
}
// Do not use |is(convertXHRBinary(event.target.responseText), expectedResult, "...");| that may output raw binary data.
var convertedData = convertXHRBinary(event.target.responseText);
is(convertedData.length, expectedResult.length,
"[XHR] Length of result in test " + testName);
ok(convertedData == expectedResult,
"[XHR] Content of result in test " + testName);
is(event.lengthComputable, true,
"[XHR] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[XHR] Loaded length in test " + testName);
is(event.total, expectedLength,
"[XHR] Total length in test " + testName);
testHasRun();
}
}
function convertXHRBinary(s) {
var res = "";
for (var i = 0; i < s.length; ++i) {
res += String.fromCharCode(s.charCodeAt(i) & 255);
}
return res;
}
function testHasRun() {
//alert(testRanCounter);
++testRanCounter;
if (testRanCounter == expectedTestCount) {
SimpleTest.finish();
}
}
function createFileWithData(fileData) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append("fileAPItestfile2-" + fileNum);
fileNum++;
var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
return fileList.files[0];
}
function gc() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
function checkMPSubmission(sub, expected) {
function getPropCount(o) {
var x, l = 0;
for (x in o) ++l;
return l;
}
is(sub.length, expected.length,
"Correct number of items");
var i;
for (i = 0; i < expected.length; ++i) {
if (!("fileName" in expected[i])) {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"",
"Correct name (A)");
is (getPropCount(sub[i].headers), 1,
"Wrong number of headers (A)");
}
else {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"; filename=\"" +
expected[i].fileName + "\"",
"Correct name (B)");
is(sub[i].headers["Content-Type"],
expected[i].contentType,
"Correct content type (B)");
is (getPropCount(sub[i].headers), 2,
"Wrong number of headers (B)");
}
// Do not use |is(sub[i].body, expected[i].value, "...");| that may output raw binary data.
is(sub[i].body.length, expected[i].value.length,
"Length of correct value");
ok(sub[i].body == expected[i].value,
"Content of correct value");
}
}
function testSlice(file, size, type, contents, fileType) {
is(file.type, type, fileType + " file is correct type");
is(file.size, size, fileType + " file is correct size");
ok(file instanceof File, fileType + " file is a File");
ok(file instanceof Blob, fileType + " file is also a Blob");
var slice = file.mozSlice(0, size);
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
slice = file.mozSlice(0, 1234);
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
ok(!(slice instanceof File), fileType + " sized slice is not a File");
slice = file.mozSlice(0, size, "foo/bar");
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
slice = file.mozSlice(0, 5432, "foo/bar");
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
var indexes = [[0, size, size],
[0, 1234, 1234],
[size-500, size, 500],
[size-500, size+500, 500],
[size+500, size+1500, 0],
[0, 0, 0],
[1000, 1000, 0],
[size, size, 0],
[0, undefined, size],
[100, undefined, size-100],
[-100, undefined, 100],
[100, -100, size-200],
[-size-100, undefined, size],
[-2*size-100, 500, 500],
[0, -size-100, 0],
[100, -size-100, 0],
[50, -size+100, 50],
[0, 33000, 33000],
[1000, 34000, 33000],
];
for (var i = 0; i < indexes.length; ++i) {
var sliceContents;
var testName;
if (indexes[i][1] == undefined) {
slice = file.mozSlice(indexes[i][0]);
sliceContents = contents.slice(indexes[i][0]);
testName = fileType + " slice(" + indexes[i][0] + ")";
}
else {
slice = file.mozSlice(indexes[i][0], indexes[i][1]);
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
}
is(slice.type, "", testName + " type");
is(slice.size, indexes[i][2], testName + " size");
is(sliceContents.length, indexes[i][2], testName + " data size");
testFile(slice, sliceContents, testName);
}
// Slice of slice
var slice = file.mozSlice(0, 40000);
testFile(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
// ...of slice of slice
slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
SpecialPowers.gc();
testFile(slice, contents.slice(5400, 5700), "file slice slice slice");
}

View File

@@ -419,6 +419,15 @@ function runTest() {
}, },
]; ];
for (let i = 0; i < 110; i++) {
tests.push({ newTest: "*******" },
{ pass: 1,
method: "DELETE",
allowMethods: "DELETE",
cacheTime: 3600,
});
}
baseURL = "http://mochi.test:8888/tests/content/base/test/" + baseURL = "http://mochi.test:8888/tests/content/base/test/" +
"file_CrossSiteXHR_cache_server.sjs?"; "file_CrossSiteXHR_cache_server.sjs?";
setStateURL = baseURL + "setState="; setStateURL = baseURL + "setState=";

View File

@@ -0,0 +1,135 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=648997
-->
<head>
<title>Test for Bug 648997</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="fileutils.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=648997">Mozilla Bug 648997</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript;version=1.7">
// We're prefixing still
window.BlobBuilder = window.MozBlobBuilder;
/** Test for Bug 648997 **/
var blobBuilder = BlobBuilder();
ok(blobBuilder, "BlobBuilder should exist");
ok(blobBuilder.append, "BlobBuilder should have an append method");
ok(blobBuilder.getBlob, "BlobBuilder should have a getBlob method");
try {
blobBuilder.append();
ok(false, "NOT REACHED");
} catch(e) {
ok(true, "an empty argument to append should throw");
}
blobBuilder.append("squiggle");
let blob1 = blobBuilder.getBlob();
blobBuilder.append("ohai");
let blob2 = blobBuilder.getBlob();
let aB = new ArrayBuffer(16);
var int8View = new Int8Array(aB);
for (var i = 0; i < 16; i++) {
int8View[i] = i+65;
}
let testData =
[
// Test 3 strings
[["foo", "bar", "baz"], [{start: 0, length: 9, contents: "foobarbaz"},
{start: 0, length: 3, contents: "foo"},
{start: 3, length:6, contents: "barbaz"},
{start: 6, length: 3, contents: "baz"},
{start: 6, length: 6, elength: 3, contents: "baz"},
{start: 0, length: 9, contents: "foobarbaz"},
{start: 0, length: 11, elength: 9, contents: "foobarbaz"},
{start: 10, length: 5, elength: 0, contents: ""}]],
// Test string, Blob, string
[["foo", blob1, "baz"], [{start: 0, length: 3, contents: "foo"},
{start: 3, length: 8, contents: "squiggle"},
{start: 2, length: 2, contents: "os"},
{start: 10, length: 2, contents: "eb"}]],
// Test blob, string, blob
[[blob1, "foo", blob1], [{start: 0, length: 8, contents: "squiggle"},
{start: 7, length: 2, contents: "ef"},
{start: 10, length: 2, contents: "os"},
{start: 1, length: 3, contents: "qui"},
{start: 12, length: 3, contents: "qui"},
{start: 40, length: 20, elength: 0, contents: ""}]],
// Test blobs all the way down
[[blob2, blob1, blob2], [{start: 0, length: 4, contents: "ohai"},
{start: 4, length: 8, contents: "squiggle"},
{start: 12, length: 4, contents: "ohai"},
{start: 1, length: 2, contents: "ha"},
{start: 5, length: 4, contents: "quig"}]],
// Test an array buffer
[[aB, blob1, "foo"], [{start: 0, length: 8, contents: "ABCDEFGH"},
{start: 8, length:10, contents: "IJKLMNOPsq"},
{start: 17, length: 3, contents: "qui"},
{start: 4, length: 8, contents: "EFGHIJKL"}]],
// Test type coercion of a number
[[3, aB, "foo"], [{start: 0, length: 8, contents: "3ABCDEFG"},
{start: 8, length:10, contents: "HIJKLMNOPf"},
{start: 17, length: 4, elength: 3, contents: "foo"},
{start: 4, length: 8, contents: "DEFGHIJK"}]]
];
let testCounter = 0;
function doTest(data) {
testCounter++;
[blobs, tests] = data;
function runTest(test) {
let bb = new BlobBuilder();
ok(bb, "BlobBuilder should exist");
function doAppend(blob) {
bb.append(blob);
blob.expando = bb; // Do we leak?
}
blobs.forEach(doAppend);
ok(true, "Test " + testCounter + " appended all successfully");
let blob = bb.getBlob();
ok(blob, "Test " + testCounter + " got blob");
ok(blob instanceof Blob, "Test " + testCounter + " blob is a Blob");
//ok(!(blob instanceof File), "Test " + testCounter + " blob is not a File");
let slice = blob.mozSlice(test.start, test.start + test.length);
ok(slice, "Test " + testCounter + " got slice");
ok(slice instanceof Blob, "Test " + testCounter + " slice is a Blob");
//ok(!(slice instanceof File), "Test " + testCounter + " slice is not a File");
is(slice.size,"elength" in test ? test.elength : test.length,
"Test " + testCounter + " slice is correct size");
testFile(slice, test.contents, "Test " + testCounter,
"elength" in test ? test.elength : test.length);
}
tests.forEach(runTest);
SpecialPowers.gc();
}
SimpleTest.waitForExplicitFinish();
testData.forEach(doTest);
</script>
</pre>
</body>
</html>

View File

@@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=575946
<title>Test for Bug 575946</title> <title>Test for Bug 575946</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script> <script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="fileutils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head> </head>
@@ -23,8 +24,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=575946
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
var fileNum = 1; var fileNum = 1;
var testRanCounter = 0;
var expectedTestCount = 0;
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
// Create files containing data we'll test with. We'll want long // Create files containing data we'll test with. We'll want long
@@ -69,83 +68,8 @@ ok(size > 65536, "test data sufficiently large");
// Test that basic properties work // Test that basic properties work
function testFile(file, size, type, contents, fileType) { testSlice(memFile, size, "image/png", fileData, "memFile");
is(file.type, type, fileType + " file is correct type"); testSlice(fileFile, size, "", fileData, "fileFile");
is(file.size, size, fileType + " file is correct size");
ok(file instanceof File, fileType + " file is a File");
ok(file instanceof Blob, fileType + " file is also a Blob");
var slice = file.mozSlice(0, size);
ok(slice instanceof Blob, fileType + " fullsize slice is a Blob");
ok(!(slice instanceof File), fileType + " fullsize slice is not a File");
slice = file.mozSlice(0, 1234);
ok(slice instanceof Blob, fileType + " sized slice is a Blob");
ok(!(slice instanceof File), fileType + " sized slice is not a File");
slice = file.mozSlice(0, size, "foo/bar");
is(slice.type, "foo/bar", fileType + " fullsize slice foo/bar type");
slice = file.mozSlice(0, 5432, "foo/bar");
is(slice.type, "foo/bar", fileType + " sized slice foo/bar type");
is(slice.mozSlice(0, 10).type, "", fileType + " slice-slice type");
is(slice.mozSlice(0, 10).size, 10, fileType + " slice-slice size");
is(slice.mozSlice(0, 10, "hello/world").type, "hello/world", fileType + " slice-slice hello/world type");
is(slice.mozSlice(0, 10, "hello/world").size, 10, fileType + " slice-slice hello/world size");
var indexes = [[0, size, size],
[0, 1234, 1234],
[size-500, size, 500],
[size-500, size+500, 500],
[size+500, size+1500, 0],
[0, 0, 0],
[1000, 1000, 0],
[size, size, 0],
[0, undefined, size],
[100, undefined, size-100],
[-100, undefined, 100],
[100, -100, size-200],
[-size-100, undefined, size],
[-2*size-100, 500, 500],
[0, -size-100, 0],
[100, -size-100, 0],
[50, -size+100, 50],
[0, 33000, 33000],
[1000, 34000, 33000],
];
for (var i = 0; i < indexes.length; ++i) {
var sliceContents;
var testName;
if (indexes[i][1] == undefined) {
slice = file.mozSlice(indexes[i][0]);
sliceContents = contents.slice(indexes[i][0]);
testName = fileType + " slice(" + indexes[i][0] + ")";
}
else {
slice = file.mozSlice(indexes[i][0], indexes[i][1]);
sliceContents = contents.slice(indexes[i][0], indexes[i][1]);
testName = fileType + " slice(" + indexes[i][0] + ", " + indexes[i][1] + ")";
}
is(slice.type, "", testName + " type");
is(slice.size, indexes[i][2], testName + " size");
is(sliceContents.length, indexes[i][2], testName + " data size");
checkFileContents(slice, sliceContents, testName);
}
// Slice of slice
var slice = file.mozSlice(0, 40000);
checkFileContents(slice.mozSlice(5000, 42000), contents.slice(5000, 40000), "file slice slice");
// ...of slice of slice
slice = slice.mozSlice(5000, 42000).mozSlice(400, 700);
gc();
checkFileContents(slice, contents.slice(5400, 5700), "file slice slice slice");
}
testFile(memFile, size, "image/png", fileData, "memFile");
testFile(fileFile, size, "", fileData, "fileFile");
// Try loading directly from slice into an image // Try loading directly from slice into an image
@@ -209,192 +133,6 @@ img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinary
img.onload = imageLoadHandler; img.onload = imageLoadHandler;
expectedTestCount++; expectedTestCount++;
// Utility functions
function checkFileContents(file, contents, test) {
SimpleTest.requestLongerTimeout(2);
// Load file using FileReader
var r = new FileReader();
r.onload = getFileReaderLoadHandler(contents, contents.length, "FileReader.readAsBinaryString of " + test);
r.readAsBinaryString(file);
expectedTestCount++;
// Load file using URL.createObjectURL and XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("GET", URL.createObjectURL(file));
xhr.onload = getXHRLoadHandler(contents, contents.length, false,
"XMLHttpRequest load of " + test);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send();
expectedTestCount++;
// Send file to server using FormData and XMLHttpRequest
xhr = new XMLHttpRequest();
xhr.onload = function(event) {
checkMPSubmission(JSON.parse(event.target.responseText),
[{ name: "hello", value: "world"},
{ name: "myfile",
value: contents,
fileName: file.name || "",
contentType: file.type || "application/octet-stream" }]);
testHasRun();
}
xhr.open("POST", "../../html/content/test/form_submit_server.sjs");
var fd = new FormData;
fd.append("hello", "world");
fd.append("myfile", file);
xhr.send(fd);
expectedTestCount++;
// Send file to server using plain XMLHttpRequest
var xhr = new XMLHttpRequest;
xhr.open("POST", "file_XHRSendData.sjs");
xhr.onload = function (event) {
is(event.target.getResponseHeader("Result-Content-Type"),
file.type ? file.type : null,
"request content-type in XMLHttpRequest send of " + test);
is(event.target.getResponseHeader("Result-Content-Length"),
file.size,
"request content-length in XMLHttpRequest send of " + test);
};
xhr.addEventListener("load",
getXHRLoadHandler(contents, contents.length, true,
"XMLHttpRequest send of " + test),
false);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.send(file);
expectedTestCount++;
}
function getFileReaderLoadHandler(expectedResult, expectedLength, testName) {
return function (event) {
is(event.target.readyState, FileReader.DONE,
"[FileReader] readyState in test " + testName);
is(event.target.error, null,
"[FileReader] no error in test " + testName);
// Do not use |is(event.target.result, expectedResult, "...");| that may output raw binary data.
is(event.target.result.length, expectedResult.length,
"[FileReader] Length of result in test " + testName);
ok(event.target.result == expectedResult,
"[FileReader] Content of result in test " + testName);
is(event.lengthComputable, true,
"[FileReader] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[FileReader] Loaded length in test " + testName);
is(event.total, expectedLength,
"[FileReader] Total length in test " + testName);
testHasRun();
}
}
function getXHRLoadHandler(expectedResult, expectedLength, statusWorking, testName) {
return function (event) {
is(event.target.readyState, 4,
"[XHR] readyState in test " + testName);
if (statusWorking) {
is(event.target.status, 200,
"[XHR] no error in test " + testName);
}
else {
todo(event.target.status, 200,
"[XHR] no error in test " + testName);
}
// Do not use |is(convertXHRBinary(event.target.responseText), expectedResult, "...");| that may output raw binary data.
var convertedData = convertXHRBinary(event.target.responseText);
is(convertedData.length, expectedResult.length,
"[XHR] Length of result in test " + testName);
ok(convertedData == expectedResult,
"[XHR] Content of result in test " + testName);
is(event.lengthComputable, true,
"[XHR] lengthComputable in test " + testName);
is(event.loaded, expectedLength,
"[XHR] Loaded length in test " + testName);
is(event.total, expectedLength,
"[XHR] Total length in test " + testName);
testHasRun();
}
}
function convertXHRBinary(s) {
var res = "";
for (var i = 0; i < s.length; ++i) {
res += String.fromCharCode(s.charCodeAt(i) & 255);
}
return res;
}
function testHasRun() {
//alert(testRanCounter);
++testRanCounter;
if (testRanCounter == expectedTestCount) {
SimpleTest.finish();
}
}
function createFileWithData(fileData) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
testFile.append("fileAPItestfile2-" + fileNum);
fileNum++;
var outStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
return fileList.files[0];
}
function gc() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
function checkMPSubmission(sub, expected) {
function getPropCount(o) {
var x, l = 0;
for (x in o) ++l;
return l;
}
is(sub.length, expected.length,
"Correct number of items");
var i;
for (i = 0; i < expected.length; ++i) {
if (!("fileName" in expected[i])) {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"",
"Correct name (A)");
is (getPropCount(sub[i].headers), 1,
"Wrong number of headers (A)");
}
else {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + expected[i].name + "\"; filename=\"" +
expected[i].fileName + "\"",
"Correct name (B)");
is(sub[i].headers["Content-Type"],
expected[i].contentType,
"Correct content type (B)");
is (getPropCount(sub[i].headers), 2,
"Wrong number of headers (B)");
}
// Do not use |is(sub[i].body, expected[i].value, "...");| that may output raw binary data.
is(sub[i].body.length, expected[i].value.length,
"Length of correct value");
ok(sub[i].body == expected[i].value,
"Content of correct value");
}
}
</script> </script>
</pre> </pre>
</body> </html> </body> </html>

View File

@@ -51,7 +51,6 @@ var last_test = 22;
var current_test = first_test; var current_test = first_test;
var timeoutToAbortTest = 60000; var timeoutToAbortTest = 60000;
var timeoutToOpenWS = 25000;
var all_ws = []; var all_ws = [];
function shouldNotOpen(e) function shouldNotOpen(e)
@@ -264,7 +263,7 @@ function test6()
ws.onmessage = function(e) ws.onmessage = function(e)
{ {
if (counter == 5) { if (counter == 5) {
ok(e.data == "あいうえお"); ok(e.data == "あいうえお", "test 6 counter 5 data ok");
ws.close(); ws.close();
doTest(7); doTest(7);
} else { } else {
@@ -278,16 +277,25 @@ function test6()
function test7() function test7()
{ {
var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 7"); // with pywebsockets for -06 ths test no longer does anything useful
ws.onopen = function() // as the server handles the receipt of the close event directly, not
{ // as part of the wsh - so we cannot fake the non-clean close which is
ws.close(); // what we're trying to do here.
}
ws.onclose = function(e) ok(true, "test disabled");
{ current_test++;
shouldCloseNotCleanly(e); doTest(8);
doTest(8);
}; // var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 7");
// ws.onopen = function()
// {
// ws.close();
// }
// ws.onclose = function(e)
// {
// shouldCloseNotCleanly(e);
// doTest(8);
// };
} }
function test8() function test8()
@@ -338,21 +346,24 @@ function test10()
function test11() function test11()
{ {
var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 11"); var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 11");
ok(ws.readyState == 0, "bad readyState in test 11!"); ok(ws.readyState == 0, "create bad readyState in test 11!");
ws.onopen = function() ws.onopen = function()
{ {
ok(ws.readyState == 1, "bad readyState in test 11!"); ok(ws.readyState == 1, "open bad readyState in test 11!");
ws.send("client data"); ws.send("client data");
} }
ws.onmessage = function(e) ws.onmessage = function(e)
{ {
ok(e.data == "server data", "bad received message in test 11!"); ok(e.data == "server data", "bad received message in test 11!");
ws.close(); ws.close();
ok(ws.readyState == 2, "bad readyState in test 11!");
// this ok() is disabled due to a race condition - it state may have
// advanced through 2 (closing) and into 3 (closed) before it is evald
// ok(ws.readyState == 2, "onmessage bad readyState in test 11!");
} }
ws.onclose = function(e) ws.onclose = function(e)
{ {
ok(ws.readyState == 3, "bad readyState in test 11!"); ok(ws.readyState == 3, "onclose bad readyState in test 11!");
shouldCloseCleanly(e); shouldCloseCleanly(e);
doTest(12); doTest(12);
} }
@@ -372,23 +383,34 @@ function test12()
ok(true, "couldn't send an unpaired surrogate!"); ok(true, "couldn't send an unpaired surrogate!");
} }
ws.close(); ws.close();
// there isnt really a server implementation of test 12, so just
// ignore an error
ws.onerror = function()
{
}
doTest(13); doTest(13);
}; };
} }
function test13() function test13()
{ {
// previous versions of this test counted the number of protocol errors returned, but the
// protocol stack typically closes down after reporting a protocol level error - trying
// to resync is too dangerous
var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 13"); var ws = CreateTestWS("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test 13");
ws._timesCalledOnError = 0; ws._timesCalledOnError = 0;
ws.onerror = function() ws.onerror = function()
{ {
ws._timesCalledOnError++; ws._timesCalledOnError++;
if (ws._timesCalledOnError == 2) {
ok(true, "test 13 succeeded");
doTest(14);
}
} }
ws.onclose = shouldCloseCleanly; ws.onclose = function(e)
{
ok(ws._timesCalledOnError > 0, "no error events");
doTest(14);
}
} }
function test14() function test14()
@@ -413,6 +435,12 @@ function test15()
shouldCloseNotCleanly(e); shouldCloseNotCleanly(e);
doTest(16); doTest(16);
}; };
// termination of the connection might cause an error event if it happens in OPEN
ws.onerror = function()
{
}
} }
function test16() function test16()
@@ -428,7 +456,13 @@ function test16()
{ {
ok(false, "shouldn't send message after calling close()"); ok(false, "shouldn't send message after calling close()");
} }
ws.onclose = shouldCloseCleanly;
ws.onerror = function()
{
}
ws.onclose = function()
{
}
} }
var status_test17 = "not started"; var status_test17 = "not started";
@@ -593,9 +627,6 @@ function test22()
}; };
} }
var domBranch;
var oldPrefVal;
function finishWSTest() function finishWSTest()
{ {
for (i = 0; i < all_ws.length; ++i) { for (i = 0; i < all_ws.length; ++i) {
@@ -604,20 +635,11 @@ function finishWSTest()
ok(false, "didn't called close on test " + all_ws[i]._testNumber + "!"); ok(false, "didn't called close on test " + all_ws[i]._testNumber + "!");
} }
} }
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
domBranch.setBoolPref("override-security-block", oldPrefVal);
SimpleTest.finish(); SimpleTest.finish();
} }
function testWebSocket () function testWebSocket ()
{ {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var prefService =
Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
domBranch = prefService.getBranch("network.websocket.");
oldPrefVal = domBranch.getBoolPref("override-security-block");
domBranch.setBoolPref("override-security-block", true);
doTest(first_test); doTest(first_test);
} }

View File

@@ -17,24 +17,8 @@
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
var ws; var ws;
var oldPrefVal;
var domBranch;
function finishWSTest() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
domBranch.setBoolPref("override-security-block", oldPrefVal);
SimpleTest.finish();
}
function testWebSocket () { function testWebSocket () {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var prefService =
Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
domBranch = prefService.getBranch("network.websocket.");
oldPrefVal = domBranch.getBoolPref("override-security-block");
domBranch.setBoolPref("override-security-block", true);
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_hello"); ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_hello");
ws.onopen = function(e) { ws.onopen = function(e) {
ws.send("data"); ws.send("data");
@@ -43,12 +27,12 @@ function testWebSocket () {
} }
ws.onerror = function(e) { ws.onerror = function(e) {
ok(false, "onerror called!"); ok(false, "onerror called!");
finishWSTest(); SimpleTest.finish();
} }
ws.onmessage = function(e) { ws.onmessage = function(e) {
is(e.data, "Hello world!", "Wrong data"); is(e.data, "Hello world!", "Wrong data");
ws.close(); ws.close();
finishWSTest(); SimpleTest.finish();
} }
} }

View File

@@ -17,8 +17,6 @@
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
var ws; var ws;
var oldPrefVal;
var domBranch;
var params = ["protocol", "resource", "origin", "end"]; var params = ["protocol", "resource", "origin", "end"];
var results = ["test", "/tests/content/base/test/file_ws_basic_tests", "http://mochi.test:8888", "end"]; var results = ["test", "/tests/content/base/test/file_ws_basic_tests", "http://mochi.test:8888", "end"];
@@ -32,20 +30,10 @@ function forcegc(){
} }
function finishWSTest() { function finishWSTest() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
domBranch.setBoolPref("override-security-block", oldPrefVal);
SimpleTest.finish(); SimpleTest.finish();
} }
function testWebSocket () { function testWebSocket () {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var prefService =
Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
domBranch = prefService.getBranch("network.websocket.");
oldPrefVal = domBranch.getBoolPref("override-security-block");
domBranch.setBoolPref("override-security-block", true);
var url = "ws://mochi.test:8888/tests/content/base/test/file_ws_basic_tests"; var url = "ws://mochi.test:8888/tests/content/base/test/file_ws_basic_tests";
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_ws_basic_tests", "test"); ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_ws_basic_tests", "test");
is(ws.url, url, "Wrong Websocket.url!"); is(ws.url, url, "Wrong Websocket.url!");

View File

@@ -127,6 +127,29 @@ WebGLContext::WebGLContext()
mFakeVertexAttrib0BufferObjectSize = 0; mFakeVertexAttrib0BufferObjectSize = 0;
mFakeVertexAttrib0BufferObject = 0; mFakeVertexAttrib0BufferObject = 0;
mFakeVertexAttrib0BufferStatus = VertexAttrib0Status::Default; mFakeVertexAttrib0BufferStatus = VertexAttrib0Status::Default;
// these are de default values, see 6.2 State tables in the OpenGL ES 2.0.25 spec
mColorWriteMask[0] = 1;
mColorWriteMask[1] = 1;
mColorWriteMask[2] = 1;
mColorWriteMask[3] = 1;
mDepthWriteMask = 1;
mColorClearValue[0] = 0.f;
mColorClearValue[1] = 0.f;
mColorClearValue[2] = 0.f;
mColorClearValue[3] = 0.f;
mDepthClearValue = 1.f;
mStencilClearValue = 0;
mStencilRefFront = 0;
mStencilRefBack = 0;
mStencilValueMaskFront = 0xffffffff;
mStencilValueMaskBack = 0xffffffff;
mStencilWriteMaskFront = 0xffffffff;
mStencilWriteMaskBack = 0xffffffff;
mScissorTestEnabled = 0;
mDitherEnabled = 1;
mBackbufferClearingStatus = BackbufferClearingStatus::NotClearedSinceLastPresented;
} }
WebGLContext::~WebGLContext() WebGLContext::~WebGLContext()
@@ -312,31 +335,24 @@ WebGLContext::SetContextOptions(nsIPropertyBag *aOptions)
WebGLContextOptions newOpts; WebGLContextOptions newOpts;
// defaults are: yes: depth, alpha, premultipliedAlpha; no: stencil GetBoolFromPropertyBag(aOptions, "stencil", &newOpts.stencil);
if (!GetBoolFromPropertyBag(aOptions, "stencil", &newOpts.stencil)) GetBoolFromPropertyBag(aOptions, "depth", &newOpts.depth);
newOpts.stencil = false; GetBoolFromPropertyBag(aOptions, "alpha", &newOpts.alpha);
GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha);
if (!GetBoolFromPropertyBag(aOptions, "depth", &newOpts.depth)) GetBoolFromPropertyBag(aOptions, "antialias", &newOpts.antialias);
newOpts.depth = true; GetBoolFromPropertyBag(aOptions, "preserveDrawingBuffer", &newOpts.preserveDrawingBuffer);
if (!GetBoolFromPropertyBag(aOptions, "alpha", &newOpts.alpha))
newOpts.alpha = true;
if (!GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha))
newOpts.premultipliedAlpha = true;
GetBoolFromPropertyBag(aOptions, "antialiasHint", &newOpts.antialiasHint);
// enforce that if stencil is specified, we also give back depth // enforce that if stencil is specified, we also give back depth
newOpts.depth |= newOpts.stencil; newOpts.depth |= newOpts.stencil;
#if 0 #if 0
LogMessage("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d\n", LogMessage("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d preserve: %d\n",
newOpts.antialiasHint ? 1 : 0, newOpts.antialias ? 1 : 0,
newOpts.stencil ? 1 : 0, newOpts.stencil ? 1 : 0,
newOpts.depth ? 1 : 0, newOpts.depth ? 1 : 0,
newOpts.alpha ? 1 : 0, newOpts.alpha ? 1 : 0,
newOpts.premultipliedAlpha ? 1 : 0); newOpts.premultipliedAlpha ? 1 : 0,
newOpts.preserveDrawingBuffer ? 1 : 0);
#endif #endif
if (mOptionsFrozen && newOpts != mOptions) { if (mOptionsFrozen && newOpts != mOptions) {
@@ -703,6 +719,8 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
mResetLayer = PR_FALSE; mResetLayer = PR_FALSE;
mBackbufferClearingStatus = BackbufferClearingStatus::NotClearedSinceLastPresented;
return canvasLayer.forget().get(); return canvasLayer.forget().get();
} }
@@ -731,6 +749,9 @@ WebGLContext::GetContextAttributes(jsval *aResult)
NULL, NULL, JSPROP_ENUMERATE) || NULL, NULL, JSPROP_ENUMERATE) ||
!JS_DefineProperty(cx, obj, "premultipliedAlpha", !JS_DefineProperty(cx, obj, "premultipliedAlpha",
mOptions.premultipliedAlpha ? JSVAL_TRUE : JSVAL_FALSE, mOptions.premultipliedAlpha ? JSVAL_TRUE : JSVAL_FALSE,
NULL, NULL, JSPROP_ENUMERATE) ||
!JS_DefineProperty(cx, obj, "preserveDrawingBuffer",
mOptions.preserveDrawingBuffer ? JSVAL_TRUE : JSVAL_FALSE,
NULL, NULL, JSPROP_ENUMERATE)) NULL, NULL, JSPROP_ENUMERATE))
{ {
*aResult = JSVAL_VOID; *aResult = JSVAL_VOID;
@@ -766,6 +787,122 @@ WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval)
{
*retval = nsnull;
// handle simple extensions that don't need custom objects first
WebGLExtensionID ei = WebGLExtensionID_Max;
if (aName.EqualsLiteral("OES_texture_float")) {
MakeContextCurrent();
PRBool avail = gl->IsExtensionSupported(gl->IsGLES2() ? "GL_OES_texture_float" : "GL_ARB_texture_float");
if (avail)
ei = WebGL_OES_texture_float;
}
// create a WebGLExtension object for extensions that don't
// have any additional tokens or methods
if (ei != WebGLExtensionID_Max) {
if (!IsExtensionEnabled(ei)) {
mEnabledExtensions[ei] = new WebGLExtension(this);
}
NS_ADDREF(*retval = mEnabledExtensions[ei]);
}
return NS_OK;
}
void
WebGLContext::ForceClearFramebufferWithDefaultValues(PRUint32 mask, const nsIntRect& viewportRect)
{
MakeContextCurrent();
PRBool initializeColorBuffer = 0 != (mask & LOCAL_GL_COLOR_BUFFER_BIT);
PRBool initializeDepthBuffer = 0 != (mask & LOCAL_GL_DEPTH_BUFFER_BIT);
PRBool initializeStencilBuffer = 0 != (mask & LOCAL_GL_STENCIL_BUFFER_BIT);
// prepare GL state for clearing
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
gl->fDisable(LOCAL_GL_DITHER);
gl->PushViewportRect(viewportRect);
if (initializeColorBuffer) {
gl->fColorMask(1, 1, 1, 1);
gl->fClearColor(0.f, 0.f, 0.f, 0.f);
}
if (initializeDepthBuffer) {
gl->fDepthMask(1);
gl->fClearDepth(1.0f);
}
if (initializeStencilBuffer) {
gl->fStencilMask(0xffffffff);
gl->fClearStencil(0);
}
// do clear
gl->fClear(mask);
// restore GL state after clearing
if (initializeColorBuffer) {
gl->fColorMask(mColorWriteMask[0],
mColorWriteMask[1],
mColorWriteMask[2],
mColorWriteMask[3]);
gl->fClearColor(mColorClearValue[0],
mColorClearValue[1],
mColorClearValue[2],
mColorClearValue[3]);
}
if (initializeDepthBuffer) {
gl->fDepthMask(mDepthWriteMask);
gl->fClearDepth(mDepthClearValue);
}
if (initializeStencilBuffer) {
gl->fStencilMaskSeparate(LOCAL_GL_FRONT, mStencilWriteMaskFront);
gl->fStencilMaskSeparate(LOCAL_GL_BACK, mStencilWriteMaskBack);
gl->fClearStencil(mStencilClearValue);
}
gl->PopViewportRect();
if (mDitherEnabled)
gl->fEnable(LOCAL_GL_DITHER);
else
gl->fDisable(LOCAL_GL_DITHER);
if (mScissorTestEnabled)
gl->fEnable(LOCAL_GL_SCISSOR_TEST);
else
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
}
void
WebGLContext::EnsureBackbufferClearedAsNeeded()
{
if (mOptions.preserveDrawingBuffer)
return;
NS_ABORT_IF_FALSE(!mBoundFramebuffer,
"EnsureBackbufferClearedAsNeeded must not be called when a FBO is bound");
if (mBackbufferClearingStatus != BackbufferClearingStatus::NotClearedSinceLastPresented)
return;
mBackbufferClearingStatus = BackbufferClearingStatus::ClearedToDefaultValues;
ForceClearFramebufferWithDefaultValues(LOCAL_GL_COLOR_BUFFER_BIT |
LOCAL_GL_DEPTH_BUFFER_BIT |
LOCAL_GL_STENCIL_BUFFER_BIT,
nsIntRect(0, 0, mWidth, mHeight));
Invalidate();
}
// //
// XPCOM goop // XPCOM goop
@@ -901,6 +1038,18 @@ NAME_NOT_SUPPORTED(WebGLShader)
NAME_NOT_SUPPORTED(WebGLFramebuffer) NAME_NOT_SUPPORTED(WebGLFramebuffer)
NAME_NOT_SUPPORTED(WebGLRenderbuffer) NAME_NOT_SUPPORTED(WebGLRenderbuffer)
NS_IMPL_ADDREF(WebGLExtension)
NS_IMPL_RELEASE(WebGLExtension)
DOMCI_DATA(WebGLExtension, WebGLExtension)
NS_INTERFACE_MAP_BEGIN(WebGLExtension)
NS_INTERFACE_MAP_ENTRY(WebGLExtension)
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtension)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtension)
NS_INTERFACE_MAP_END
/* [noscript] attribute WebGLint location; */ /* [noscript] attribute WebGLint location; */
NS_IMETHODIMP NS_IMETHODIMP
WebGLUniformLocation::GetLocation(WebGLint *aLocation) WebGLUniformLocation::GetLocation(WebGLint *aLocation)
@@ -969,9 +1118,3 @@ WebGLContext::IsContextLost(WebGLboolean *retval)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
WebGLContext::GetExtension(const nsAString& aName, nsISupports **retval)
{
*retval = nsnull;
return NS_OK;
}

View File

@@ -84,8 +84,13 @@ struct VertexAttrib0Status {
enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray }; enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
}; };
struct BackbufferClearingStatus {
enum { NotClearedSinceLastPresented, ClearedToDefaultValues, HasBeenDrawnTo };
};
struct WebGLTexelFormat { struct WebGLTexelFormat {
enum { Generic, Auto, RGBA8, RGB8, RGBX8, BGRA8, BGR8, BGRX8, RGBA5551, RGBA4444, RGB565, R8, RA8, A8 }; enum { Generic, Auto, RGBA8, RGB8, RGBX8, BGRA8, BGR8, BGRX8, RGBA5551, RGBA4444, RGB565, R8, RA8, A8,
RGBA32F, RGB32F, A32F, R32F, RA32F };
}; };
struct WebGLTexelPremultiplicationOp { struct WebGLTexelPremultiplicationOp {
@@ -284,7 +289,8 @@ struct WebGLContextOptions {
// these are defaults // these are defaults
WebGLContextOptions() WebGLContextOptions()
: alpha(true), depth(true), stencil(false), : alpha(true), depth(true), stencil(false),
premultipliedAlpha(true), antialiasHint(false) premultipliedAlpha(true), antialias(false),
preserveDrawingBuffer(false)
{ } { }
bool operator==(const WebGLContextOptions& other) const { bool operator==(const WebGLContextOptions& other) const {
@@ -293,24 +299,20 @@ struct WebGLContextOptions {
depth == other.depth && depth == other.depth &&
stencil == other.stencil && stencil == other.stencil &&
premultipliedAlpha == other.premultipliedAlpha && premultipliedAlpha == other.premultipliedAlpha &&
antialiasHint == other.antialiasHint; antialias == other.antialias &&
preserveDrawingBuffer == other.preserveDrawingBuffer;
} }
bool operator!=(const WebGLContextOptions& other) const { bool operator!=(const WebGLContextOptions& other) const {
return return !operator==(other);
alpha != other.alpha ||
depth != other.depth ||
stencil != other.stencil ||
premultipliedAlpha != other.premultipliedAlpha ||
antialiasHint != other.antialiasHint;
} }
bool alpha; bool alpha;
bool depth; bool depth;
bool stencil; bool stencil;
bool premultipliedAlpha; bool premultipliedAlpha;
bool antialiasHint; bool antialias;
bool preserveDrawingBuffer;
}; };
class WebGLContext : class WebGLContext :
@@ -377,6 +379,16 @@ public:
// all context resources to be lost. // all context resources to be lost.
PRUint32 Generation() { return mGeneration.value(); } PRUint32 Generation() { return mGeneration.value(); }
// this is similar to GLContext::ClearSafely, but is more comprehensive
// (takes care of scissor, stencil write mask, dithering, viewport...)
// WebGL has more complex needs than GLContext as content controls GL state.
void ForceClearFramebufferWithDefaultValues(PRUint32 mask, const nsIntRect& viewportRect);
// if the preserveDrawingBuffer context option is false, we need to clear the back buffer
// after it's been presented to the compositor. This function does that if needed.
// See section 2.2 in the WebGL spec.
void EnsureBackbufferClearedAsNeeded();
protected: protected:
void SetDontKnowIfNeedFakeBlack() { void SetDontKnowIfNeedFakeBlack() {
mFakeBlackStatus = DontKnowIfNeedFakeBlack; mFakeBlackStatus = DontKnowIfNeedFakeBlack;
@@ -425,6 +437,17 @@ protected:
PRInt32 mGLMaxFragmentUniformVectors; PRInt32 mGLMaxFragmentUniformVectors;
PRInt32 mGLMaxVertexUniformVectors; PRInt32 mGLMaxVertexUniformVectors;
// extensions
enum WebGLExtensionID {
WebGL_OES_texture_float,
WebGLExtensionID_Max
};
nsCOMPtr<nsIWebGLExtension> mEnabledExtensions[WebGLExtensionID_Max];
PRBool IsExtensionEnabled(WebGLExtensionID ext) const {
NS_ABORT_IF_FALSE(ext >= 0 && ext < WebGLExtensionID_Max, "bogus index!");
return mEnabledExtensions[ext] != nsnull;
}
PRBool SafeToCreateCanvas3DContext(nsHTMLCanvasElement *canvasElement); PRBool SafeToCreateCanvas3DContext(nsHTMLCanvasElement *canvasElement);
PRBool InitAndValidateGL(); PRBool InitAndValidateGL();
PRBool ValidateBuffers(PRInt32* maxAllowedCount, const char *info); PRBool ValidateBuffers(PRInt32* maxAllowedCount, const char *info);
@@ -438,10 +461,11 @@ protected:
PRBool ValidateStencilOpEnum(WebGLenum action, const char *info); PRBool ValidateStencilOpEnum(WebGLenum action, const char *info);
PRBool ValidateFaceEnum(WebGLenum face, const char *info); PRBool ValidateFaceEnum(WebGLenum face, const char *info);
PRBool ValidateBufferUsageEnum(WebGLenum target, const char *info); PRBool ValidateBufferUsageEnum(WebGLenum target, const char *info);
PRBool ValidateTexFormatAndType(WebGLenum format, WebGLenum type, PRBool ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
PRUint32 *texelSize, const char *info); PRUint32 *texelSize, const char *info);
PRBool ValidateDrawModeEnum(WebGLenum mode, const char *info); PRBool ValidateDrawModeEnum(WebGLenum mode, const char *info);
PRBool ValidateAttribIndex(WebGLuint index, const char *info); PRBool ValidateAttribIndex(WebGLuint index, const char *info);
PRBool ValidateStencilParamsForDrawCall();
void Invalidate(); void Invalidate();
void DestroyResourcesAndContext(); void DestroyResourcesAndContext();
@@ -453,12 +477,14 @@ protected:
WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero, WebGLint border, WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero, WebGLint border,
WebGLenum format, WebGLenum type, WebGLenum format, WebGLenum type,
void *data, PRUint32 byteLength, void *data, PRUint32 byteLength,
int jsArrayType,
int srcFormat, PRBool srcPremultiplied); int srcFormat, PRBool srcPremultiplied);
nsresult TexSubImage2D_base(WebGLenum target, WebGLint level, nsresult TexSubImage2D_base(WebGLenum target, WebGLint level,
WebGLint xoffset, WebGLint yoffset, WebGLint xoffset, WebGLint yoffset,
WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero, WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
WebGLenum format, WebGLenum type, WebGLenum format, WebGLenum type,
void *pixels, PRUint32 byteLength, void *pixels, PRUint32 byteLength,
int jsArrayType,
int srcFormat, PRBool srcPremultiplied); int srcFormat, PRBool srcPremultiplied);
nsresult ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height, nsresult ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height,
WebGLenum format, WebGLenum type, void *data, PRUint32 byteLength); WebGLenum format, WebGLenum type, void *data, PRUint32 byteLength);
@@ -566,8 +592,18 @@ protected:
GLuint mFakeVertexAttrib0BufferObject; GLuint mFakeVertexAttrib0BufferObject;
int mFakeVertexAttrib0BufferStatus; int mFakeVertexAttrib0BufferStatus;
WebGLint mStencilRef; WebGLint mStencilRefFront, mStencilRefBack;
WebGLuint mStencilValueMask, mStencilWriteMask; WebGLuint mStencilValueMaskFront, mStencilValueMaskBack,
mStencilWriteMaskFront, mStencilWriteMaskBack;
realGLboolean mColorWriteMask[4];
realGLboolean mDepthWriteMask;
realGLboolean mScissorTestEnabled;
realGLboolean mDitherEnabled;
WebGLfloat mColorClearValue[4];
WebGLint mStencilClearValue;
WebGLfloat mDepthClearValue;
int mBackbufferClearingStatus;
public: public:
// console logging helpers // console logging helpers
@@ -878,7 +914,7 @@ protected:
public: public:
ImageInfo& ImageInfoAt(size_t level, size_t face) { ImageInfo& ImageInfoAt(size_t level, size_t face = 0) {
#ifdef DEBUG #ifdef DEBUG
if (face >= mFacesCount) if (face >= mFacesCount)
NS_ERROR("wrong face index, must be 0 for TEXTURE_2D and at most 5 for cube maps"); NS_ERROR("wrong face index, must be 0 for TEXTURE_2D and at most 5 for cube maps");
@@ -917,6 +953,12 @@ protected:
mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount); mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount);
} }
PRBool CheckFloatTextureFilterParams() const {
// Without OES_texture_float_linear, only NEAREST and NEAREST_MIMPAMP_NEAREST are supported
return (mMagFilter == LOCAL_GL_NEAREST) &&
(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
}
PRBool DoesMinFilterRequireMipmap() const { PRBool DoesMinFilterRequireMipmap() const {
return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR); return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR);
} }
@@ -1143,7 +1185,7 @@ public:
("%s is a 2D texture, with a minification filter requiring a mipmap, " ("%s is a 2D texture, with a minification filter requiring a mipmap, "
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black); "and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack; mFakeBlackStatus = DoNeedFakeBlack;
} else if (!ImageInfoAt(0, 0).IsPowerOfTwo()) { } else if (!ImageInfoAt(0).IsPowerOfTwo()) {
mContext->LogMessageIfVerbose mContext->LogMessageIfVerbose
("%s is a 2D texture, with a minification filter requiring a mipmap, " ("%s is a 2D texture, with a minification filter requiring a mipmap, "
"and either its width or height is not a power of two.", msg_rendering_as_black); "and either its width or height is not a power of two.", msg_rendering_as_black);
@@ -1152,12 +1194,12 @@ public:
} }
else // no mipmap required else // no mipmap required
{ {
if (!ImageInfoAt(0, 0).IsPositive()) { if (!ImageInfoAt(0).IsPositive()) {
mContext->LogMessageIfVerbose mContext->LogMessageIfVerbose
("%s is a 2D texture and its width or height is equal to zero.", ("%s is a 2D texture and its width or height is equal to zero.",
msg_rendering_as_black); msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack; mFakeBlackStatus = DoNeedFakeBlack;
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(0, 0).IsPowerOfTwo()) { } else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(0).IsPowerOfTwo()) {
mContext->LogMessageIfVerbose mContext->LogMessageIfVerbose
("%s is a 2D texture, with a minification filter not requiring a mipmap, " ("%s is a 2D texture, with a minification filter not requiring a mipmap, "
"with its width or height not a power of two, and with a wrap mode " "with its width or height not a power of two, and with a wrap mode "
@@ -1766,97 +1808,37 @@ protected:
if (mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) != LOCAL_GL_FRAMEBUFFER_COMPLETE) if (mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) != LOCAL_GL_FRAMEBUFFER_COMPLETE)
return; return;
PRBool initializeColorBuffer = mColorAttachment.HasUninitializedRenderbuffer(); PRUint32 mask = 0;
PRBool initializeDepthBuffer = mDepthAttachment.HasUninitializedRenderbuffer() ||
mDepthStencilAttachment.HasUninitializedRenderbuffer();
PRBool initializeStencilBuffer = mStencilAttachment.HasUninitializedRenderbuffer() ||
mDepthStencilAttachment.HasUninitializedRenderbuffer();
realGLboolean savedColorMask[4] = {0}; if (mColorAttachment.HasUninitializedRenderbuffer())
realGLboolean savedDepthMask = 0; mask |= LOCAL_GL_COLOR_BUFFER_BIT;
GLuint savedStencilMask = 0;
GLfloat savedColorClearValue[4] = {0.f};
GLfloat savedDepthClearValue = 0.f;
GLint savedStencilClearValue = 0;
GLuint clearBits = 0;
realGLboolean wasScissorTestEnabled = mContext->gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST); if (mDepthAttachment.HasUninitializedRenderbuffer() ||
mContext->gl->fDisable(LOCAL_GL_SCISSOR_TEST); mDepthStencilAttachment.HasUninitializedRenderbuffer())
{
realGLboolean wasDitherEnabled = mContext->gl->fIsEnabled(LOCAL_GL_DITHER); mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
mContext->gl->fDisable(LOCAL_GL_DITHER);
mContext->gl->PushViewportRect(nsIntRect(0,0,width(),height()));
if (initializeColorBuffer) {
mContext->gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, savedColorMask);
mContext->gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, savedColorClearValue);
mContext->gl->fColorMask(1, 1, 1, 1);
mContext->gl->fClearColor(0.f, 0.f, 0.f, 0.f);
clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
} }
if (initializeDepthBuffer) { if (mStencilAttachment.HasUninitializedRenderbuffer() ||
mContext->gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &savedDepthMask); mDepthStencilAttachment.HasUninitializedRenderbuffer())
mContext->gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &savedDepthClearValue); {
mContext->gl->fDepthMask(1); mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
mContext->gl->fClearDepth(0.f);
clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
}
if (initializeStencilBuffer) {
mContext->gl->fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&savedStencilMask));
mContext->gl->fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &savedStencilClearValue);
mContext->gl->fStencilMask(0xffffffff);
mContext->gl->fClearStencil(0);
clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
} }
// the one useful line of code // the one useful line of code
mContext->gl->fClear(clearBits); mContext->ForceClearFramebufferWithDefaultValues(mask, nsIntRect(0,0,width(),height()));
if (initializeColorBuffer) { if (mColorAttachment.HasUninitializedRenderbuffer())
mContext->gl->fColorMask(savedColorMask[0],
savedColorMask[1],
savedColorMask[2],
savedColorMask[3]);
mContext->gl->fClearColor(savedColorClearValue[0],
savedColorClearValue[1],
savedColorClearValue[2],
savedColorClearValue[3]);
mColorAttachment.Renderbuffer()->SetInitialized(PR_TRUE); mColorAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
}
if (initializeDepthBuffer) { if (mDepthAttachment.HasUninitializedRenderbuffer())
mContext->gl->fDepthMask(savedDepthMask); mDepthAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
mContext->gl->fClearDepth(savedDepthClearValue);
if (mDepthAttachment.Renderbuffer())
mDepthAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
}
if (initializeStencilBuffer) { if (mStencilAttachment.HasUninitializedRenderbuffer())
mContext->gl->fStencilMask(savedStencilMask); mStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
mContext->gl->fClearStencil(savedStencilClearValue);
if (mStencilAttachment.Renderbuffer())
mStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
}
if (initializeDepthBuffer && initializeStencilBuffer) { if (mDepthStencilAttachment.HasUninitializedRenderbuffer())
if (mDepthStencilAttachment.Renderbuffer()) mDepthStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
mDepthStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
}
mContext->gl->PopViewportRect();
if (wasDitherEnabled)
mContext->gl->fEnable(LOCAL_GL_DITHER);
else
mContext->gl->fDisable(LOCAL_GL_DITHER);
if (wasScissorTestEnabled)
mContext->gl->fEnable(LOCAL_GL_DITHER);
else
mContext->gl->fDisable(LOCAL_GL_SCISSOR_TEST);
} }
WebGLuint mName; WebGLuint mName;
@@ -1939,6 +1921,26 @@ protected:
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLActiveInfo, WEBGLACTIVEINFO_PRIVATE_IID) NS_DEFINE_STATIC_IID_ACCESSOR(WebGLActiveInfo, WEBGLACTIVEINFO_PRIVATE_IID)
#define WEBGLEXTENSION_PRIVATE_IID \
{0x457dd0b2, 0x9f77, 0x4c23, {0x95, 0x70, 0x9d, 0x62, 0x65, 0xc1, 0xa4, 0x81}}
class WebGLExtension :
public nsIWebGLExtension,
public WebGLContextBoundObject,
public WebGLZeroingObject
{
public:
WebGLExtension(WebGLContext *baseContext)
: WebGLContextBoundObject(baseContext)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBGLEXTENSION
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLEXTENSION_PRIVATE_IID)
};
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLExtension, WEBGLACTIVEINFO_PRIVATE_IID)
/** /**
** Template implementations ** Template implementations
**/ **/

View File

@@ -65,6 +65,7 @@
using namespace mozilla; using namespace mozilla;
static PRBool BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize); static PRBool BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize);
static WebGLenum InternalFormatForFormatAndType(WebGLenum format, WebGLenum type, bool isGLES2);
/* Helper macros for when we're just wrapping a gl method, so that /* Helper macros for when we're just wrapping a gl method, so that
* we can avoid having to type this 500 times. Note that these MUST * we can avoid having to type this 500 times. Note that these MUST
@@ -586,27 +587,81 @@ WebGLContext::Clear(PRUint32 mask)
{ {
MakeContextCurrent(); MakeContextCurrent();
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return NS_OK;
PRUint32 m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT); PRUint32 m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
if (mask != m) { if (mask != m)
return ErrorInvalidValue("clear: invalid mask bits"); return ErrorInvalidValue("clear: invalid mask bits");
PRBool needClearCallHere = PR_TRUE;
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return NS_OK;
} else {
// no FBO is bound, so we are clearing the backbuffer here
EnsureBackbufferClearedAsNeeded();
PRBool valuesAreDefault = mColorClearValue[0] == 0.0f &&
mColorClearValue[1] == 0.0f &&
mColorClearValue[2] == 0.0f &&
mColorClearValue[3] == 0.0f &&
mDepthClearValue == 1.0f &&
mStencilClearValue == 0;
if (valuesAreDefault &&
mBackbufferClearingStatus == BackbufferClearingStatus::ClearedToDefaultValues)
{
needClearCallHere = PR_FALSE;
}
} }
gl->fClear(mask); if (needClearCallHere) {
Invalidate(); gl->fClear(mask);
mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
Invalidate();
}
return NS_OK; return NS_OK;
} }
GL_SAME_METHOD_4(ClearColor, ClearColor, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat) NS_IMETHODIMP
WebGLContext::ClearColor(WebGLfloat r, WebGLfloat g, WebGLfloat b, WebGLfloat a)
{
MakeContextCurrent();
mColorClearValue[0] = r;
mColorClearValue[1] = g;
mColorClearValue[2] = b;
mColorClearValue[3] = a;
gl->fClearColor(r, g, b, a);
return NS_OK;
}
GL_SAME_METHOD_1(ClearDepth, ClearDepth, WebGLfloat) NS_IMETHODIMP
WebGLContext::ClearDepth(WebGLfloat v)
{
MakeContextCurrent();
mDepthClearValue = v;
gl->fClearDepth(v);
return NS_OK;
}
GL_SAME_METHOD_1(ClearStencil, ClearStencil, WebGLint) NS_IMETHODIMP
WebGLContext::ClearStencil(WebGLint v)
{
MakeContextCurrent();
mStencilClearValue = v;
gl->fClearStencil(v);
return NS_OK;
}
GL_SAME_METHOD_4(ColorMask, ColorMask, WebGLboolean, WebGLboolean, WebGLboolean, WebGLboolean) NS_IMETHODIMP
WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
{
MakeContextCurrent();
mColorWriteMask[0] = r;
mColorWriteMask[1] = g;
mColorWriteMask[2] = b;
mColorWriteMask[3] = a;
gl->fColorMask(r, g, b, a);
return NS_OK;
}
nsresult nsresult
WebGLContext::CopyTexSubImage2D_base(WebGLenum target, WebGLContext::CopyTexSubImage2D_base(WebGLenum target,
@@ -642,7 +697,7 @@ WebGLContext::CopyTexSubImage2D_base(WebGLenum target,
// first, compute the size of the buffer we should allocate to initialize the texture as black // first, compute the size of the buffer we should allocate to initialize the texture as black
PRUint32 texelSize = 0; PRUint32 texelSize = 0;
if (!ValidateTexFormatAndType(internalformat, LOCAL_GL_UNSIGNED_BYTE, &texelSize, info)) if (!ValidateTexFormatAndType(internalformat, LOCAL_GL_UNSIGNED_BYTE, -1, &texelSize, info))
return NS_OK; return NS_OK;
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize; CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
@@ -1080,7 +1135,14 @@ WebGLContext::DepthFunc(WebGLenum func)
return NS_OK; return NS_OK;
} }
GL_SAME_METHOD_1(DepthMask, DepthMask, WebGLboolean) NS_IMETHODIMP
WebGLContext::DepthMask(WebGLboolean b)
{
MakeContextCurrent();
mDepthWriteMask = b;
gl->fDepthMask(b);
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
WebGLContext::DepthRange(WebGLfloat zNear, WebGLfloat zFar) WebGLContext::DepthRange(WebGLfloat zNear, WebGLfloat zFar)
@@ -1301,6 +1363,9 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
if (first < 0 || count < 0) if (first < 0 || count < 0)
return ErrorInvalidValue("DrawArrays: negative first or count"); return ErrorInvalidValue("DrawArrays: negative first or count");
if (!ValidateStencilParamsForDrawCall())
return NS_OK;
// If count is 0, there's nothing to do. // If count is 0, there's nothing to do.
if (count == 0) if (count == 0)
return NS_OK; return NS_OK;
@@ -1324,8 +1389,12 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
MakeContextCurrent(); MakeContextCurrent();
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers()) if (mBoundFramebuffer) {
return NS_OK; if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return NS_OK;
} else {
EnsureBackbufferClearedAsNeeded();
}
BindFakeBlackTextures(); BindFakeBlackTextures();
DoFakeVertexAttrib0(checked_firstPlusCount.value()); DoFakeVertexAttrib0(checked_firstPlusCount.value());
@@ -1335,6 +1404,7 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
UndoFakeVertexAttrib0(); UndoFakeVertexAttrib0();
UnbindFakeBlackTextures(); UnbindFakeBlackTextures();
mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
Invalidate(); Invalidate();
return NS_OK; return NS_OK;
@@ -1349,6 +1419,9 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
if (count < 0 || byteOffset < 0) if (count < 0 || byteOffset < 0)
return ErrorInvalidValue("DrawElements: negative count or offset"); return ErrorInvalidValue("DrawElements: negative count or offset");
if (!ValidateStencilParamsForDrawCall())
return NS_OK;
// If count is 0, there's nothing to do. // If count is 0, there's nothing to do.
if (count == 0) if (count == 0)
return NS_OK; return NS_OK;
@@ -1422,8 +1495,12 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
MakeContextCurrent(); MakeContextCurrent();
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers()) if (mBoundFramebuffer) {
return NS_OK; if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return NS_OK;
} else {
EnsureBackbufferClearedAsNeeded();
}
BindFakeBlackTextures(); BindFakeBlackTextures();
DoFakeVertexAttrib0(checked_maxIndexPlusOne.value()); DoFakeVertexAttrib0(checked_maxIndexPlusOne.value());
@@ -1433,6 +1510,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
UndoFakeVertexAttrib0(); UndoFakeVertexAttrib0();
UnbindFakeBlackTextures(); UnbindFakeBlackTextures();
mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
Invalidate(); Invalidate();
return NS_OK; return NS_OK;
@@ -1443,6 +1521,15 @@ NS_IMETHODIMP WebGLContext::Enable(WebGLenum cap)
if (!ValidateCapabilityEnum(cap, "enable")) if (!ValidateCapabilityEnum(cap, "enable"))
return NS_OK; return NS_OK;
switch(cap) {
case LOCAL_GL_SCISSOR_TEST:
mScissorTestEnabled = 1;
break;
case LOCAL_GL_DITHER:
mDitherEnabled = 1;
break;
}
MakeContextCurrent(); MakeContextCurrent();
gl->fEnable(cap); gl->fEnable(cap);
return NS_OK; return NS_OK;
@@ -1453,6 +1540,15 @@ NS_IMETHODIMP WebGLContext::Disable(WebGLenum cap)
if (!ValidateCapabilityEnum(cap, "disable")) if (!ValidateCapabilityEnum(cap, "disable"))
return NS_OK; return NS_OK;
switch(cap) {
case LOCAL_GL_SCISSOR_TEST:
mScissorTestEnabled = 0;
break;
case LOCAL_GL_DITHER:
mDitherEnabled = 0;
break;
}
MakeContextCurrent(); MakeContextCurrent();
gl->fDisable(cap); gl->fDisable(cap);
return NS_OK; return NS_OK;
@@ -2857,9 +2953,14 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
MakeContextCurrent(); MakeContextCurrent();
// prevent readback of arbitrary video memory through uninitialized renderbuffers! if (mBoundFramebuffer) {
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers()) // prevent readback of arbitrary video memory through uninitialized renderbuffers!
return NS_OK; if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return NS_OK;
} else {
EnsureBackbufferClearedAsNeeded();
}
if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, boundWidth, boundHeight)) { if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, boundWidth, boundHeight)) {
// the easy case: we're not reading out-of-range pixels // the easy case: we're not reading out-of-range pixels
@@ -3071,8 +3172,10 @@ WebGLContext::StencilFunc(WebGLenum func, WebGLint ref, WebGLuint mask)
if (!ValidateComparisonEnum(func, "stencilFunc: func")) if (!ValidateComparisonEnum(func, "stencilFunc: func"))
return NS_OK; return NS_OK;
mStencilRef = ref; mStencilRefFront = ref;
mStencilValueMask = mask; mStencilRefBack = ref;
mStencilValueMaskFront = mask;
mStencilValueMaskBack = mask;
MakeContextCurrent(); MakeContextCurrent();
gl->fStencilFunc(func, ref, mask); gl->fStencilFunc(func, ref, mask);
@@ -3086,12 +3189,22 @@ WebGLContext::StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref,
!ValidateComparisonEnum(func, "stencilFuncSeparate: func")) !ValidateComparisonEnum(func, "stencilFuncSeparate: func"))
return NS_OK; return NS_OK;
if (face != LOCAL_GL_FRONT_AND_BACK && (ref != mStencilRef || mask != mStencilValueMask)) switch (face) {
return ErrorInvalidOperation("stencilFuncSeparate: WebGL doesn't currently allow specifying " case LOCAL_GL_FRONT_AND_BACK:
"different values for front and back."); mStencilRefFront = ref;
mStencilRefBack = ref;
mStencilRef = ref; mStencilValueMaskFront = mask;
mStencilValueMask = mask; mStencilValueMaskBack = mask;
break;
case LOCAL_GL_FRONT:
mStencilRefFront = ref;
mStencilValueMaskFront = mask;
break;
case LOCAL_GL_BACK:
mStencilRefBack = ref;
mStencilValueMaskBack = mask;
break;
}
MakeContextCurrent(); MakeContextCurrent();
gl->fStencilFuncSeparate(face, func, ref, mask); gl->fStencilFuncSeparate(face, func, ref, mask);
@@ -3101,7 +3214,8 @@ WebGLContext::StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref,
NS_IMETHODIMP NS_IMETHODIMP
WebGLContext::StencilMask(WebGLuint mask) WebGLContext::StencilMask(WebGLuint mask)
{ {
mStencilWriteMask = mask; mStencilWriteMaskFront = mask;
mStencilWriteMaskBack = mask;
MakeContextCurrent(); MakeContextCurrent();
gl->fStencilMask(mask); gl->fStencilMask(mask);
@@ -3114,10 +3228,18 @@ WebGLContext::StencilMaskSeparate(WebGLenum face, WebGLuint mask)
if (!ValidateFaceEnum(face, "stencilMaskSeparate: face")) if (!ValidateFaceEnum(face, "stencilMaskSeparate: face"))
return NS_OK; return NS_OK;
if (face != LOCAL_GL_FRONT_AND_BACK && mask != mStencilWriteMask) switch (face) {
return ErrorInvalidOperation("stencilMaskSeparate: WebGL doesn't currently allow specifying " case LOCAL_GL_FRONT_AND_BACK:
"different values for front and back."); mStencilWriteMaskFront = mask;
mStencilWriteMask = mask; mStencilWriteMaskBack = mask;
break;
case LOCAL_GL_FRONT:
mStencilWriteMaskFront = mask;
break;
case LOCAL_GL_BACK:
mStencilWriteMaskBack = mask;
break;
}
MakeContextCurrent(); MakeContextCurrent();
gl->fStencilMaskSeparate(face, mask); gl->fStencilMaskSeparate(face, mask);
@@ -3163,18 +3285,21 @@ struct WebGLImageConverter
memset(this, 0, sizeof(WebGLImageConverter)); memset(this, 0, sizeof(WebGLImageConverter));
} }
template<typename SrcType, typename DstType, template<typename SrcType, typename DstType, typename UnpackType,
void unpackingFunc(const SrcType*, PRUint8*), void unpackingFunc(const SrcType*, UnpackType*),
void packingFunc(const PRUint8*, DstType*)> void packingFunc(const UnpackType*, DstType*)>
void run() void run()
{ {
// Note -- even though the functions take UnpackType, the
// pointers below are all in terms of PRUint8; otherwise
// pointer math starts getting tricky.
for (size_t src_row = 0; src_row < height; ++src_row) { for (size_t src_row = 0; src_row < height; ++src_row) {
size_t dst_row = flip ? (height - 1 - src_row) : src_row; size_t dst_row = flip ? (height - 1 - src_row) : src_row;
PRUint8 *dst_row_ptr = dst + dst_row * dstStride; PRUint8 *dst_row_ptr = dst + dst_row * dstStride;
const PRUint8 *src_row_ptr = src + src_row * srcStride; const PRUint8 *src_row_ptr = src + src_row * srcStride;
const PRUint8 *src_row_end = src_row_ptr + width * srcTexelSize; // != src_row_ptr + byteStride const PRUint8 *src_row_end = src_row_ptr + width * srcTexelSize; // != src_row_ptr + byteStride
while (src_row_ptr != src_row_end) { while (src_row_ptr != src_row_end) {
PRUint8 tmp[4]; UnpackType tmp[4];
unpackingFunc(reinterpret_cast<const SrcType*>(src_row_ptr), tmp); unpackingFunc(reinterpret_cast<const SrcType*>(src_row_ptr), tmp);
packingFunc(tmp, reinterpret_cast<DstType*>(dst_row_ptr)); packingFunc(tmp, reinterpret_cast<DstType*>(dst_row_ptr));
src_row_ptr += srcTexelSize; src_row_ptr += srcTexelSize;
@@ -3205,6 +3330,8 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
// So the case we're handling here is when even though no format conversion is needed, // So the case we're handling here is when even though no format conversion is needed,
// we still might have to flip vertically and/or to adjust to a different stride. // we still might have to flip vertically and/or to adjust to a different stride.
NS_ASSERTION(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree
const PRUint8* src_row = src; const PRUint8* src_row = src;
const PRUint8* src_end = src + height * srcStride; const PRUint8* src_end = src + height * srcStride;
@@ -3239,17 +3366,17 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
case WebGLTexelFormat::format: \ case WebGLTexelFormat::format: \
switch (premultiplicationOp) { \ switch (premultiplicationOp) { \
case WebGLTexelPremultiplicationOp::Premultiply: \ case WebGLTexelPremultiplicationOp::Premultiply: \
converter.run<SrcType, DstType, \ converter.run<SrcType, DstType, PRUint8, \
WebGLTexelConversions::unpackFunc, \ WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc##Premultiply>(); \ WebGLTexelConversions::packFunc##Premultiply>(); \
break; \ break; \
case WebGLTexelPremultiplicationOp::Unmultiply: \ case WebGLTexelPremultiplicationOp::Unmultiply: \
converter.run<SrcType, DstType, \ converter.run<SrcType, DstType, PRUint8, \
WebGLTexelConversions::unpackFunc, \ WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc##Unmultiply>(); \ WebGLTexelConversions::packFunc##Unmultiply>(); \
break; \ break; \
default: \ default: \
converter.run<SrcType, DstType, \ converter.run<SrcType, DstType, PRUint8, \
WebGLTexelConversions::unpackFunc, \ WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc>(); \ WebGLTexelConversions::packFunc>(); \
break; \ break; \
@@ -3269,7 +3396,7 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
HANDLE_DSTFORMAT(RGB565, SrcType, PRUint16, unpackFunc, packRGBA8ToUnsignedShort565) \ HANDLE_DSTFORMAT(RGB565, SrcType, PRUint16, unpackFunc, packRGBA8ToUnsignedShort565) \
/* A8 needs to be special-cased as it doesn't have color channels to premultiply */ \ /* A8 needs to be special-cased as it doesn't have color channels to premultiply */ \
case WebGLTexelFormat::A8: \ case WebGLTexelFormat::A8: \
converter.run<SrcType, PRUint8, \ converter.run<SrcType, PRUint8, PRUint8, \
WebGLTexelConversions::unpackFunc, \ WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packRGBA8ToA8>(); \ WebGLTexelConversions::packRGBA8ToA8>(); \
break; \ break; \
@@ -3279,6 +3406,39 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
} \ } \
break; break;
#define HANDLE_FLOAT_DSTFORMAT(format, unpackFunc, packFunc) \
case WebGLTexelFormat::format: \
switch (premultiplicationOp) { \
case WebGLTexelPremultiplicationOp::Premultiply: \
converter.run<float, float, float, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc##Premultiply>(); \
break; \
case WebGLTexelPremultiplicationOp::Unmultiply: \
NS_ASSERTION(PR_FALSE, "Floating point can't be un-premultiplied -- we have no premultiplied source data!"); \
break; \
default: \
converter.run<float, float, float, \
WebGLTexelConversions::unpackFunc, \
WebGLTexelConversions::packFunc>(); \
break; \
} \
break;
#define HANDLE_FLOAT_SRCFORMAT(format, size, unpackFunc) \
case WebGLTexelFormat::format: \
converter.srcTexelSize = size; \
switch (dstFormat) { \
HANDLE_FLOAT_DSTFORMAT(RGB32F, unpackFunc, packRGBA32FToRGB32F) \
HANDLE_FLOAT_DSTFORMAT(A32F, unpackFunc, packRGBA32FToA32F) \
HANDLE_FLOAT_DSTFORMAT(R32F, unpackFunc, packRGBA32FToR32F) \
HANDLE_FLOAT_DSTFORMAT(RA32F, unpackFunc, packRGBA32FToRA32F) \
default: \
NS_ASSERTION(PR_FALSE, "Coding error?! Should never reach this point."); \
return; \
} \
break;
switch (srcFormat) { switch (srcFormat) {
HANDLE_SRCFORMAT(RGBA8, 4, PRUint8, unpackRGBA8ToRGBA8) HANDLE_SRCFORMAT(RGBA8, 4, PRUint8, unpackRGBA8ToRGBA8)
HANDLE_SRCFORMAT(RGBX8, 4, PRUint8, unpackRGB8ToRGBA8) HANDLE_SRCFORMAT(RGBX8, 4, PRUint8, unpackRGB8ToRGBA8)
@@ -3292,6 +3452,10 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
HANDLE_SRCFORMAT(RGBA5551, 2, PRUint16, unpackRGBA5551ToRGBA8) HANDLE_SRCFORMAT(RGBA5551, 2, PRUint16, unpackRGBA5551ToRGBA8)
HANDLE_SRCFORMAT(RGBA4444, 2, PRUint16, unpackRGBA4444ToRGBA8) HANDLE_SRCFORMAT(RGBA4444, 2, PRUint16, unpackRGBA4444ToRGBA8)
HANDLE_SRCFORMAT(RGB565, 2, PRUint16, unpackRGB565ToRGBA8) HANDLE_SRCFORMAT(RGB565, 2, PRUint16, unpackRGB565ToRGBA8)
HANDLE_FLOAT_SRCFORMAT(RGB32F, 12, unpackRGB32FToRGBA32F)
HANDLE_FLOAT_SRCFORMAT(RA32F, 8, unpackRA32FToRGBA32F)
HANDLE_FLOAT_SRCFORMAT(R32F, 4, unpackR32FToRGBA32F)
HANDLE_FLOAT_SRCFORMAT(A32F, 4, unpackA32FToRGBA32F)
default: default:
NS_ASSERTION(PR_FALSE, "Coding error?! Should never reach this point."); NS_ASSERTION(PR_FALSE, "Coding error?! Should never reach this point.");
return; return;
@@ -3358,7 +3522,10 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
return NS_OK; \ return NS_OK; \
if (isNull) \ if (isNull) \
return NS_OK; \ return NS_OK; \
if (mCurrentProgram != location_object->Program()) \ /* the need to check specifically for !mCurrentProgram here is explained in bug 657556 */ \
if (!mCurrentProgram) \
return ErrorInvalidOperation("%s: no program is currently bound", info); \
if (mCurrentProgram != location_object->Program()) \
return ErrorInvalidOperation("%s: this uniform location doesn't correspond to the current program", info); \ return ErrorInvalidOperation("%s: this uniform location doesn't correspond to the current program", info); \
if (mCurrentProgram->Generation() != location_object->ProgramGeneration()) \ if (mCurrentProgram->Generation() != location_object->ProgramGeneration()) \
return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \ return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \
@@ -3595,11 +3762,9 @@ WebGLContext::ValidateProgram(nsIWebGLProgram *pobj)
MakeContextCurrent(); MakeContextCurrent();
#ifdef XP_MACOSX #ifdef XP_MACOSX
if (gl->Vendor() == gl::GLContext::VendorNVIDIA) { // see bug 593867 for NVIDIA and bug 657201 for ATI. The latter is confirmed with Mac OS 10.6.7
LogMessageIfVerbose("validateProgram: implemented as a no-operation " LogMessageIfVerbose("validateProgram: implemented as a no-operation on Mac to work around crashes");
"on Mac/NVIDIA to work around a driver crash"); return NS_OK;
return NS_OK;
}
#endif #endif
gl->fValidateProgram(progname); gl->fValidateProgram(progname);
@@ -3940,6 +4105,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
WebGLint border, WebGLint border,
WebGLenum format, WebGLenum type, WebGLenum format, WebGLenum type,
void *data, PRUint32 byteLength, void *data, PRUint32 byteLength,
int jsArrayType, // a TypedArray format enum, or -1 if not relevant
int srcFormat, PRBool srcPremultiplied) int srcFormat, PRBool srcPremultiplied)
{ {
switch (target) { switch (target) {
@@ -3996,7 +4162,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
return ErrorInvalidValue("TexImage2D: border must be 0"); return ErrorInvalidValue("TexImage2D: border must be 0");
PRUint32 texelSize = 0; PRUint32 texelSize = 0;
if (!ValidateTexFormatAndType(format, type, &texelSize, "texImage2D")) if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texImage2D"))
return NS_OK; return NS_OK;
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize; CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
@@ -4028,6 +4194,10 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
MakeContextCurrent(); MakeContextCurrent();
// Handle ES2 and GL differences in floating point internal formats. Note that
// format == internalformat, as checked above and as required by ES.
internalformat = InternalFormatForFormatAndType(format, type, gl->IsGLES2());
if (byteLength) { if (byteLength) {
int dstFormat = GetWebGLTexelFormat(format, type); int dstFormat = GetWebGLTexelFormat(format, type);
int actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat; int actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
@@ -4081,6 +4251,7 @@ WebGLContext::TexImage2D_buf(WebGLenum target, WebGLint level, WebGLenum interna
return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type, return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
pixels ? pixels->data : 0, pixels ? pixels->data : 0,
pixels ? pixels->byteLength : 0, pixels ? pixels->byteLength : 0,
-1,
WebGLTexelFormat::Auto, PR_FALSE); WebGLTexelFormat::Auto, PR_FALSE);
} }
@@ -4093,6 +4264,7 @@ WebGLContext::TexImage2D_array(WebGLenum target, WebGLint level, WebGLenum inter
return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type, return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
pixels ? pixels->data : 0, pixels ? pixels->data : 0,
pixels ? pixels->byteLength : 0, pixels ? pixels->byteLength : 0,
(int) pixels->type,
WebGLTexelFormat::Auto, PR_FALSE); WebGLTexelFormat::Auto, PR_FALSE);
} }
@@ -4105,6 +4277,7 @@ WebGLContext::TexImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum i
return TexImage2D_base(target, level, internalformat, width, height, 4*width, border, format, type, return TexImage2D_base(target, level, internalformat, width, height, 4*width, border, format, type,
pixels ? pixels->data : 0, pixels ? pixels->data : 0,
pixels ? pixels->byteLength : 0, pixels ? pixels->byteLength : 0,
-1,
WebGLTexelFormat::RGBA8, PR_FALSE); WebGLTexelFormat::RGBA8, PR_FALSE);
} }
@@ -4125,6 +4298,7 @@ WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum interna
isurf->Width(), isurf->Height(), isurf->Stride(), 0, isurf->Width(), isurf->Height(), isurf->Stride(), 0,
format, type, format, type,
isurf->Data(), byteLength, isurf->Data(), byteLength,
-1,
srcFormat, mPixelStorePremultiplyAlpha); srcFormat, mPixelStorePremultiplyAlpha);
} }
@@ -4140,6 +4314,7 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero, WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
WebGLenum format, WebGLenum type, WebGLenum format, WebGLenum type,
void *pixels, PRUint32 byteLength, void *pixels, PRUint32 byteLength,
int jsArrayType,
int srcFormat, PRBool srcPremultiplied) int srcFormat, PRBool srcPremultiplied)
{ {
switch (target) { switch (target) {
@@ -4176,7 +4351,7 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
} }
PRUint32 texelSize = 0; PRUint32 texelSize = 0;
if (!ValidateTexFormatAndType(format, type, &texelSize, "texSubImage2D")) if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texSubImage2D"))
return NS_OK; return NS_OK;
if (width == 0 || height == 0) if (width == 0 || height == 0)
@@ -4254,6 +4429,7 @@ WebGLContext::TexSubImage2D_buf(WebGLenum target, WebGLint level,
return TexSubImage2D_base(target, level, xoffset, yoffset, return TexSubImage2D_base(target, level, xoffset, yoffset,
width, height, 0, format, type, width, height, 0, format, type,
pixels->data, pixels->byteLength, pixels->data, pixels->byteLength,
-1,
WebGLTexelFormat::Auto, PR_FALSE); WebGLTexelFormat::Auto, PR_FALSE);
} }
@@ -4270,6 +4446,7 @@ WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level,
return TexSubImage2D_base(target, level, xoffset, yoffset, return TexSubImage2D_base(target, level, xoffset, yoffset,
width, height, 0, format, type, width, height, 0, format, type,
pixels->data, pixels->byteLength, pixels->data, pixels->byteLength,
pixels->type,
WebGLTexelFormat::Auto, PR_FALSE); WebGLTexelFormat::Auto, PR_FALSE);
} }
@@ -4286,6 +4463,7 @@ WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level,
return TexSubImage2D_base(target, level, xoffset, yoffset, return TexSubImage2D_base(target, level, xoffset, yoffset,
width, height, 4*width, format, type, width, height, 4*width, format, type,
pixels->data, pixels->byteLength, pixels->data, pixels->byteLength,
-1,
WebGLTexelFormat::RGBA8, PR_FALSE); WebGLTexelFormat::RGBA8, PR_FALSE);
} }
@@ -4309,6 +4487,7 @@ WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level,
isurf->Width(), isurf->Height(), isurf->Stride(), isurf->Width(), isurf->Height(), isurf->Stride(),
format, type, format, type,
isurf->Data(), byteLength, isurf->Data(), byteLength,
-1,
srcFormat, PR_TRUE); srcFormat, PR_TRUE);
} }
@@ -4385,8 +4564,7 @@ BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *u
int mozilla::GetWebGLTexelFormat(GLenum format, GLenum type) int mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
{ {
if (type == LOCAL_GL_UNSIGNED_BYTE) if (type == LOCAL_GL_UNSIGNED_BYTE) {
{
switch (format) { switch (format) {
case LOCAL_GL_RGBA: case LOCAL_GL_RGBA:
return WebGLTexelFormat::RGBA8; return WebGLTexelFormat::RGBA8;
@@ -4402,6 +4580,23 @@ int mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
NS_ASSERTION(PR_FALSE, "Coding mistake?! Should never reach this point."); NS_ASSERTION(PR_FALSE, "Coding mistake?! Should never reach this point.");
return WebGLTexelFormat::Generic; return WebGLTexelFormat::Generic;
} }
} else if (type == LOCAL_GL_FLOAT) {
// OES_texture_float
switch (format) {
case LOCAL_GL_RGBA:
return WebGLTexelFormat::RGBA32F;
case LOCAL_GL_RGB:
return WebGLTexelFormat::RGB32F;
case LOCAL_GL_ALPHA:
return WebGLTexelFormat::A32F;
case LOCAL_GL_LUMINANCE:
return WebGLTexelFormat::R32F;
case LOCAL_GL_LUMINANCE_ALPHA:
return WebGLTexelFormat::RA32F;
default:
NS_ASSERTION(PR_FALSE, "Coding mistake?! Should never reach this point.");
return WebGLTexelFormat::Generic;
}
} else { } else {
switch (type) { switch (type) {
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4: case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
@@ -4416,3 +4611,43 @@ int mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
} }
} }
} }
WebGLenum
InternalFormatForFormatAndType(WebGLenum format, WebGLenum type, bool isGLES2)
{
// ES2 requires that format == internalformat; floating-point is
// indicated purely by the type that's loaded. For desktop GL, we
// have to specify a floating point internal format.
if (isGLES2)
return format;
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
return format;
case LOCAL_GL_FLOAT:
switch (format) {
case LOCAL_GL_RGBA:
return LOCAL_GL_RGBA32F_ARB;
case LOCAL_GL_RGB:
return LOCAL_GL_RGB32F_ARB;
case LOCAL_GL_ALPHA:
return LOCAL_GL_ALPHA32F_ARB;
case LOCAL_GL_LUMINANCE:
return LOCAL_GL_LUMINANCE32F_ARB;
case LOCAL_GL_LUMINANCE_ALPHA:
return LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
}
break;
default:
break;
}
NS_ASSERTION(PR_FALSE, "Coding mistake -- bad format/type passed?");
return 0;
}

View File

@@ -44,6 +44,8 @@
#include "CheckedInt.h" #include "CheckedInt.h"
#include "jstypedarray.h"
#if defined(USE_ANGLE) #if defined(USE_ANGLE)
#include "angle/ShaderLang.h" #include "angle/ShaderLang.h"
#endif #endif
@@ -327,53 +329,78 @@ PRBool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
} }
} }
PRBool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, PRBool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
PRUint32 *texelSize, const char *info) PRUint32 *texelSize, const char *info)
{ {
if (type == LOCAL_GL_UNSIGNED_BYTE) if (type == LOCAL_GL_UNSIGNED_BYTE ||
(IsExtensionEnabled(WebGL_OES_texture_float) && type == LOCAL_GL_FLOAT))
{ {
if (jsArrayType != -1) {
if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::TypedArray::TYPE_UINT8) ||
(type == LOCAL_GL_FLOAT && jsArrayType != js::TypedArray::TYPE_FLOAT32))
{
ErrorInvalidOperation("%s: invalid typed array type for given format", info);
return PR_FALSE;
}
}
int texMultiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
switch (format) { switch (format) {
case LOCAL_GL_ALPHA: case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE: case LOCAL_GL_LUMINANCE:
*texelSize = 1; *texelSize = 1 * texMultiplier;
return PR_TRUE; return PR_TRUE;
case LOCAL_GL_LUMINANCE_ALPHA: case LOCAL_GL_LUMINANCE_ALPHA:
*texelSize = 2; *texelSize = 2 * texMultiplier;
return PR_TRUE; return PR_TRUE;
case LOCAL_GL_RGB: case LOCAL_GL_RGB:
*texelSize = 3; *texelSize = 3 * texMultiplier;
return PR_TRUE; return PR_TRUE;
case LOCAL_GL_RGBA: case LOCAL_GL_RGBA:
*texelSize = 4; *texelSize = 4 * texMultiplier;
return PR_TRUE; return PR_TRUE;
default: default:
ErrorInvalidEnum("%s: invalid format 0x%x", info, format); break;
return PR_FALSE;
}
} else {
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
if (format == LOCAL_GL_RGBA) {
*texelSize = 2;
return PR_TRUE;
} else {
ErrorInvalidOperation("%s: mutually incompatible format and type", info);
return PR_FALSE;
}
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
if (format == LOCAL_GL_RGB) {
*texelSize = 2;
return PR_TRUE;
} else {
ErrorInvalidOperation("%s: mutually incompatible format and type", info);
return PR_FALSE;
}
default:
ErrorInvalidEnum("%s: invalid type 0x%x", info, type);
return PR_FALSE;
} }
ErrorInvalidEnum("%s: invalid format 0x%x", info, format);
return PR_FALSE;
} }
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
ErrorInvalidOperation("%s: invalid typed array type for given format", info);
return PR_FALSE;
}
if (format == LOCAL_GL_RGBA) {
*texelSize = 2;
return PR_TRUE;
}
ErrorInvalidOperation("%s: mutually incompatible format and type", info);
return PR_FALSE;
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
ErrorInvalidOperation("%s: invalid typed array type for given format", info);
return PR_FALSE;
}
if (format == LOCAL_GL_RGB) {
*texelSize = 2;
return PR_TRUE;
}
ErrorInvalidOperation("%s: mutually incompatible format and type", info);
return PR_FALSE;
default:
break;
}
ErrorInvalidEnum("%s: invalid type 0x%x", info, type);
return PR_FALSE;
} }
PRBool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info) PRBool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
@@ -392,6 +419,24 @@ PRBool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
} }
} }
PRBool WebGLContext::ValidateStencilParamsForDrawCall()
{
const char *msg = "%s set different front and back stencil %s. Drawing in this configuration is not allowed.";
if (mStencilRefFront != mStencilRefBack) {
ErrorInvalidOperation(msg, "stencilFuncSeparate", "reference values");
return PR_FALSE;
}
if (mStencilValueMaskFront != mStencilValueMaskBack) {
ErrorInvalidOperation(msg, "stencilFuncSeparate", "value masks");
return PR_FALSE;
}
if (mStencilWriteMaskFront != mStencilWriteMaskBack) {
ErrorInvalidOperation(msg, "stencilMaskSeparate", "write masks");
return PR_FALSE;
}
return PR_TRUE;
}
PRBool PRBool
WebGLContext::InitAndValidateGL() WebGLContext::InitAndValidateGL()
{ {
@@ -547,10 +592,6 @@ WebGLContext::InitAndValidateGL()
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*) &mPixelStorePackAlignment); gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*) &mPixelStorePackAlignment);
gl->fGetIntegerv(LOCAL_GL_UNPACK_ALIGNMENT, (GLint*) &mPixelStoreUnpackAlignment); gl->fGetIntegerv(LOCAL_GL_UNPACK_ALIGNMENT, (GLint*) &mPixelStoreUnpackAlignment);
gl->fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, (GLint*) &mStencilWriteMask);
gl->fGetIntegerv(LOCAL_GL_STENCIL_VALUE_MASK, (GLint*) &mStencilValueMask);
gl->fGetIntegerv(LOCAL_GL_STENCIL_REF, (GLint*) &mStencilRef);
// Check the shader validator pref // Check the shader validator pref
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID); nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE); NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);

View File

@@ -148,6 +148,38 @@ void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict desti
destination[3] = source[0]; destination[3] = source[0];
} }
void unpackRGB32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
destination[3] = 1;
}
void unpackR32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
destination[3] = 1;
}
void unpackRA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[0];
destination[2] = source[0];
destination[3] = source[1];
}
void unpackA32FToRGBA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = 0;
destination[1] = 0;
destination[2] = 0;
destination[3] = source[0];
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Pixel packing routines. // Pixel packing routines.
// //
@@ -360,6 +392,66 @@ void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uin
| ((sourceB & 0xF8) >> 3)); | ((sourceB & 0xF8) >> 3));
} }
void packRGBA32FToRGB32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
}
void packRGBA32FToRGB32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
destination[2] = source[2] * scaleFactor;
}
void packRGBA32FToRGBA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = source[1] * scaleFactor;
destination[2] = source[2] * scaleFactor;
destination[3] = source[3];
}
void packRGBA32FToA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[3];
}
// identical to above, to avoid special-casing
void packRGBA32FToA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[3];
}
void packRGBA32FToR32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
}
void packRGBA32FToR32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
}
void packRGBA32FToRA32F(const float* __restrict source, float* __restrict destination)
{
destination[0] = source[0];
destination[1] = source[3];
}
void packRGBA32FToRA32FPremultiply(const float* __restrict source, float* __restrict destination)
{
float scaleFactor = source[3];
destination[0] = source[0] * scaleFactor;
destination[1] = scaleFactor;
}
/****** END CODE TAKEN FROM WEBKIT ******/ /****** END CODE TAKEN FROM WEBKIT ******/
} // end namespace WebGLTexelConversions } // end namespace WebGLTexelConversions

View File

@@ -172,15 +172,16 @@ static PRInt64 GetCanvasMemoryUsed(void *) {
return gCanvasMemoryUsed; return gCanvasMemoryUsed;
} }
// This isn't "heap-used/content/canvas/2d-pixel-bytes" because the pixels of a // This is MR_OTHER because it's not always clear where in memory the pixels of
// canvas may not be stored on the heap. And if they are, they will be tracked // a canvas are stored. Furthermore, this memory will be tracked by the
// by the underlying surface implementations. See bug 655638 for details. // underlying surface implementations. See bug 655638 for details.
NS_MEMORY_REPORTER_IMPLEMENT(CanvasMemory, NS_MEMORY_REPORTER_IMPLEMENT(CanvasMemory,
"canvas-2d-pixel-bytes", "canvas-2d-pixel-bytes",
"Memory used by 2D canvases. Each canvas " MR_OTHER,
"requires (width * height * 4) bytes.", "Memory used by 2D canvases. Each canvas requires (width * height * 4) "
GetCanvasMemoryUsed, "bytes.",
NULL) GetCanvasMemoryUsed,
NULL)
static void static void
CopyContext(gfxContext* dest, gfxContext* src) CopyContext(gfxContext* dest, gfxContext* src)

View File

@@ -78,8 +78,10 @@ successfullyParsed = true;
</script> </script>
</head> </head>
<body> <body>
<div id="description"></div> <!-- Important to put the canvas at the top so that it's always visible even in the test suite runner.
Otherwise it just doesn't get composited in Firefox. -->
<canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas> <canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas>
<div id="description"></div>
<div id="console"></div> <div id="console"></div>
</body> </body>
</html> </html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -84,9 +84,11 @@ if (!gl) {
testPassed("No OES_texture_float support -- this is legal"); testPassed("No OES_texture_float support -- this is legal");
} else { } else {
testPassed("Successfully enabled OES_texture_float extension"); testPassed("Successfully enabled OES_texture_float extension");
dump('XXXXXX ' + gl.getExtension("OES_texture_float") + '\n');
runTextureCreationTest(testProgram, true); runTextureCreationTest(testProgram, true);
runRenderTargetTest(testProgram); runRenderTargetTest(testProgram);
runUniqueObjectTest(); // this sub-test is currently failing, see discussion in bug 630672
// runUniqueObjectTest();
} }
} }

View File

@@ -1,5 +1,3 @@
conformance/buffer-preserve-test.html
conformance/context-attributes.html
conformance/gl-getshadersource.html conformance/gl-getshadersource.html
conformance/gl-get-active-attribute.html conformance/gl-get-active-attribute.html
conformance/gl-uniform-bool.html conformance/gl-uniform-bool.html
@@ -19,4 +17,3 @@ conformance/object-deletion-behaviour.html
conformance/read-pixels-test.html conformance/read-pixels-test.html
conformance/tex-sub-image-2d-bad-args.html conformance/tex-sub-image-2d-bad-args.html
conformance/uninitialized-test.html conformance/uninitialized-test.html
conformance/webgl-specific.html

View File

@@ -1,7 +1,4 @@
conformance/buffer-preserve-test.html
conformance/canvas-test.html conformance/canvas-test.html
conformance/canvas-test.html
conformance/context-attributes.html
conformance/gl-getshadersource.html conformance/gl-getshadersource.html
conformance/gl-object-get-calls.html conformance/gl-object-get-calls.html
conformance/texture-npot.html conformance/texture-npot.html
@@ -12,7 +9,6 @@ conformance/read-pixels-test.html
conformance/tex-input-validation.html conformance/tex-input-validation.html
conformance/tex-sub-image-2d-bad-args.html conformance/tex-sub-image-2d-bad-args.html
conformance/uninitialized-test.html conformance/uninitialized-test.html
conformance/webgl-specific.html
conformance/more/functions/copyTexImage2D.html conformance/more/functions/copyTexImage2D.html
conformance/more/functions/copyTexSubImage2D.html conformance/more/functions/copyTexSubImage2D.html
conformance/more/functions/copyTexSubImage2DBadArgs.html conformance/more/functions/copyTexSubImage2DBadArgs.html

View File

@@ -1,5 +1,3 @@
conformance/buffer-preserve-test.html
conformance/context-attributes.html
conformance/gl-getshadersource.html conformance/gl-getshadersource.html
conformance/glsl-conformance.html conformance/glsl-conformance.html
conformance/invalid-passed-params.html conformance/invalid-passed-params.html
@@ -7,7 +5,6 @@ conformance/object-deletion-behaviour.html
conformance/read-pixels-test.html conformance/read-pixels-test.html
conformance/tex-sub-image-2d-bad-args.html conformance/tex-sub-image-2d-bad-args.html
conformance/uninitialized-test.html conformance/uninitialized-test.html
conformance/webgl-specific.html
conformance/more/conformance/quickCheckAPI.html conformance/more/conformance/quickCheckAPI.html
conformance/more/functions/copyTexImage2D.html conformance/more/functions/copyTexImage2D.html
conformance/more/functions/copyTexSubImage2D.html conformance/more/functions/copyTexSubImage2D.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -1225,20 +1225,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent); nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
NS_NAMED_LITERAL_CSTRING(actionslot, ".action"); PRBool useSysNumLines = UseSystemScrollSettingFor(msEvent);
NS_NAMED_LITERAL_CSTRING(numlinesslot, ".numlines"); PRInt32 action = GetWheelActionFor(msEvent);
NS_NAMED_LITERAL_CSTRING(sysnumlinesslot, ".sysnumlines");
nsCAutoString baseKey;
GetBasePrefKeyForMouseWheel(msEvent, baseKey);
nsCAutoString sysNumLinesKey(baseKey);
sysNumLinesKey.Append(sysnumlinesslot);
PRBool useSysNumLines = nsContentUtils::GetBoolPref(sysNumLinesKey.get());
nsCAutoString actionKey(baseKey);
actionKey.Append(actionslot);
PRInt32 action = nsContentUtils::GetIntPref(actionKey.get());
if (!useSysNumLines) { if (!useSysNumLines) {
// If the scroll event's delta isn't to our liking, we can // If the scroll event's delta isn't to our liking, we can
@@ -1254,9 +1242,7 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
// second item, if the parameter is negative we swap // second item, if the parameter is negative we swap
// directions. // directions.
nsCAutoString numLinesKey(baseKey); PRInt32 numLines = GetScrollLinesFor(msEvent);
numLinesKey.Append(numlinesslot);
PRInt32 numLines = nsContentUtils::GetIntPref(numLinesKey.get());
PRBool swapDirs = (numLines < 0); PRBool swapDirs = (numLines < 0);
PRInt32 userSize = swapDirs ? -numLines : numLines; PRInt32 userSize = swapDirs ? -numLines : numLines;
@@ -2573,6 +2559,66 @@ nsEventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, aStatus); nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, aStatus);
} }
PRInt32
nsEventStateManager::ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent,
PRBool aUseSystemSettings)
{
PRInt32 action = GetWheelActionFor(aMouseEvent);
if (aUseSystemSettings &&
(aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage)) {
action = MOUSE_SCROLL_PAGE;
}
if (aMouseEvent->message == NS_MOUSE_PIXEL_SCROLL) {
if (action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE ||
(aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
action = MOUSE_SCROLL_PIXELS;
} else {
// Do not scroll pixels when zooming
action = -1;
}
} else if (aMouseEvent->scrollFlags & nsMouseScrollEvent::kHasPixels) {
if (aUseSystemSettings ||
action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE ||
(aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
// Don't scroll lines when a pixel scroll event will follow.
// Also, don't do history scrolling or zooming for momentum scrolls.
action = -1;
}
}
return action;
}
PRInt32
nsEventStateManager::GetWheelActionFor(nsMouseScrollEvent* aMouseEvent)
{
nsCAutoString prefName;
GetBasePrefKeyForMouseWheel(aMouseEvent, prefName);
prefName.Append(".action");
return nsContentUtils::GetIntPref(prefName.get());
}
PRInt32
nsEventStateManager::GetScrollLinesFor(nsMouseScrollEvent* aMouseEvent)
{
NS_ASSERTION(!UseSystemScrollSettingFor(aMouseEvent),
"GetScrollLinesFor() called when should use system settings");
nsCAutoString prefName;
GetBasePrefKeyForMouseWheel(aMouseEvent, prefName);
prefName.Append(".numlines");
return nsContentUtils::GetIntPref(prefName.get());
}
PRBool
nsEventStateManager::UseSystemScrollSettingFor(nsMouseScrollEvent* aMouseEvent)
{
nsCAutoString prefName;
GetBasePrefKeyForMouseWheel(aMouseEvent, prefName);
prefName.Append(".sysnumlines");
return nsContentUtils::GetBoolPref(prefName.get());
}
nsresult nsresult
nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame, nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
nsMouseScrollEvent* aMouseEvent, nsMouseScrollEvent* aMouseEvent,
@@ -3062,45 +3108,8 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
} }
if (*aStatus != nsEventStatus_eConsumeNoDefault) { if (*aStatus != nsEventStatus_eConsumeNoDefault) {
// Build the preference keys, based on the event properties. PRBool useSysNumLines = UseSystemScrollSettingFor(msEvent);
NS_NAMED_LITERAL_CSTRING(actionslot, ".action"); PRInt32 action = ComputeWheelActionFor(msEvent, useSysNumLines);
NS_NAMED_LITERAL_CSTRING(sysnumlinesslot, ".sysnumlines");
nsCAutoString baseKey;
GetBasePrefKeyForMouseWheel(msEvent, baseKey);
// Extract the preferences
nsCAutoString actionKey(baseKey);
actionKey.Append(actionslot);
nsCAutoString sysNumLinesKey(baseKey);
sysNumLinesKey.Append(sysnumlinesslot);
PRInt32 action = nsContentUtils::GetIntPref(actionKey.get());
PRBool useSysNumLines =
nsContentUtils::GetBoolPref(sysNumLinesKey.get());
if (useSysNumLines) {
if (msEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage)
action = MOUSE_SCROLL_PAGE;
}
if (aEvent->message == NS_MOUSE_PIXEL_SCROLL) {
if (action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE ||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
action = MOUSE_SCROLL_PIXELS;
} else {
// Do not scroll pixels when zooming
action = -1;
}
} else if (msEvent->scrollFlags & nsMouseScrollEvent::kHasPixels) {
if (useSysNumLines || action == MOUSE_SCROLL_N_LINES ||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
// Don't scroll lines when a pixel scroll event will follow.
// Also, don't do history scrolling or zooming for momentum scrolls.
action = -1;
}
}
switch (action) { switch (action) {
case MOUSE_SCROLL_N_LINES: case MOUSE_SCROLL_N_LINES:
@@ -4686,13 +4695,35 @@ nsEventStateManager::DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
nsIFrame* aTargetFrame) nsIFrame* aTargetFrame)
{ {
nsMouseScrollEvent* msEvent = aEvent->mInput.mMouseScrollEvent; nsMouseScrollEvent* msEvent = aEvent->mInput.mMouseScrollEvent;
nsIScrollableFrame::ScrollUnit unit;
if (msEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage) { // Don't use high resolution scrolling when user customize the scrolling
unit = nsIScrollableFrame::PAGES; // speed.
} else { if (!UseSystemScrollSettingFor(msEvent)) {
unit = nsIScrollableFrame::LINES; return;
} }
DoScrollText(aTargetFrame, msEvent, unit, PR_FALSE, aEvent);
nsIScrollableFrame::ScrollUnit unit;
PRBool allowOverrideSystemSettings;
switch (ComputeWheelActionFor(msEvent, PR_TRUE)) {
case MOUSE_SCROLL_N_LINES:
unit = nsIScrollableFrame::LINES;
allowOverrideSystemSettings = PR_TRUE;
break;
case MOUSE_SCROLL_PAGE:
unit = nsIScrollableFrame::PAGES;
allowOverrideSystemSettings = PR_FALSE;
break;
case MOUSE_SCROLL_PIXELS:
unit = nsIScrollableFrame::DEVICE_PIXELS;
allowOverrideSystemSettings = PR_FALSE;
default:
// Don't use high resolution scrolling when the action doesn't scroll
// contents.
return;
}
DoScrollText(aTargetFrame, msEvent, unit,
allowOverrideSystemSettings, aEvent);
} }
void void

View File

@@ -342,6 +342,33 @@ protected:
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv); nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
nsresult ChangeTextSize(PRInt32 change); nsresult ChangeTextSize(PRInt32 change);
nsresult ChangeFullZoom(PRInt32 change); nsresult ChangeFullZoom(PRInt32 change);
/**
* Computes the action for the aMouseEvent with prefs. The result is
* MOUSE_SCROLL_N_LINES, MOUSE_SCROLL_PAGE, MOUSE_SCROLL_HISTORY,
* MOUSE_SCROLL_ZOOM, MOUSE_SCROLL_PIXELS or -1.
* When the result is -1, nothing happens for the event.
*
* @param aUseSystemSettings Set the result of UseSystemScrollSettingFor().
*/
PRInt32 ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent,
PRBool aUseSystemSettings);
/**
* Gets the wheel action for the aMouseEvent ONLY with the pref.
* When you actually do something for the event, probably you should use
* ComputeWheelActionFor().
*/
PRInt32 GetWheelActionFor(nsMouseScrollEvent* aMouseEvent);
/**
* Gets the pref value for line scroll amount for the aMouseEvent.
* Note that this method doesn't check whether the aMouseEvent is line scroll
* event and doesn't use system settings.
*/
PRInt32 GetScrollLinesFor(nsMouseScrollEvent* aMouseEvent);
/**
* Whether use system scroll settings or settings in our prefs for the event.
* TRUE, if use system scroll settings. Otherwise, FALSE.
*/
PRBool UseSystemScrollSettingFor(nsMouseScrollEvent* aMouseEvent);
// end mousewheel functions // end mousewheel functions
/* /*

View File

@@ -83,16 +83,11 @@ PRBool nsXMLEventsListener::InitXMLEventsListener(nsIDocument * aDocument,
nsIURI *baseURI = aDocument->GetDocBaseURI(); nsIURI *baseURI = aDocument->GetDocBaseURI();
rv = NS_NewURI( getter_AddRefs(handlerURI), handlerURIStr, nsnull, baseURI); rv = NS_NewURI( getter_AddRefs(handlerURI), handlerURIStr, nsnull, baseURI);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIURL> handlerURL(do_QueryInterface(handlerURI)); handlerURI->GetRef(handlerRef);
if (handlerURL) { // We support only XML Events Basic.
handlerURL->GetRef(handlerRef); rv = docURI->EqualsExceptRef(handlerURI, &equals);
handlerURL->SetRef(EmptyCString()); if (NS_SUCCEEDED(rv) && equals) {
//We support only XML Events Basic. handler = aDocument->GetElementById(NS_ConvertUTF8toUTF16(handlerRef));
docURI->Equals(handlerURL, &equals);
if (equals) {
handler =
aDocument->GetElementById(NS_ConvertUTF8toUTF16(handlerRef));
}
} }
} }
} }

View File

@@ -112,6 +112,7 @@ CPPSRCS = \
nsDOMValidityState.cpp \ nsDOMValidityState.cpp \
nsIConstraintValidation.cpp \ nsIConstraintValidation.cpp \
nsRadioVisitor.cpp \ nsRadioVisitor.cpp \
nsDOMStringMap.cpp \
$(NULL) $(NULL)
ifdef MOZ_MEDIA ifdef MOZ_MEDIA

View File

@@ -0,0 +1,334 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* William Chen <wchen@mozilla.com> (Original Author)
*
* 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 "nsDOMStringMap.h"
#include "nsDOMClassInfo.h"
#include "nsGenericHTMLElement.h"
#include "nsContentUtils.h"
DOMCI_DATA(DOMStringMap, nsDOMStringMap)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStringMap)
// Call back to element to null out weak reference to this object.
tmp->mElement->ClearDataset();
tmp->mElement = nsnull;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStringMap)
NS_INTERFACE_MAP_ENTRY(nsIDOMDOMStringMap)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMStringMap)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMStringMap)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMStringMap)
nsDOMStringMap::nsDOMStringMap(nsGenericHTMLElement* aElement)
: mElement(aElement),
mRemovingProp(PR_FALSE)
{
}
nsDOMStringMap::~nsDOMStringMap()
{
// Check if element still exists, may have been unlinked by cycle collector.
if (mElement) {
// Call back to element to null out weak reference to this object.
mElement->ClearDataset();
}
}
class nsDOMStringMapRemoveProp : public nsRunnable {
public:
nsDOMStringMapRemoveProp(nsDOMStringMap* aDataset, nsIAtom* aProperty)
: mDataset(aDataset),
mProperty(aProperty)
{
}
NS_IMETHOD Run()
{
return mDataset->RemovePropInternal(mProperty);
}
virtual ~nsDOMStringMapRemoveProp()
{
}
protected:
nsRefPtr<nsDOMStringMap> mDataset;
nsCOMPtr<nsIAtom> mProperty;
};
/* [notxpcom] boolean hasDataAttr (in DOMString prop); */
NS_IMETHODIMP_(PRBool) nsDOMStringMap::HasDataAttr(const nsAString& aProp)
{
nsAutoString attr;
if (!DataPropToAttr(aProp, attr)) {
return PR_FALSE;
}
nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
if (!attrAtom) {
return PR_FALSE;
}
return mElement->HasAttr(kNameSpaceID_None, attrAtom);
}
/* [noscript] DOMString getDataAttr (in DOMString prop); */
NS_IMETHODIMP nsDOMStringMap::GetDataAttr(const nsAString& aProp,
nsAString& aResult NS_OUTPARAM)
{
nsAutoString attr;
if (!DataPropToAttr(aProp, attr)) {
aResult.SetIsVoid(PR_TRUE);
return NS_OK;
}
nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
if (!mElement->GetAttr(kNameSpaceID_None, attrAtom, aResult)) {
aResult.SetIsVoid(PR_TRUE);
return NS_OK;
}
return NS_OK;
}
/* [noscript] void setDataAttr (in DOMString prop, in DOMString value); */
NS_IMETHODIMP nsDOMStringMap::SetDataAttr(const nsAString& aProp,
const nsAString& aValue)
{
nsAutoString attr;
NS_ENSURE_TRUE(DataPropToAttr(aProp, attr), NS_ERROR_DOM_SYNTAX_ERR);
nsresult rv = nsContentUtils::CheckQName(attr, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
return mElement->SetAttr(kNameSpaceID_None, attrAtom, aValue, PR_TRUE);
}
/* [notxpcom] void removeDataAttr (in DOMString prop); */
NS_IMETHODIMP_(void) nsDOMStringMap::RemoveDataAttr(const nsAString& aProp)
{
// Currently removing property, attribute is already removed.
if (mRemovingProp) {
return;
}
nsAutoString attr;
if (!DataPropToAttr(aProp, attr)) {
return;
}
nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
if (!attrAtom) {
return;
}
mElement->UnsetAttr(kNameSpaceID_None, attrAtom, PR_TRUE);
}
nsGenericHTMLElement* nsDOMStringMap::GetElement()
{
return mElement;
}
/* [notxpcom] void removeProp (in nsIAtom attr); */
NS_IMETHODIMP_(void) nsDOMStringMap::RemoveProp(nsIAtom* aAttr)
{
nsContentUtils::AddScriptRunner(new nsDOMStringMapRemoveProp(this, aAttr));
}
nsresult nsDOMStringMap::RemovePropInternal(nsIAtom* aAttr)
{
nsAutoString attr;
aAttr->ToString(attr);
nsAutoString prop;
NS_ENSURE_TRUE(AttrToDataProp(attr, prop), NS_OK);
jsval val;
JSContext* cx = nsContentUtils::GetCurrentJSContext();
nsresult rv = nsContentUtils::WrapNative(cx, JS_GetScopeChain(cx),
this, &val);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, JSVAL_TO_OBJECT(val))) {
return NS_ERROR_FAILURE;
}
// Guard against infinite recursion. Prevents the stack from looking like
// ...
// RemoveProp
// ...
// RemoveDataAttr
// ...
// RemoveProp
mRemovingProp = PR_TRUE;
jsval dummy;
JS_DeleteUCProperty2(cx, JSVAL_TO_OBJECT(val), prop.get(), prop.Length(),
&dummy);
mRemovingProp = PR_FALSE;
return NS_OK;
}
/**
* Returns a list of dataset properties corresponding to the data
* attributes on the element.
*/
nsresult nsDOMStringMap::GetDataPropList(nsTArray<nsString>& aResult)
{
PRUint32 attrCount = mElement->GetAttrCount();
// Iterate through all the attributes and add property
// names corresponding to data attributes to return array.
for (PRUint32 i = 0; i < attrCount; ++i) {
nsAutoString attrString;
const nsAttrName* attrName = mElement->GetAttrNameAt(i);
attrName->LocalName()->ToString(attrString);
nsAutoString prop;
if (!AttrToDataProp(attrString, prop)) {
continue;
}
aResult.AppendElement(prop);
}
return NS_OK;
}
/**
* Converts a dataset property name to the corresponding data attribute name.
* (ex. aBigFish to data-a-big-fish).
*/
PRBool nsDOMStringMap::DataPropToAttr(const nsAString& aProp,
nsAString& aResult)
{
const PRUnichar* cur = aProp.BeginReading();
const PRUnichar* end = aProp.EndReading();
// String corresponding to the data attribute on the element.
nsAutoString attr;
// Length of attr will be at least the length of the property + 5 for "data-".
attr.SetCapacity(aProp.Length() + 5);
attr.Append(NS_LITERAL_STRING("data-"));
// Iterate property by character to form attribute name.
// Return syntax error if there is a sequence of "-" followed by a character
// in the range "a" to "z".
// Replace capital characters with "-" followed by lower case character.
// Otherwise, simply append character to attribute name.
for (; cur < end; ++cur) {
const PRUnichar* next = cur + 1;
if (PRUnichar('-') == *cur && next < end &&
PRUnichar('a') <= *next && *next <= PRUnichar('z')) {
// Syntax error if character following "-" is in range "a" to "z".
return PR_FALSE;
}
if (PRUnichar('A') <= *cur && *cur <= PRUnichar('Z')) {
// Uncamel-case characters in the range of "A" to "Z".
attr.Append(PRUnichar('-'));
attr.Append(*cur - 'A' + 'a');
} else {
attr.Append(*cur);
}
}
aResult.Assign(attr);
return PR_TRUE;
}
/**
* Converts a data attribute name to the corresponding dataset property name.
* (ex. data-a-big-fish to aBigFish).
*/
PRBool nsDOMStringMap::AttrToDataProp(const nsAString& aAttr,
nsAString& aResult)
{
// If the attribute name does not begin with "data-" then it can not be
// a data attribute.
if (!StringBeginsWith(aAttr, NS_LITERAL_STRING("data-"))) {
return PR_FALSE;
}
// Start reading attribute from first character after "data-".
const PRUnichar* cur = aAttr.BeginReading() + 5;
const PRUnichar* end = aAttr.EndReading();
// Dataset property name. Ensure that the string is large enough to store
// all the characters in the property name.
nsAutoString prop;
// Iterate through attrName by character to form property name.
// If there is a sequence of "-" followed by a character in the range "a" to
// "z" then replace with upper case letter.
// Otherwise append character to property name.
for (; cur < end; ++cur) {
const PRUnichar* next = cur + 1;
if (PRUnichar('-') == *cur && next < end &&
PRUnichar('a') <= *next && *next <= PRUnichar('z')) {
// Upper case the lower case letters that follow a "-".
prop.Append(*next - 'a' + 'A');
// Consume character to account for "-" character.
++cur;
} else {
// Simply append character if camel case is not necessary.
prop.Append(*cur);
}
}
aResult.Assign(prop);
return PR_TRUE;
}

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* William Chen <wchen@mozilla.com> (Original Author)
*
* 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 ***** */
#ifndef nsDOMStringMap_h
#define nsDOMStringMap_h
#include "nsIDOMDOMStringMap.h"
#include "nsCycleCollectionParticipant.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsString.h"
class nsGenericHTMLElement;
class nsDOMStringMap : public nsIDOMDOMStringMap
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMDOMSTRINGMAP
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
nsDOMStringMap(nsGenericHTMLElement* aElement);
// GetDataPropList is not defined in IDL due to difficulty
// of returning arrays in IDL. Instead, we cast to this
// class if this method needs to be called.
nsresult GetDataPropList(nsTArray<nsString>& aResult);
nsresult RemovePropInternal(nsIAtom* aAttr);
nsGenericHTMLElement* GetElement();
private:
virtual ~nsDOMStringMap();
protected:
nsRefPtr<nsGenericHTMLElement> mElement;
// Flag to guard against infinite recursion.
PRBool mRemovingProp;
PRBool DataPropToAttr(const nsAString& aProp, nsAString& aResult);
PRBool AttrToDataProp(const nsAString& aAttr, nsAString& aResult);
};
#endif

View File

@@ -103,6 +103,8 @@
#include "nsIDOMText.h" #include "nsIDOMText.h"
#include "nsDOMStringMap.h"
#include "nsIEditor.h" #include "nsIEditor.h"
#include "nsIEditorIMESupport.h" #include "nsIEditorIMESupport.h"
#include "nsEventDispatcher.h" #include "nsEventDispatcher.h"
@@ -302,7 +304,7 @@ nsGenericHTMLElement::DOMQueryInterface(nsIDOMHTMLElement *aElement,
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
// No closing bracket, because NS_INTERFACE_MAP_END does that for us. // No closing bracket, because NS_INTERFACE_MAP_END does that for us.
nsresult nsresult
nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst) const nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst) const
{ {
@@ -364,6 +366,33 @@ nsGenericHTMLElement::SetAttribute(const nsAString& aName,
aValue, PR_TRUE); aValue, PR_TRUE);
} }
nsresult
nsGenericHTMLElement::GetDataset(nsIDOMDOMStringMap** aDataset)
{
nsDOMSlots *slots = DOMSlots();
if (!slots->mDataset) {
// mDataset is a weak reference so assignment will not AddRef.
// AddRef is called before assigning to out parameter.
slots->mDataset = new nsDOMStringMap(this);
}
NS_ADDREF(*aDataset = slots->mDataset);
return NS_OK;
}
nsresult
nsGenericHTMLElement::ClearDataset()
{
nsDOMSlots *slots = GetExistingDOMSlots();
NS_ASSERTION(slots && slots->mDataset,
"Slots should exist and dataset should not be null.");
slots->mDataset = nsnull;
return NS_OK;
}
// Implementation for nsIDOMHTMLElement // Implementation for nsIDOMHTMLElement
nsresult nsresult
nsGenericHTMLElement::GetId(nsAString& aId) nsGenericHTMLElement::GetId(nsAString& aId)
@@ -1231,6 +1260,12 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
manager->RemoveScriptEventListener(aAttribute); manager->RemoveScriptEventListener(aAttribute);
} }
} }
// Remove dataset property if necessary.
nsDOMSlots *slots = GetExistingDOMSlots();
if (slots && slots->mDataset) {
slots->mDataset->RemoveProp(aAttribute);
}
} }
nsresult rv = nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute, nsresult rv = nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute,

View File

@@ -64,6 +64,7 @@ class nsIEditor;
struct nsRect; struct nsRect;
struct nsSize; struct nsSize;
class nsHTMLFormElement; class nsHTMLFormElement;
class nsIDOMDOMStringMap;
typedef nsMappedAttributeElement nsGenericHTMLElementBase; typedef nsMappedAttributeElement nsGenericHTMLElementBase;
@@ -150,6 +151,9 @@ public:
nsresult GetContentEditable(nsAString& aContentEditable); nsresult GetContentEditable(nsAString& aContentEditable);
nsresult GetIsContentEditable(PRBool* aContentEditable); nsresult GetIsContentEditable(PRBool* aContentEditable);
nsresult SetContentEditable(const nsAString &aContentEditable); nsresult SetContentEditable(const nsAString &aContentEditable);
nsresult GetDataset(nsIDOMDOMStringMap** aDataset);
// Callback for destructor of of dataset to ensure to null out weak pointer.
nsresult ClearDataset();
// Implementation for nsIContent // Implementation for nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,

View File

@@ -591,19 +591,25 @@ nsHTMLCanvasElement::UpdateContext(nsIPropertyBag *aNewContextOptions)
return NS_OK; return NS_OK;
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsIntSize sz = GetWidthHeight();
rv = mCurrentContext->SetIsOpaque(GetIsOpaque()); rv = mCurrentContext->SetIsOpaque(GetIsOpaque());
if (NS_FAILED(rv)) if (NS_FAILED(rv)) {
mCurrentContext = nsnull;
return rv; return rv;
}
rv = mCurrentContext->SetContextOptions(aNewContextOptions); rv = mCurrentContext->SetContextOptions(aNewContextOptions);
if (NS_FAILED(rv)) if (NS_FAILED(rv)) {
mCurrentContext = nsnull;
return rv; return rv;
}
nsIntSize sz = GetWidthHeight();
rv = mCurrentContext->SetDimensions(sz.width, sz.height); rv = mCurrentContext->SetDimensions(sz.width, sz.height);
if (NS_FAILED(rv)) if (NS_FAILED(rv)) {
mCurrentContext = nsnull;
return rv; return rv;
}
return rv; return rv;
} }

View File

@@ -84,7 +84,6 @@ public:
RestoreSelectionState(nsTextEditorState *aState, nsTextControlFrame *aFrame, RestoreSelectionState(nsTextEditorState *aState, nsTextControlFrame *aFrame,
PRInt32 aStart, PRInt32 aEnd) PRInt32 aStart, PRInt32 aEnd)
: mFrame(aFrame), : mFrame(aFrame),
mWeakFrame(aFrame),
mStart(aStart), mStart(aStart),
mEnd(aEnd), mEnd(aEnd),
mTextEditorState(aState) mTextEditorState(aState)
@@ -92,19 +91,24 @@ public:
} }
NS_IMETHOD Run() { NS_IMETHOD Run() {
if (mWeakFrame.IsAlive()) { if (mFrame) {
// SetSelectionRange leads to Selection::AddRange which flushes Layout - // SetSelectionRange leads to Selection::AddRange which flushes Layout -
// need to block script to avoid nested PrepareEditor calls (bug 642800). // need to block script to avoid nested PrepareEditor calls (bug 642800).
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
mFrame->SetSelectionRange(mStart, mEnd); mFrame->SetSelectionRange(mStart, mEnd);
mTextEditorState->HideSelectionIfBlurred(); mTextEditorState->HideSelectionIfBlurred();
} }
mTextEditorState->FinishedRestoringSelection();
return NS_OK; return NS_OK;
} }
// Let the text editor tell us we're no longer relevant - avoids use of nsWeakFrame
void Revoke() {
mFrame = nsnull;
}
private: private:
nsTextControlFrame* mFrame; nsTextControlFrame* mFrame;
nsWeakFrame mWeakFrame;
PRInt32 mStart; PRInt32 mStart;
PRInt32 mEnd; PRInt32 mEnd;
nsTextEditorState* mTextEditorState; nsTextEditorState* mTextEditorState;
@@ -645,7 +649,7 @@ protected:
protected: protected:
nsWeakFrame mFrame; nsIFrame* mFrame;
nsITextControlElement* const mTxtCtrlElement; nsITextControlElement* const mTxtCtrlElement;
@@ -673,7 +677,8 @@ protected:
*/ */
nsTextInputListener::nsTextInputListener(nsITextControlElement* aTxtCtrlElement) nsTextInputListener::nsTextInputListener(nsITextControlElement* aTxtCtrlElement)
: mTxtCtrlElement(aTxtCtrlElement) : mFrame(nsnull)
, mTxtCtrlElement(aTxtCtrlElement)
, mSelectionWasCollapsed(PR_TRUE) , mSelectionWasCollapsed(PR_TRUE)
, mHadUndoItems(PR_FALSE) , mHadUndoItems(PR_FALSE)
, mHadRedoItems(PR_FALSE) , mHadRedoItems(PR_FALSE)
@@ -703,7 +708,9 @@ NS_IMETHODIMP
nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel, PRInt16 aReason) nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel, PRInt16 aReason)
{ {
PRBool collapsed; PRBool collapsed;
if (!mFrame.IsAlive() || !aDoc || !aSel || NS_FAILED(aSel->GetIsCollapsed(&collapsed))) nsWeakFrame weakFrame = mFrame;
if (!aDoc || !aSel || NS_FAILED(aSel->GetIsCollapsed(&collapsed)))
return NS_OK; return NS_OK;
// Fire the select event // Fire the select event
@@ -748,7 +755,7 @@ nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection*
mSelectionWasCollapsed = collapsed; mSelectionWasCollapsed = collapsed;
if (!mFrame.IsAlive() || !nsContentUtils::IsFocusedContent(mFrame->GetContent())) if (!weakFrame.IsAlive() || !nsContentUtils::IsFocusedContent(mFrame->GetContent()))
return NS_OK; return NS_OK;
return UpdateTextInputCommands(NS_LITERAL_STRING("select")); return UpdateTextInputCommands(NS_LITERAL_STRING("select"));
@@ -799,7 +806,6 @@ DoCommandCallback(const char *aCommand, void *aData)
NS_IMETHODIMP NS_IMETHODIMP
nsTextInputListener::KeyDown(nsIDOMEvent *aDOMEvent) nsTextInputListener::KeyDown(nsIDOMEvent *aDOMEvent)
{ {
NS_ENSURE_STATE(mFrame.IsAlive());
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent)); nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG); NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
@@ -818,7 +824,6 @@ nsTextInputListener::KeyDown(nsIDOMEvent *aDOMEvent)
NS_IMETHODIMP NS_IMETHODIMP
nsTextInputListener::KeyPress(nsIDOMEvent *aDOMEvent) nsTextInputListener::KeyPress(nsIDOMEvent *aDOMEvent)
{ {
NS_ENSURE_STATE(mFrame.IsAlive());
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent)); nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG); NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
@@ -837,7 +842,6 @@ nsTextInputListener::KeyPress(nsIDOMEvent *aDOMEvent)
NS_IMETHODIMP NS_IMETHODIMP
nsTextInputListener::KeyUp(nsIDOMEvent *aDOMEvent) nsTextInputListener::KeyUp(nsIDOMEvent *aDOMEvent)
{ {
NS_ENSURE_STATE(mFrame.IsAlive());
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent)); nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG); NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
@@ -859,8 +863,9 @@ nsTextInputListener::KeyUp(nsIDOMEvent *aDOMEvent)
NS_IMETHODIMP NS_IMETHODIMP
nsTextInputListener::EditAction() nsTextInputListener::EditAction()
{ {
NS_ENSURE_STATE(mFrame.IsAlive()); nsWeakFrame weakFrame = mFrame;
nsITextControlFrame* frameBase = do_QueryFrame(mFrame.GetFrame());
nsITextControlFrame* frameBase = do_QueryFrame(mFrame);
nsTextControlFrame* frame = static_cast<nsTextControlFrame*> (frameBase); nsTextControlFrame* frame = static_cast<nsTextControlFrame*> (frameBase);
NS_ASSERTION(frame, "Where is our frame?"); NS_ASSERTION(frame, "Where is our frame?");
// //
@@ -887,7 +892,7 @@ nsTextInputListener::EditAction()
mHadRedoItems = numRedoItems != 0; mHadRedoItems = numRedoItems != 0;
} }
if (!mFrame.IsAlive()) { if (!weakFrame.IsAlive()) {
return NS_OK; return NS_OK;
} }
@@ -916,8 +921,6 @@ nsTextInputListener::EditAction()
nsresult nsresult
nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate) nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate)
{ {
NS_ENSURE_STATE(mFrame.IsAlive());
nsIContent* content = mFrame->GetContent(); nsIContent* content = mFrame->GetContent();
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
@@ -967,6 +970,7 @@ nsTextInputListener::GetKeyBindings()
nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement) nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement)
: mTextCtrlElement(aOwningElement), : mTextCtrlElement(aOwningElement),
mRestoringSelection(nsnull),
mBoundFrame(nsnull), mBoundFrame(nsnull),
mTextListener(nsnull), mTextListener(nsnull),
mEditorInitialized(PR_FALSE), mEditorInitialized(PR_FALSE),
@@ -1385,8 +1389,13 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
// Restore our selection after being bound to a new frame // Restore our selection after being bound to a new frame
if (mSelState) { if (mSelState) {
nsContentUtils::AddScriptRunner(new RestoreSelectionState(this, mBoundFrame, mSelState->mStart, mSelState->mEnd)); if (mRestoringSelection) // paranoia
mSelState = nsnull; mRestoringSelection->Revoke();
mRestoringSelection = new RestoreSelectionState(this, mBoundFrame, mSelState->mStart, mSelState->mEnd);
if (mRestoringSelection) {
nsContentUtils::AddScriptRunner(mRestoringSelection);
mSelState = nsnull;
}
} }
return rv; return rv;
@@ -1419,6 +1428,11 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
nsAutoString value; nsAutoString value;
GetValue(value, PR_TRUE); GetValue(value, PR_TRUE);
if (mRestoringSelection) {
mRestoringSelection->Revoke();
mRestoringSelection = nsnull;
}
// Save our selection state if needed. // Save our selection state if needed.
// Note that nsTextControlFrame::GetSelectionRange attempts to initialize the // Note that nsTextControlFrame::GetSelectionRange attempts to initialize the
// editor before grabbing the range, and because this is not an acceptable // editor before grabbing the range, and because this is not an acceptable

View File

@@ -140,6 +140,8 @@ struct SelectionState;
* frame is bound to the text editor state object. * frame is bound to the text editor state object.
*/ */
class RestoreSelectionState;
class nsTextEditorState { class nsTextEditorState {
public: public:
explicit nsTextEditorState(nsITextControlElement* aOwningElement); explicit nsTextEditorState(nsITextControlElement* aOwningElement);
@@ -213,6 +215,8 @@ public:
void HideSelectionIfBlurred(); void HideSelectionIfBlurred();
private: private:
friend class RestoreSelectionState;
// not copy constructible // not copy constructible
nsTextEditorState(const nsTextEditorState&); nsTextEditorState(const nsTextEditorState&);
// not assignable // not assignable
@@ -225,6 +229,8 @@ private:
void DestroyEditor(); void DestroyEditor();
void Clear(); void Clear();
void FinishedRestoringSelection() { mRestoringSelection = nsnull; }
class InitializationGuard { class InitializationGuard {
public: public:
explicit InitializationGuard(nsTextEditorState& aState) : explicit InitializationGuard(nsTextEditorState& aState) :
@@ -253,6 +259,7 @@ private:
nsITextControlElement* const mTextCtrlElement; nsITextControlElement* const mTextCtrlElement;
nsRefPtr<nsTextInputSelectionImpl> mSelCon; nsRefPtr<nsTextInputSelectionImpl> mSelCon;
nsAutoPtr<SelectionState> mSelState; nsAutoPtr<SelectionState> mSelState;
RestoreSelectionState* mRestoringSelection;
nsCOMPtr<nsIEditor> mEditor; nsCOMPtr<nsIEditor> mEditor;
nsCOMPtr<nsIContent> mRootNode; nsCOMPtr<nsIContent> mRootNode;
nsCOMPtr<nsIContent> mPlaceholderDiv; nsCOMPtr<nsIContent> mPlaceholderDiv;

View File

@@ -274,6 +274,7 @@ _TEST_FILES = \
test_bug643051.html \ test_bug643051.html \
test_bug583514.html \ test_bug583514.html \
test_bug514437.html \ test_bug514437.html \
test_bug560112.html \
test_bug649134.html \ test_bug649134.html \
$(NULL) $(NULL)

View File

@@ -0,0 +1,212 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=560112
-->
<head>
<title>Test for Bug 560112</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=560112">Mozilla Bug 560112</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 560112 **/
/**
* Sets dataset property. Checks data attribute "attr".
* Gets dataset property. Checks data attribute "attr".
* Overwrites dataset property Checks data attribute "attr".
* Deletes dataset property. Checks data attribute "attr".
*/
function SetGetOverwriteDel(attr, prop)
{
var el = document.createElement('div');
// Set property.
is(prop in el.dataset, false, 'Property should not be in dataset before setting.');
el.dataset[prop] = "zzzzzz";
is(prop in el.dataset, true, 'Property should be in dataset after setting.');
ok(el.hasAttribute(attr), 'Element should have data attribute for dataset property "' + prop + '".');
// Get property.
is(el.dataset[prop], "zzzzzz", 'Dataset property "' + prop + '" should have value "zzzzzz".');
is(el.getAttribute(attr), "zzzzzz", 'Attribute "' + attr + '" should have value "zzzzzz".');
// Overwrite property.
el.dataset[prop] = "yyyyyy";
is(el.dataset[prop], "yyyyyy", 'Dataset property "' + prop + '" should have value "yyyyyy".');
is(el.getAttribute(attr), "yyyyyy", 'Attribute "' + attr + '" should have value "yyyyyy".');
// Delete property.
delete el.dataset[prop];
ok(!el.hasAttribute(attr), 'Element should not have data attribute for dataset property "' + prop + '".');
is(prop in el.dataset, false, 'Deleted property should not be in dataset.');
}
/**
* Sets dataset property and expects exception.
*/
function SetExpectException(prop)
{
var el = document.createElement('div');
try {
el.dataset[prop] = "xxxxxx";
ok(false, 'Exception should have been thrown.');
} catch (ex) {
ok(true, 'Exception should have been thrown.');
}
}
/**
* Adds attributes in "attrList" to element.
* Deletes attributes in "delList" from element.
* Checks for "numProp" properties in dataset.
*/
function DelAttrEnumerate(attrList, delList, numProp)
{
var el = document.createElement('div');
// Adds attributes in "attrList".
for (var i = 0; i < attrList.length; ++i) {
el.setAttribute(attrList[i], "aaaaaa");
}
// Remove attributes in "delList".
for (var i = 0; i < delList.length; ++i) {
el.removeAttribute(delList[i]);
}
var numPropCounted = 0;
for (var prop in el.dataset) {
if (el.dataset[prop] == "aaaaaa") {
++numPropCounted;
}
}
is(numPropCounted, numProp, 'Number of enumerable dataset properties is incorrent after attribute removal.');
}
/**
* Adds attributes in "attrList" to element.
* Checks for "numProp" properties in dataset.
*/
function Enumerate(attrList, numProp)
{
var el = document.createElement('div');
// Adds attributes in "attrList" to element.
for (var i = 0; i < attrList.length; ++i) {
el.setAttribute(attrList[i], "aaaaaa");
}
var numPropCounted = 0;
for (var prop in el.dataset) {
if (el.dataset[prop] == "aaaaaa") {
++numPropCounted;
}
}
is(numPropCounted, numProp, 'Number of enumerable dataset properties is incorrect.');
}
/**
* Adds dataset property then removes attribute from element and check for presence of
* properties using the "in" operator.
*/
function AddPropDelAttr(attr, prop)
{
var el = document.createElement('div');
el.dataset[prop] = 'dddddd';
is(prop in el.dataset, true, 'Operator "in" should return true after setting property.');
el.removeAttribute(attr);
is(prop in el.dataset, false, 'Operator "in" should return false for removed attribute.');
}
/**
* Adds then removes attribute from element and check for presence of properties using the
* "in" operator.
*/
function AddDelAttr(attr, prop)
{
var el = document.createElement('div');
el.setAttribute(attr, 'dddddd');
is(prop in el.dataset, true, 'Operator "in" should return true after setting attribute.');
el.removeAttribute(attr);
is(prop in el.dataset, false, 'Operator "in" should return false for removed attribute.');
}
// Typical use case.
SetGetOverwriteDel('data-property', 'property');
SetGetOverwriteDel('data-a-longer-property', 'aLongerProperty');
AddDelAttr('data-property', 'property');
AddDelAttr('data-a-longer-property', 'aLongerProperty');
AddPropDelAttr('data-property', 'property');
AddPropDelAttr('data-a-longer-property', 'aLongerProperty');
// Empty property name.
SetGetOverwriteDel('data-', '');
// Leading dash characters.
SetGetOverwriteDel('data--', '-');
SetGetOverwriteDel('data--d', 'D');
SetGetOverwriteDel('data---d', '-D');
// Trailing dash characters.
SetGetOverwriteDel('data-d-', 'd-');
SetGetOverwriteDel('data-d--', 'd--');
SetGetOverwriteDel('data-d-d-', 'dD-');
// "data-" in attribute name.
SetGetOverwriteDel('data-data-', 'data-');
SetGetOverwriteDel('data-data-data-', 'dataData-');
// Longer attribute.
SetGetOverwriteDel('data-long-long-long-long-long-long-long-long-long-long-long-long-long', 'longLongLongLongLongLongLongLongLongLongLongLongLong');
var longAttr = 'data-long';
var longProp = 'long';
for (var i = 0; i < 30000; ++i) {
// Create really long attribute and property names.
longAttr += '-long';
longProp += 'Long';
}
SetGetOverwriteDel(longAttr, longProp);
// Syntax error in setting dataset property (dash followed by lower case).
SetExpectException('-a');
SetExpectException('a-a');
SetExpectException('a-a-a');
// Invalid character.
SetExpectException('a a');
// Enumeration over dataset properties.
Enumerate(['data-a-big-fish'], 1);
Enumerate(['dat-a-big-fish'], 0);
Enumerate(['data-'], 1);
Enumerate(['data-', 'data-more-data'], 2);
Enumerate(['daaata-', 'data-more-data'], 1);
// Delete data attributes and enumerate properties.
DelAttrEnumerate(['data-one', 'data-two'], ['data-one'], 1);
DelAttrEnumerate(['data-one', 'data-two'], ['data-three'], 2);
DelAttrEnumerate(['data-one', 'data-two'], ['one'], 2);
</script>
</pre>
</body>
</html>

View File

@@ -305,16 +305,13 @@ nsXBLPrototypeBinding::Init(const nsACString& aID,
nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI)); nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// The binding URI might not be a nsIURL (e.g. for data: URIs). In that case, // The binding URI might be an immutable URI (e.g. for about: URIs). In that case,
// we always use the first binding, so we don't need to keep track of the ID. // we'll fail in SetRef below, but that doesn't matter much for now.
nsCOMPtr<nsIURL> bindingURL = do_QueryInterface(mBindingURI); if (aFirstBinding) {
if (bindingURL) { rv = mBindingURI->Clone(getter_AddRefs(mAlternateBindingURI));
if (aFirstBinding) { NS_ENSURE_SUCCESS(rv, rv);
rv = mBindingURI->Clone(getter_AddRefs(mAlternateBindingURI));
NS_ENSURE_SUCCESS(rv, rv);
}
bindingURL->SetRef(aID);
} }
mBindingURI->SetRef(aID);
mXBLDocInfoWeak = aInfo; mXBLDocInfoWeak = aInfo;

View File

@@ -862,9 +862,7 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nsCAutoString ref; nsCAutoString ref;
nsCOMPtr<nsIURL> url(do_QueryInterface(aURI)); aURI->GetRef(ref);
if (url)
url->GetRef(ref);
nsCOMPtr<nsIDocument> boundDocument = aBoundElement->GetOwnerDoc(); nsCOMPtr<nsIDocument> boundDocument = aBoundElement->GetOwnerDoc();
@@ -1129,12 +1127,8 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsRefPtr<nsXBLDocumentInfo> info; nsRefPtr<nsXBLDocumentInfo> info;
nsCOMPtr<nsIURI> documentURI; nsCOMPtr<nsIURI> documentURI;
rv = aBindingURI->Clone(getter_AddRefs(documentURI)); rv = aBindingURI->CloneIgnoringRef(getter_AddRefs(documentURI));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURL> documentURL(do_QueryInterface(documentURI));
if (documentURL)
documentURL->SetRef(EmptyCString());
#ifdef MOZ_XUL #ifdef MOZ_XUL
// We've got a file. Check our XBL document cache. // We've got a file. Check our XBL document cache.

View File

@@ -743,15 +743,10 @@ TX_CompileStylesheet(nsINode* aNode, txMozillaXSLTProcessor* aProcessor,
nsIURI* docUri = doc->GetDocumentURI(); nsIURI* docUri = doc->GetDocumentURI();
NS_ENSURE_TRUE(docUri, NS_ERROR_FAILURE); NS_ENSURE_TRUE(docUri, NS_ERROR_FAILURE);
docUri->Clone(getter_AddRefs(uri)); // We need to remove the ref, a URI with a ref would mean that we have an
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
// We need to remove the ref, a URL with a ref would mean that we have an
// embedded stylesheet. // embedded stylesheet.
nsCOMPtr<nsIURL> url = do_QueryInterface(uri); docUri->CloneIgnoringRef(getter_AddRefs(uri));
if (url) { NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
url->SetRef(EmptyCString());
}
uri->GetSpec(spec); uri->GetSpec(spec);
NS_ConvertUTF8toUTF16 stylesheetURI(spec); NS_ConvertUTF8toUTF16 stylesheetURI(spec);

View File

@@ -328,34 +328,29 @@ nsXULContentUtils::MakeElementURI(nsIDocument* aDocument,
// Convert an element's ID to a URI that can be used to refer to // Convert an element's ID to a URI that can be used to refer to
// the element in the XUL graph. // the element in the XUL graph.
nsIURI *docURL = aDocument->GetDocumentURI(); nsIURI *docURI = aDocument->GetDocumentURI();
NS_ENSURE_TRUE(docURL, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(docURI, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIURI> docURIClone; nsRefPtr<nsIURI> docURIClone;
nsresult rv = docURL->Clone(getter_AddRefs(docURIClone)); nsresult rv = docURI->Clone(getter_AddRefs(docURIClone));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURL> mutableURL(do_QueryInterface(docURIClone)); rv = docURIClone->SetRef(NS_ConvertUTF16toUTF8(aElementID));
if (!mutableURL) { if (NS_SUCCEEDED(rv)) {
nsCString uri; return docURIClone->GetSpec(aURI);
rv = docURL->GetSpec(aURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString ref;
NS_EscapeURL(NS_ConvertUTF16toUTF8(aElementID), esc_FilePath | esc_AlwaysCopy, ref);
aURI.Append('#');
aURI.Append(ref);
return NS_OK;
} }
NS_ENSURE_TRUE(mutableURL, NS_ERROR_NOT_AVAILABLE); // docURIClone is apparently immutable. Fine - we can append ref manually.
rv = docURI->GetSpec(aURI);
rv = mutableURL->SetRef(NS_ConvertUTF16toUTF8(aElementID));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return mutableURL->GetSpec(aURI); nsCAutoString ref;
NS_EscapeURL(NS_ConvertUTF16toUTF8(aElementID), esc_FilePath | esc_AlwaysCopy, ref);
aURI.Append('#');
aURI.Append(ref);
return NS_OK;
} }
@@ -390,27 +385,9 @@ nsXULContentUtils::MakeElementID(nsIDocument* aDocument,
aDocument->GetDocumentCharacterSet().get()); aDocument->GetDocumentCharacterSet().get());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURL> url = do_QueryInterface(uri); nsCAutoString ref;
if (url) { uri->GetRef(ref);
nsCAutoString ref; CopyUTF8toUTF16(ref, aElementID);
url->GetRef(ref);
CopyUTF8toUTF16(ref, aElementID);
} else {
const char* start = aURI.BeginReading();
const char* end = aURI.EndReading();
const char* chr = end;
while (--chr >= start) {
if (*chr == '#') {
nsDependentCSubstring ref = Substring(chr + 1, end);
nsCAutoString unescaped;
CopyUTF8toUTF16(NS_UnescapeURL(ref, esc_FilePath, unescaped), aElementID);
return NS_OK;
}
}
aElementID.Truncate();
}
return NS_OK; return NS_OK;
} }

View File

@@ -122,9 +122,15 @@ ConsoleAPI.prototype = {
if (!aID) if (!aID)
return; return;
let stack = this.getStackTrace();
// Skip the first frame since it contains an internal call.
let frame = stack[1];
let consoleEvent = { let consoleEvent = {
ID: aID, ID: aID,
level: aLevel, level: aLevel,
filename: frame.filename,
lineNumber: frame.lineNumber,
functionName: frame.functionName,
arguments: aArguments arguments: aArguments
}; };
@@ -157,7 +163,7 @@ ConsoleAPI.prototype = {
} }
return stack; return stack;
}, }
}; };
let NSGetFactory = XPCOMUtils.generateNSGetFactory([ConsoleAPI]); let NSGetFactory = XPCOMUtils.generateNSGetFactory([ConsoleAPI]);

View File

@@ -46,6 +46,8 @@
#include "WrapperFactory.h" #include "WrapperFactory.h"
#include "AccessCheck.h" #include "AccessCheck.h"
#include "xpcprivate.h"
#include "nscore.h" #include "nscore.h"
#include "nsDOMClassInfo.h" #include "nsDOMClassInfo.h"
#include "nsCRT.h" #include "nsCRT.h"
@@ -135,6 +137,8 @@
#include "nsIDOMNameList.h" #include "nsIDOMNameList.h"
#include "nsIDOMNSElement.h" #include "nsIDOMNSElement.h"
#include "nsDOMStringMap.h"
// HTMLFormElement helper includes // HTMLFormElement helper includes
#include "nsIForm.h" #include "nsIForm.h"
#include "nsIFormControl.h" #include "nsIFormControl.h"
@@ -473,6 +477,8 @@
#include "nsIDOMFileError.h" #include "nsIDOMFileError.h"
#include "nsIDOMFormData.h" #include "nsIDOMFormData.h"
#include "nsIDOMDOMStringMap.h"
#include "nsIDOMDesktopNotification.h" #include "nsIDOMDesktopNotification.h"
#include "nsIDOMNavigatorDesktopNotification.h" #include "nsIDOMNavigatorDesktopNotification.h"
@@ -569,6 +575,14 @@ static const char kDOMStringBundleURL[] =
nsIXPCScriptable::WANT_GETPROPERTY | \ nsIXPCScriptable::WANT_GETPROPERTY | \
nsIXPCScriptable::WANT_ENUMERATE) nsIXPCScriptable::WANT_ENUMERATE)
#define DOMSTRINGMAP_SCRIPTABLE_FLAGS \
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_ENUMERATE | \
nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_DELPROPERTY | \
nsIXPCScriptable::WANT_SETPROPERTY | \
nsIXPCScriptable::WANT_GETPROPERTY)
#define EVENTTARGET_SCRIPTABLE_FLAGS \ #define EVENTTARGET_SCRIPTABLE_FLAGS \
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \ (DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_ADDPROPERTY) nsIXPCScriptable::WANT_ADDPROPERTY)
@@ -1337,6 +1351,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
EVENTTARGET_SCRIPTABLE_FLAGS) EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozURLProperty, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(MozURLProperty, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozBlobBuilder, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMStringMap, nsDOMStringMapSH,
DOMSTRINGMAP_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH, NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
DEFAULT_SCRIPTABLE_FLAGS | DEFAULT_SCRIPTABLE_FLAGS |
@@ -1434,6 +1453,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLActiveInfo, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(WebGLActiveInfo, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(WebGLExtension, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1556,6 +1577,7 @@ static const nsConstructorFuncMapData kConstructorFuncMap[] =
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker) NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker) NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFile::NewFile) NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFile::NewFile)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
}; };
nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull; nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
@@ -3982,12 +4004,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob) DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob) DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile) DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob) DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile) DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
@@ -4008,6 +4028,14 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozURLProperty) DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozURLProperty)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozBlobBuilder, nsIDOMBlobBuilder)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlobBuilder)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(DOMStringMap, nsIDOMDOMStringMap)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMStringMap)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow) DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow) DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow) DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
@@ -4185,6 +4213,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLActiveInfo) DOM_CLASSINFO_MAP_ENTRY(nsIWebGLActiveInfo)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLExtension, nsIWebGLExtension)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtension)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest) DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest) DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
@@ -8530,6 +8562,139 @@ nsContentListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
return list->GetNamedItem(aName, aCache); return list->GetNamedItem(aName, aCache);
} }
NS_IMETHODIMP
nsDOMStringMapSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,
JSObject **objp, PRBool *_retval)
{
nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
nsDependentJSString prop(id);
if (dataset->HasDataAttr(prop)) {
*_retval = JS_DefinePropertyById(cx, obj, id, JSVAL_VOID,
nsnull, nsnull,
JSPROP_ENUMERATE | JSPROP_SHARED);
*objp = obj;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMStringMapSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRBool *_retval)
{
nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
nsDOMStringMap* stringMap = static_cast<nsDOMStringMap*>(dataset.get());
nsTArray<nsString> properties;
nsresult rv = stringMap->GetDataPropList(properties);
NS_ENSURE_SUCCESS(rv, rv);
for (PRUint32 i = 0; i < properties.Length(); ++i) {
nsDependentString prop(properties[i]);
*_retval = JS_DefineUCProperty(cx, obj, prop.get(), prop.Length(),
JSVAL_VOID, nsnull, nsnull,
JSPROP_ENUMERATE | JSPROP_SHARED);
NS_ENSURE_TRUE(*_retval, NS_ERROR_FAILURE);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMStringMapSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
*parentObj = globalObj;
nsDOMStringMap* dataset = static_cast<nsDOMStringMap*>(nativeObj);
nsIDocument* document = dataset->GetElement()->GetOwnerDoc();
NS_ENSURE_TRUE(document, NS_OK);
nsCOMPtr<nsIScriptGlobalObject> sgo =
do_GetInterface(document->GetScopeObject());
if (sgo) {
JSObject *global = sgo->GetGlobalJSObject();
if (global) {
*parentObj = global;
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMStringMapSH::DelProperty(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj, jsid id,
jsval *vp, PRBool *_retval)
{
nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
*_retval = PR_TRUE;
nsDependentJSString prop(id);
dataset->RemoveDataAttr(prop);
return NS_OK;
}
NS_IMETHODIMP
nsDOMStringMapSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp,
PRBool *_retval)
{
nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
nsDependentJSString propName(id);
nsAutoString prop;
nsresult rv = dataset->GetDataAttr(propName, prop);
NS_ENSURE_SUCCESS(rv, rv);
if (prop.IsVoid()) {
*vp = JSVAL_VOID;
return NS_SUCCESS_I_DID_SOMETHING;
}
nsStringBuffer* valBuf;
*vp = XPCStringConvert::ReadableToJSVal(cx, prop, &valBuf);
if (valBuf) {
prop.ForgetSharedBuffer();
}
return NS_SUCCESS_I_DID_SOMETHING;
}
NS_IMETHODIMP
nsDOMStringMapSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp,
PRBool *_retval)
{
nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
JSString *val = JS_ValueToString(cx, *vp);
NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
nsDependentJSString propName(id);
nsDependentJSString propVal;
NS_ENSURE_TRUE(propVal.init(cx, val), NS_ERROR_UNEXPECTED);
nsresult rv = dataset->SetDataAttr(propName, propVal);
NS_ENSURE_SUCCESS(rv, rv);
return NS_SUCCESS_I_DID_SOMETHING;
}
NS_IMETHODIMP NS_IMETHODIMP
nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags, JSObject *obj, jsid id, PRUint32 flags,

View File

@@ -896,6 +896,41 @@ public:
}; };
// DOMStringMap helper for .dataset property on elements.
class nsDOMStringMapSH : public nsDOMGenericSH
{
public:
nsDOMStringMapSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
{
}
virtual ~nsDOMStringMapSH()
{
}
public:
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,
JSObject **objp, PRBool *_retval);
NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRBool *_retval);
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj);
NS_IMETHOD DelProperty(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj, jsid id,
jsval *vp, PRBool *_retval);
NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsDOMStringMapSH(aData);
}
};
// Document helper, for document.location and document.on* // Document helper, for document.location and document.on*

View File

@@ -406,6 +406,9 @@ DOMCI_CLASS(FileException)
DOMCI_CLASS(FileError) DOMCI_CLASS(FileError)
DOMCI_CLASS(FileReader) DOMCI_CLASS(FileReader)
DOMCI_CLASS(MozURLProperty) DOMCI_CLASS(MozURLProperty)
DOMCI_CLASS(MozBlobBuilder)
DOMCI_CLASS(DOMStringMap)
// DOM modal content window class, almost identical to Window // DOM modal content window class, almost identical to Window
DOMCI_CLASS(ModalContentWindow) DOMCI_CLASS(ModalContentWindow)
@@ -471,8 +474,8 @@ DOMCI_CLASS(WebGLFramebuffer)
DOMCI_CLASS(WebGLRenderbuffer) DOMCI_CLASS(WebGLRenderbuffer)
DOMCI_CLASS(WebGLUniformLocation) DOMCI_CLASS(WebGLUniformLocation)
DOMCI_CLASS(WebGLActiveInfo) DOMCI_CLASS(WebGLActiveInfo)
DOMCI_CLASS(WebGLExtension)
// WebGL Buffers
DOMCI_CLASS(PaintRequest) DOMCI_CLASS(PaintRequest)
DOMCI_CLASS(PaintRequestList) DOMCI_CLASS(PaintRequestList)

View File

@@ -79,6 +79,8 @@
#include "nsICachingChannel.h" #include "nsICachingChannel.h"
#include "nsPluginArray.h" #include "nsPluginArray.h"
#include "nsIPluginHost.h" #include "nsIPluginHost.h"
#include "nsPluginHost.h"
#include "nsIPluginInstanceOwner.h"
#include "nsGeolocation.h" #include "nsGeolocation.h"
#include "nsDesktopNotification.h" #include "nsDesktopNotification.h"
#include "nsContentCID.h" #include "nsContentCID.h"
@@ -6548,20 +6550,17 @@ nsGlobalWindow::InitJavaProperties()
// can fail. If it fails, we won't try again... // can fail. If it fails, we won't try again...
mDidInitJavaProperties = PR_TRUE; mDidInitJavaProperties = PR_TRUE;
// Check whether the plugin supports NPRuntime, if so, init through
// it.
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
if (!host) {
return;
}
mDummyJavaPluginOwner = new nsDummyJavaPluginOwner(mDoc); mDummyJavaPluginOwner = new nsDummyJavaPluginOwner(mDoc);
if (!mDummyJavaPluginOwner) { if (!mDummyJavaPluginOwner) {
return; return;
} }
host->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner); nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
return;
}
pluginHost->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner);
// It's possible for us (or the Java plugin, rather) to process // It's possible for us (or the Java plugin, rather) to process
// events during the above call, which can lead to this window being // events during the above call, which can lead to this window being

View File

@@ -1140,6 +1140,7 @@ protected:
nsresult CheckURL(nsIURI *url, nsIDocShellLoadInfo** aLoadInfo); nsresult CheckURL(nsIURI *url, nsIDocShellLoadInfo** aLoadInfo);
nsString mCachedHash;
nsWeakPtr mDocShell; nsWeakPtr mDocShell;
}; };

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