mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and tracemonkey.
This commit is contained in:
commit
52221a8477
@ -199,23 +199,32 @@ private:
|
||||
printf("uri: %s", spec);
|
||||
|
||||
#define NS_LOG_ACCDOC_TYPE(aDocument) \
|
||||
PRBool isContent = nsCoreUtils::IsContentDocument(aDocument); \
|
||||
printf("%s document", (isContent ? "content" : "chrome"));
|
||||
if (aDocument->IsActive()) { \
|
||||
PRBool isContent = nsCoreUtils::IsContentDocument(aDocument); \
|
||||
printf("%s document", (isContent ? "content" : "chrome")); \
|
||||
} else { \
|
||||
printf("document type: [failed]"); \
|
||||
}
|
||||
|
||||
#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; \
|
||||
if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) \
|
||||
docShellBusy.AppendLiteral("'none'"); \
|
||||
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'"); \
|
||||
nsCOMPtr<nsISupports> container = aDocument->GetContainer(); \
|
||||
if (container) { \
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container); \
|
||||
PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; \
|
||||
docShell->GetBusyFlags(&busyFlags); \
|
||||
if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) \
|
||||
docShellBusy.AppendLiteral("'none'"); \
|
||||
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());
|
||||
|
||||
#define NS_LOG_ACCDOC_DOCSTATES(aDocument) \
|
||||
@ -336,20 +345,22 @@ private:
|
||||
printf(" "); \
|
||||
NS_LOG_ACCDOC_ADDRESS(aDocument, aDocAcc) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_URI(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_SHELLSTATE(aDocument) \
|
||||
printf("; "); \
|
||||
NS_LOG_ACCDOC_TYPE(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_DOCSTATES(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \
|
||||
printf(", "); \
|
||||
NS_LOG_ACCDOC_DOCPARENT(aDocument) \
|
||||
printf("\n"); \
|
||||
if (aDocument) { \
|
||||
NS_LOG_ACCDOC_URI(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_SHELLSTATE(aDocument) \
|
||||
printf("; "); \
|
||||
NS_LOG_ACCDOC_TYPE(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_DOCSTATES(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \
|
||||
printf("\n "); \
|
||||
NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \
|
||||
printf(", "); \
|
||||
NS_LOG_ACCDOC_DOCPARENT(aDocument) \
|
||||
printf("\n"); \
|
||||
} \
|
||||
}
|
||||
#define NS_LOG_ACCDOC_DOCINFO_END \
|
||||
printf(" }\n");
|
||||
|
@ -160,7 +160,8 @@ nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIContent *aContent,
|
||||
control->GetItemAtIndex(index, getter_AddRefs(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) {
|
||||
(*aSetSize)--;
|
||||
@ -201,7 +202,8 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
|
||||
container->GetItemAtIndex(index, getter_AddRefs(item));
|
||||
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
|
||||
|
||||
nsAccessible* itemAcc = GetAccService()->GetAccessible(itemNode);
|
||||
nsAccessible* itemAcc = itemNode ?
|
||||
GetAccService()->GetAccessible(itemNode) : nsnull;
|
||||
|
||||
if (itemAcc) {
|
||||
PRUint32 itemRole = Role(itemAcc);
|
||||
@ -220,8 +222,9 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
|
||||
nsCOMPtr<nsIDOMXULElement> item;
|
||||
container->GetItemAtIndex(index, getter_AddRefs(item));
|
||||
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
|
||||
|
||||
nsAccessible* itemAcc = GetAccService()->GetAccessible(itemNode);
|
||||
|
||||
nsAccessible* itemAcc =
|
||||
itemNode ? GetAccService()->GetAccessible(itemNode) : nsnull;
|
||||
|
||||
if (itemAcc) {
|
||||
PRUint32 itemRole = Role(itemAcc);
|
||||
|
@ -842,6 +842,8 @@ nsAccessibilityService::GetAccessibleInShell(nsINode* aNode,
|
||||
nsAccessible*
|
||||
nsAccessibilityService::GetAccessible(nsINode* aNode)
|
||||
{
|
||||
NS_PRECONDITION(aNode, "Getting an accessible for null node! Crash.");
|
||||
|
||||
nsDocAccessible* document = GetDocAccessible(aNode->GetOwnerDoc());
|
||||
return document ? document->GetAccessible(aNode) : nsnull;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ nsLeafAccessible::CacheChildren()
|
||||
nsLinkableAccessible::
|
||||
nsLinkableAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
|
||||
nsAccessibleWrap(aContent, aShell),
|
||||
mActionContent(nsnull),
|
||||
mActionAcc(nsnull),
|
||||
mIsLink(PR_FALSE),
|
||||
mIsOnclick(PR_FALSE)
|
||||
{
|
||||
@ -107,11 +107,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsAccessibleWrap)
|
||||
NS_IMETHODIMP
|
||||
nsLinkableAccessible::TakeFocus()
|
||||
{
|
||||
nsAccessible *actionAcc = GetActionAccessible();
|
||||
if (actionAcc)
|
||||
return actionAcc->TakeFocus();
|
||||
|
||||
return nsAccessibleWrap::TakeFocus();
|
||||
return mActionAcc ? mActionAcc->TakeFocus() : nsAccessibleWrap::TakeFocus();
|
||||
}
|
||||
|
||||
PRUint64
|
||||
@ -120,8 +116,7 @@ nsLinkableAccessible::NativeState()
|
||||
PRUint64 states = nsAccessibleWrap::NativeState();
|
||||
if (mIsLink) {
|
||||
states |= states::LINKED;
|
||||
nsAccessible* actionAcc = GetActionAccessible();
|
||||
if (actionAcc->State() & states::TRAVERSED)
|
||||
if (mActionAcc->State() & states::TRAVERSED)
|
||||
states |= states::TRAVERSED;
|
||||
}
|
||||
|
||||
@ -137,13 +132,7 @@ nsLinkableAccessible::GetValue(nsAString& aValue)
|
||||
if (!aValue.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
if (mIsLink) {
|
||||
nsAccessible *actionAcc = GetActionAccessible();
|
||||
if (actionAcc)
|
||||
return actionAcc->GetValue(aValue);
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return mIsLink ? mActionAcc->GetValue(aValue) : NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
@ -152,7 +141,7 @@ nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNumActions);
|
||||
|
||||
*aNumActions = mActionContent ? 1 : 0;
|
||||
*aNumActions = mActionAcc ? 1 : 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -182,11 +171,8 @@ nsLinkableAccessible::DoAction(PRUint8 aIndex)
|
||||
if (aIndex != eAction_Jump)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsAccessible *actionAcc = GetActionAccessible();
|
||||
if (actionAcc)
|
||||
return actionAcc->DoAction(aIndex);
|
||||
|
||||
return nsAccessibleWrap::DoAction(aIndex);
|
||||
return mActionAcc ? mActionAcc->DoAction(aIndex) :
|
||||
nsAccessibleWrap::DoAction(aIndex);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -194,11 +180,8 @@ nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
|
||||
{
|
||||
aKeyboardShortcut.Truncate();
|
||||
|
||||
nsAccessible *actionAcc = GetActionAccessible();
|
||||
if (actionAcc)
|
||||
return actionAcc->GetKeyboardShortcut(aKeyboardShortcut);
|
||||
|
||||
return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
|
||||
return mActionAcc ? mActionAcc->GetKeyboardShortcut(aKeyboardShortcut) :
|
||||
nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -207,7 +190,9 @@ nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
|
||||
void
|
||||
nsLinkableAccessible::Shutdown()
|
||||
{
|
||||
mActionContent = nsnull;
|
||||
mIsLink = PR_FALSE;
|
||||
mIsOnclick = PR_FALSE;
|
||||
mActionAcc = nsnull;
|
||||
nsAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
@ -218,14 +203,11 @@ already_AddRefed<nsIURI>
|
||||
nsLinkableAccessible::GetAnchorURI(PRUint32 aAnchorIndex)
|
||||
{
|
||||
if (mIsLink) {
|
||||
nsAccessible* link = GetActionAccessible();
|
||||
if (link) {
|
||||
NS_ASSERTION(link->IsHyperLink(),
|
||||
"nsIAccessibleHyperLink isn't implemented.");
|
||||
NS_ASSERTION(mActionAcc->IsHyperLink(),
|
||||
"nsIAccessibleHyperLink isn't implemented.");
|
||||
|
||||
if (link->IsHyperLink())
|
||||
return link->GetAnchorURI(aAnchorIndex);
|
||||
}
|
||||
if (mActionAcc->IsHyperLink())
|
||||
return mActionAcc->GetAnchorURI(aAnchorIndex);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
@ -241,55 +223,36 @@ nsLinkableAccessible::BindToParent(nsAccessible* aParent,
|
||||
nsAccessibleWrap::BindToParent(aParent, aIndexInParent);
|
||||
|
||||
// Cache action content.
|
||||
mActionContent = nsnull;
|
||||
mActionAcc = nsnull;
|
||||
mIsLink = PR_FALSE;
|
||||
mIsOnclick = PR_FALSE;
|
||||
|
||||
nsIContent* walkUpContent = mContent;
|
||||
PRBool isOnclick = nsCoreUtils::HasClickListener(walkUpContent);
|
||||
|
||||
if (isOnclick) {
|
||||
mActionContent = walkUpContent;
|
||||
if (nsCoreUtils::HasClickListener(mContent)) {
|
||||
mActionAcc = this;
|
||||
mIsOnclick = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
while ((walkUpContent = walkUpContent->GetParent())) {
|
||||
nsAccessible* walkUpAcc =
|
||||
GetAccService()->GetAccessibleInWeakShell(walkUpContent, mWeakShell);
|
||||
|
||||
// XXX: The logic looks broken since the click listener may be registered
|
||||
// on non accessible node in parent chain but this node is skipped when tree
|
||||
// is traversed.
|
||||
nsAccessible* walkUpAcc = this;
|
||||
while ((walkUpAcc = walkUpAcc->GetParent()) && !walkUpAcc->IsDoc()) {
|
||||
if (walkUpAcc && walkUpAcc->Role() == nsIAccessibleRole::ROLE_LINK &&
|
||||
walkUpAcc->State() & states::LINKED) {
|
||||
mIsLink = PR_TRUE;
|
||||
mActionContent = walkUpContent;
|
||||
mActionAcc = walkUpAcc;
|
||||
return;
|
||||
}
|
||||
|
||||
isOnclick = nsCoreUtils::HasClickListener(walkUpContent);
|
||||
if (isOnclick) {
|
||||
mActionContent = walkUpContent;
|
||||
if (nsCoreUtils::HasClickListener(walkUpAcc->GetContent())) {
|
||||
mActionAcc = walkUpAcc;
|
||||
mIsOnclick = PR_TRUE;
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -108,14 +108,10 @@ protected:
|
||||
// nsAccessible
|
||||
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;
|
||||
|
||||
nsCOMPtr<nsIContent> mActionContent;
|
||||
nsAccessible* mActionAcc;
|
||||
PRPackedBool mIsLink;
|
||||
PRPackedBool mIsOnclick;
|
||||
};
|
||||
|
@ -493,12 +493,10 @@ nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
|
||||
nsCAutoString path;
|
||||
uri->GetPath(path);
|
||||
|
||||
nsCAutoString::const_iterator start, end;
|
||||
path.BeginReading(start);
|
||||
path.EndReading(end);
|
||||
|
||||
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
|
||||
|
@ -213,8 +213,8 @@ nsOuterDocAccessible::RemoveChild(nsAccessible *aAccessible)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_LOG_ACCDOCDESTROY("remove document from outerdoc",
|
||||
child->GetDocumentNode())
|
||||
NS_LOG_ACCDOCDESTROY_FOR("remove document from outerdoc",
|
||||
child->GetDocumentNode(), child)
|
||||
NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this)
|
||||
|
||||
PRBool wasRemoved = nsAccessible::RemoveChild(child);
|
||||
|
@ -1014,7 +1014,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
|
||||
}
|
||||
|
||||
if (aType == eGetBefore) {
|
||||
endOffset = aOffset;
|
||||
finalEndOffset = aOffset;
|
||||
}
|
||||
else {
|
||||
// Start moving forward from the start so that we don't get
|
||||
|
@ -192,11 +192,11 @@
|
||||
/**
|
||||
* Load wrong URI what results in error page loading.
|
||||
*/
|
||||
function loadErrorPageInvoker()
|
||||
function loadErrorPageInvoker(aURL, aURLDescr)
|
||||
{
|
||||
this.invoke = function loadErrorPageInvoker_invoke()
|
||||
{
|
||||
gTabBrowser.loadURI("www.wronguri.wronguri");
|
||||
gTabBrowser.loadURI(aURL);
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
@ -209,7 +209,7 @@
|
||||
|
||||
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 loadURIInvoker("about:mozilla"));
|
||||
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.invoke();
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ _TEST_FILES = \
|
||||
test_doc.html \
|
||||
test_hypertext.html \
|
||||
test_passwords.html \
|
||||
$(warning test_singleline.html disabled due to bug 652459) \
|
||||
$(warning test_whitespaces.html disabled due to bug 652459) \
|
||||
test_singleline.html \
|
||||
test_whitespaces.html \
|
||||
test_words.html \
|
||||
$(NULL)
|
||||
|
||||
|
@ -216,10 +216,10 @@
|
||||
|
||||
// BOUNDARY_WORD_START
|
||||
testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
@ -231,10 +231,10 @@
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
testTextBeforeOffset(6, BOUNDARY_WORD_START, "hello ", 0, 6,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(7, BOUNDARY_WORD_START, "hello ", 0, 6,
|
||||
"input", kTodo, kTodo, kTodo,
|
||||
"div", kTodo, kTodo, kTodo,
|
||||
@ -246,10 +246,10 @@
|
||||
"editable", kTodo, kTodo, kTodo,
|
||||
"textarea", kTodo, kTodo, kTodo);
|
||||
testTextBeforeOffset(9, BOUNDARY_WORD_START, "my ", 6, 9,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(10, BOUNDARY_WORD_START, "my ", 6, 9,
|
||||
"input", kTodo, kTodo, kTodo,
|
||||
"div", kTodo, kTodo, kTodo,
|
||||
@ -268,10 +268,10 @@
|
||||
|
||||
// BOUNDARY_WORD_END
|
||||
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
@ -283,10 +283,10 @@
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
testTextBeforeOffset(6, BOUNDARY_WORD_END, "hello ", 0, 6,
|
||||
"input", kTodo, kTodo, kTodo,
|
||||
"div", kTodo, kTodo, kTodo,
|
||||
"editable", kTodo, kTodo, kTodo,
|
||||
"textarea", kTodo, kTodo, kTodo);
|
||||
"input", kTodo, kTodo, kOk,
|
||||
"div", kTodo, kTodo, kOk,
|
||||
"editable", kTodo, kTodo, kOk,
|
||||
"textarea", kTodo, kTodo, kOk);
|
||||
testTextBeforeOffset(7, BOUNDARY_WORD_END, "hello ", 0, 6,
|
||||
"input", kTodo, kTodo, kTodo,
|
||||
"div", kTodo, kTodo, kTodo,
|
||||
@ -320,10 +320,10 @@
|
||||
|
||||
// BOUNDARY_LINE_START
|
||||
testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(1, BOUNDARY_LINE_START, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
@ -342,10 +342,10 @@
|
||||
|
||||
// BOUNDARY_LINE_END
|
||||
testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
|
@ -196,10 +196,10 @@
|
||||
|
||||
// BOUNDARY_WORD_START
|
||||
testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
@ -211,10 +211,10 @@
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
testTextBeforeOffset(6, BOUNDARY_WORD_START, "Brave ", 0, 6,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(9, BOUNDARY_WORD_START, "Brave ", 0, 6,
|
||||
"input", kTodo, kTodo, kTodo,
|
||||
"div", kTodo, kTodo, kTodo,
|
||||
@ -226,10 +226,10 @@
|
||||
"editable", kTodo, kTodo, kTodo,
|
||||
"textarea", kTodo, kTodo, kTodo);
|
||||
testTextBeforeOffset(11, BOUNDARY_WORD_START, "Sir ", 6, 11,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(15, BOUNDARY_WORD_START, "Sir ", 6, 11,
|
||||
"input", kTodo, kTodo, kTodo,
|
||||
"div", kTodo, kTodo, kTodo,
|
||||
@ -251,10 +251,10 @@
|
||||
"editable", kTodo, kTodo, kTodo,
|
||||
"textarea", kTodo, kTodo, kTodo);
|
||||
testTextBeforeOffset(19, BOUNDARY_WORD_START, "Robin ", 11, 19,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(20, BOUNDARY_WORD_START, "Robin ", 11, 19,
|
||||
"input", kTodo, kTodo, kTodo,
|
||||
"div", kTodo, kTodo, kTodo,
|
||||
@ -268,10 +268,10 @@
|
||||
|
||||
// BOUNDARY_WORD_END
|
||||
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
"editable", kTodo, kOk, kTodo,
|
||||
"textarea", kTodo, kOk, kTodo);
|
||||
"input", kOk, kOk, kOk,
|
||||
"div", kOk, kOk, kOk,
|
||||
"editable", kOk, kOk, kOk,
|
||||
"textarea", kOk, kOk, kOk);
|
||||
testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0,
|
||||
"input", kTodo, kOk, kTodo,
|
||||
"div", kTodo, kOk, kTodo,
|
||||
|
@ -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.
|
||||
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
|
||||
// preference is a string so that localizers can alter it.
|
||||
pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
|
||||
|
@ -462,7 +462,6 @@ statuspanel {
|
||||
margin-top: -3em;
|
||||
left: 0;
|
||||
max-width: 50%;
|
||||
-moz-transition: opacity 100ms ease-out;
|
||||
}
|
||||
|
||||
statuspanel:-moz-locale-dir(ltr)[mirror],
|
||||
@ -482,6 +481,7 @@ statuspanel[type=status] {
|
||||
}
|
||||
|
||||
statuspanel[type=overLink] {
|
||||
-moz-transition: opacity 100ms ease-out;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
|
@ -1385,7 +1385,7 @@ function prepareForStartup() {
|
||||
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
||||
#ifdef XP_MACOSX
|
||||
gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false);
|
||||
|
||||
@ -6698,12 +6698,15 @@ var gPluginHandler = {
|
||||
handleEvent : function(event) {
|
||||
let self = gPluginHandler;
|
||||
let plugin = event.target;
|
||||
let hideBarPrefName;
|
||||
let doc = plugin.ownerDocument;
|
||||
|
||||
// We're expecting the target to be a plugin.
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
|
||||
// Force a style flush, so that we ensure our binding is attached.
|
||||
plugin.clientTop;
|
||||
|
||||
switch (event.type) {
|
||||
case "PluginCrashed":
|
||||
self.pluginInstanceCrashed(plugin, event);
|
||||
@ -6713,32 +6716,38 @@ var gPluginHandler = {
|
||||
// For non-object plugin tags, register a click handler to install the
|
||||
// plugin. Object tags can, and often do, deal with that themselves,
|
||||
// so don't stomp on the page developers toes.
|
||||
if (!(plugin instanceof HTMLObjectElement))
|
||||
self.addLinkClickCallback(plugin, "installSinglePlugin");
|
||||
if (!(plugin instanceof HTMLObjectElement)) {
|
||||
// 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 */
|
||||
|
||||
case "PluginBlocklisted":
|
||||
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
|
||||
case "npapi-carbon-event-model-failure":
|
||||
hideBarPrefName = "plugins.hide_infobar_for_carbon_failure_plugin";
|
||||
if (gPrefService.getBoolPref(hideBarPrefName))
|
||||
return;
|
||||
|
||||
#endif
|
||||
self.pluginUnavailable(plugin, event.type);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case "PluginDisabled":
|
||||
self.addLinkClickCallback(plugin, "managePlugins");
|
||||
let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
|
||||
self.addLinkClickCallback(manageLink, "managePlugins");
|
||||
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) {
|
||||
@ -6757,10 +6766,10 @@ var gPluginHandler = {
|
||||
},
|
||||
|
||||
// Callback for user clicking on a missing (unsupported) plugin.
|
||||
installSinglePlugin: function (aEvent) {
|
||||
installSinglePlugin: function (plugin) {
|
||||
var missingPluginsArray = {};
|
||||
|
||||
var pluginInfo = getPluginInfo(aEvent.target);
|
||||
var pluginInfo = getPluginInfo(plugin);
|
||||
missingPluginsArray[pluginInfo.mimetype] = pluginInfo;
|
||||
|
||||
openDialog("chrome://mozapps/content/plugins/pluginInstallerWizard.xul",
|
||||
@ -6810,9 +6819,6 @@ var gPluginHandler = {
|
||||
let blockedNotification = notificationBox.getNotificationWithValue("blocked-plugins");
|
||||
let missingNotification = notificationBox.getNotificationWithValue("missing-plugins");
|
||||
|
||||
// If there is already an outdated plugin notification then do nothing
|
||||
if (outdatedNotification)
|
||||
return;
|
||||
|
||||
function showBlocklistInfo() {
|
||||
var url = formatURL("extensions.blocklist.detailsURL", true);
|
||||
@ -6844,7 +6850,7 @@ var gPluginHandler = {
|
||||
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
|
||||
createInstance(Ci.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", null);
|
||||
|
||||
|
||||
// Something aborted the quit process.
|
||||
if (cancelQuit.data)
|
||||
return;
|
||||
@ -6908,10 +6914,17 @@ var gPluginHandler = {
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// If there is already an outdated plugin notification then do nothing
|
||||
if (outdatedNotification)
|
||||
return;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
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");
|
||||
|
||||
if (carbonFailureNotification)
|
||||
@ -6923,11 +6936,18 @@ var gPluginHandler = {
|
||||
eventType = "PluginNotFound";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (eventType == "PluginBlocklisted") {
|
||||
if (gPrefService.getBoolPref("plugins.hide_infobar_for_missing_plugin")) // XXX add a new pref?
|
||||
return;
|
||||
|
||||
if (blockedNotification || missingNotification)
|
||||
return;
|
||||
}
|
||||
else if (eventType == "PluginOutdated") {
|
||||
if (gPrefService.getBoolPref("plugins.hide_infobar_for_outdated_plugin"))
|
||||
return;
|
||||
|
||||
// Cancel any notification about blocklisting/missing plugins
|
||||
if (blockedNotification)
|
||||
blockedNotification.close();
|
||||
@ -6935,6 +6955,9 @@ var gPluginHandler = {
|
||||
missingNotification.close();
|
||||
}
|
||||
else if (eventType == "PluginNotFound") {
|
||||
if (gPrefService.getBoolPref("plugins.hide_infobar_for_missing_plugin"))
|
||||
return;
|
||||
|
||||
if (missingNotification)
|
||||
return;
|
||||
|
||||
@ -6990,9 +7013,6 @@ var gPluginHandler = {
|
||||
// Remap the plugin name to a more user-presentable form.
|
||||
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]);
|
||||
|
||||
//
|
||||
@ -7000,12 +7020,6 @@ var gPluginHandler = {
|
||||
//
|
||||
let doc = plugin.ownerDocument;
|
||||
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");
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
let status;
|
||||
|
@ -58,7 +58,7 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource:///modules/PropertyPanel.jsm");
|
||||
|
||||
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_L10N = "chrome://browser/locale/scratchpad.properties";
|
||||
const SCRATCHPAD_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||
@ -75,7 +75,7 @@ var Scratchpad = {
|
||||
* Possible values:
|
||||
* - SCRATCHPAD_CONTEXT_CONTENT to execute code in the context of the current
|
||||
* 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.
|
||||
*/
|
||||
executionContext: SCRATCHPAD_CONTEXT_CONTENT,
|
||||
@ -121,6 +121,11 @@ var Scratchpad = {
|
||||
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.
|
||||
*/
|
||||
@ -129,8 +134,9 @@ var Scratchpad = {
|
||||
/**
|
||||
* 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
|
||||
* kept only for the current browser window and it is reset for each context
|
||||
* switch or navigator:browser window switch.
|
||||
* kept only for the current location in the current tab of the current
|
||||
* browser window and it is reset for each context switch,
|
||||
* navigator:browser window switch, tab switch or navigation.
|
||||
*/
|
||||
get contentSandbox()
|
||||
{
|
||||
@ -141,12 +147,16 @@ var Scratchpad = {
|
||||
}
|
||||
|
||||
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;
|
||||
this._contentSandbox = new Cu.Sandbox(contentWindow,
|
||||
{ sandboxPrototype: contentWindow, wantXrays: false });
|
||||
|
||||
this._previousBrowserWindow = this.browserWindow;
|
||||
this._previousBrowser = this.gBrowser.selectedBrowser;
|
||||
this._previousLocation = contentWindow.location.href;
|
||||
}
|
||||
|
||||
return this._contentSandbox;
|
||||
@ -283,7 +293,7 @@ var Scratchpad = {
|
||||
* Execute the selected text (if any) or the entire textbox content in the
|
||||
* current context.
|
||||
*/
|
||||
execute: function SP_execute()
|
||||
run: function SP_run()
|
||||
{
|
||||
let selection = this.selectedText || this.textbox.value;
|
||||
let result = this.evalForContext(selection);
|
||||
@ -298,7 +308,7 @@ var Scratchpad = {
|
||||
*/
|
||||
inspect: function SP_inspect()
|
||||
{
|
||||
let [selection, result] = this.execute();
|
||||
let [selection, result] = this.run();
|
||||
|
||||
if (result) {
|
||||
this.openPropertyPanel(selection, result);
|
||||
@ -307,11 +317,11 @@ var Scratchpad = {
|
||||
|
||||
/**
|
||||
* 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
|
||||
* selected text.
|
||||
*/
|
||||
print: function SP_print()
|
||||
display: function SP_display()
|
||||
{
|
||||
let selectionStart = this.textbox.selectionStart;
|
||||
let selectionEnd = this.textbox.selectionEnd;
|
||||
@ -319,7 +329,7 @@ var Scratchpad = {
|
||||
selectionEnd = this.textbox.value.length;
|
||||
}
|
||||
|
||||
let [selection, result] = this.execute();
|
||||
let [selection, result] = this.run();
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
@ -556,23 +566,23 @@ var Scratchpad = {
|
||||
setContentContext: function SP_setContentContext()
|
||||
{
|
||||
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);
|
||||
this.statusbarStatus.label = content.getAttribute("label");
|
||||
this.executionContext = SCRATCHPAD_CONTEXT_CONTENT;
|
||||
this.statusbarStatus.label = content.getAttribute("label");
|
||||
this.resetContext();
|
||||
},
|
||||
|
||||
/**
|
||||
* 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");
|
||||
chrome.setAttribute("checked", true);
|
||||
this.statusbarStatus.label = chrome.getAttribute("label");
|
||||
this.executionContext = SCRATCHPAD_CONTEXT_CHROME;
|
||||
browser.setAttribute("checked", true);
|
||||
this.executionContext = SCRATCHPAD_CONTEXT_BROWSER;
|
||||
this.statusbarStatus.label = browser.getAttribute("label");
|
||||
this.resetContext();
|
||||
},
|
||||
|
||||
@ -584,6 +594,8 @@ var Scratchpad = {
|
||||
this._chromeSandbox = null;
|
||||
this._contentSandbox = null;
|
||||
this._previousWindow = null;
|
||||
this._previousBrowser = null;
|
||||
this._previousLocation = null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -604,10 +616,10 @@ var Scratchpad = {
|
||||
*/
|
||||
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 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);
|
||||
if (chrome) {
|
||||
@ -616,6 +628,7 @@ var Scratchpad = {
|
||||
errorConsoleCommand.removeAttribute("disabled");
|
||||
chromeContextCommand.removeAttribute("disabled");
|
||||
}
|
||||
this.insertIntro();
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -70,11 +70,11 @@
|
||||
-->
|
||||
|
||||
<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-print" oncommand="Scratchpad.print();"/>
|
||||
<command id="sp-cmd-display" oncommand="Scratchpad.display();"/>
|
||||
<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-errorConsole" oncommand="Scratchpad.openErrorConsole();" disabled="true"/>
|
||||
<command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/>
|
||||
@ -118,17 +118,17 @@
|
||||
<key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/>
|
||||
<key id="key_undo" key="&undoCmd.key;" modifiers="accel"/>
|
||||
<key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift"/>
|
||||
<key id="sp-key-execute"
|
||||
key="&execute.key;"
|
||||
command="sp-cmd-execute"
|
||||
<key id="sp-key-run"
|
||||
key="&run.key;"
|
||||
command="sp-cmd-run"
|
||||
modifiers="accel"/>
|
||||
<key id="sp-key-inspect"
|
||||
key="&inspect.key;"
|
||||
command="sp-cmd-inspect"
|
||||
modifiers="accel"/>
|
||||
<key id="sp-key-print"
|
||||
key="&print.key;"
|
||||
command="sp-cmd-print"
|
||||
<key id="sp-key-display"
|
||||
key="&display.key;"
|
||||
command="sp-cmd-display"
|
||||
modifiers="accel"/>
|
||||
<key id="sp-key-errorConsole"
|
||||
key="&errorConsoleCmd.commandkey;"
|
||||
@ -220,7 +220,6 @@
|
||||
key="key_selectAll"
|
||||
accesskey="&selectAllCmd.accesskey;"
|
||||
command="cmd_selectAll"/>
|
||||
<menuseparator/>
|
||||
|
||||
<!-- TODO: bug 650345 - implement search and replace
|
||||
<menuitem id="sp-menu-find"
|
||||
@ -238,38 +237,44 @@
|
||||
<menuseparator id="sp-execute-separator"/>
|
||||
-->
|
||||
|
||||
<menuitem id="sp-text-execute"
|
||||
label="&execute.label;"
|
||||
accesskey="&execute.accesskey;"
|
||||
key="sp-key-execute"
|
||||
command="sp-cmd-execute"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="sp-execute-menu" label="&executeMenu.label;"
|
||||
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"
|
||||
label="&inspect.label;"
|
||||
accesskey="&inspect.accesskey;"
|
||||
key="sp-key-inspect"
|
||||
command="sp-cmd-inspect"/>
|
||||
<menuitem id="sp-text-print"
|
||||
label="&print.label;"
|
||||
accesskey="&print.accesskey;"
|
||||
key="sp-key-print"
|
||||
command="sp-cmd-print"/>
|
||||
<menuitem id="sp-text-display"
|
||||
label="&display.label;"
|
||||
accesskey="&display.accesskey;"
|
||||
key="sp-key-display"
|
||||
command="sp-cmd-display"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="sp-context-menu"
|
||||
label="&contextMenu.label;"
|
||||
accesskey="&contextMenu.accesskey;">
|
||||
<menupopup id="sp-menu-context">
|
||||
<menu id="sp-environment-menu"
|
||||
label="&environmentMenu.label;"
|
||||
accesskey="&environmentMenu.accesskey;">
|
||||
<menupopup id="sp-menu-environment">
|
||||
<menuitem id="sp-menu-content"
|
||||
label="&contentContext.label;"
|
||||
accesskey="&contentContext.accesskey;"
|
||||
command="sp-cmd-contentContext"
|
||||
checked="true"
|
||||
type="radio"/>
|
||||
<menuitem id="sp-menu-chrome" hidden="true"
|
||||
command="sp-cmd-chromeContext"
|
||||
label="&chromeContext.label;"
|
||||
accesskey="&chromeContext.accesskey;"
|
||||
<menuitem id="sp-menu-browser" hidden="true"
|
||||
command="sp-cmd-browserContext"
|
||||
label="&browserContext.label;"
|
||||
accesskey="&browserContext.accesskey;"
|
||||
type="radio"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="sp-menu-resetContext"
|
||||
@ -306,21 +311,21 @@
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_selectAll"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="sp-text-execute"
|
||||
label="&execute.label;"
|
||||
accesskey="&execute.accesskey;"
|
||||
key="sp-key-execute"
|
||||
command="sp-cmd-execute"/>
|
||||
<menuitem id="sp-text-run"
|
||||
label="&run.label;"
|
||||
accesskey="&run.accesskey;"
|
||||
key="sp-key-run"
|
||||
command="sp-cmd-run"/>
|
||||
<menuitem id="sp-text-inspect"
|
||||
label="&inspect.label;"
|
||||
accesskey="&inspect.accesskey;"
|
||||
key="sp-key-inspect"
|
||||
command="sp-cmd-inspect"/>
|
||||
<menuitem id="sp-text-print"
|
||||
label="&print.label;"
|
||||
accesskey="&print.accesskey;"
|
||||
key="sp-key-print"
|
||||
command="sp-cmd-print"/>
|
||||
<menuitem id="sp-text-display"
|
||||
label="&display.label;"
|
||||
accesskey="&display.accesskey;"
|
||||
key="sp-key-display"
|
||||
command="sp-cmd-display"/>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
|
||||
@ -328,7 +333,7 @@
|
||||
multiline="true"
|
||||
flex="1"
|
||||
context="scratchpad-text-popup"
|
||||
placeholder="&textbox.placeholder;" />
|
||||
placeholder="&textbox.placeholder1;" />
|
||||
<statusbar id="scratchpad-statusbar" align="end">
|
||||
<statusbarpanel id="scratchpad-status"
|
||||
label="&contentContext.label;"
|
||||
|
@ -2902,7 +2902,7 @@
|
||||
tabWidth += "px";
|
||||
for (let i = numPinned; i < tabs.length; i++) {
|
||||
let tab = tabs[i];
|
||||
tab.style.maxWidth = tabWidth;
|
||||
tab.style.setProperty("max-width", tabWidth, "important");
|
||||
if (!isEndTab) { // keep tabs the same width
|
||||
tab.style.MozTransition = "none";
|
||||
tab.clientTop; // flush styles to skip animation; see bug 649247
|
||||
|
@ -194,6 +194,7 @@ _BROWSER_FILES = \
|
||||
browser_inspector_treePanel_result.html \
|
||||
browser_scratchpad_initialization.js \
|
||||
browser_scratchpad_contexts.js \
|
||||
browser_scratchpad_tab_switch.js \
|
||||
browser_scratchpad_execute_print.js \
|
||||
browser_scratchpad_inspect.js \
|
||||
browser_scratchpad_files.js \
|
||||
|
@ -127,7 +127,12 @@ function test3() {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ function runTests()
|
||||
ok(sp, "Scratchpad object exists in new window");
|
||||
|
||||
let chromeContextMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-menu-chrome");
|
||||
getElementById("sp-menu-browser");
|
||||
ok(chromeContextMenu, "Chrome context menuitem element exists");
|
||||
ok(!chromeContextMenu.hasAttribute("hidden"),
|
||||
"Chrome context menuitem is visible");
|
||||
@ -54,7 +54,7 @@ function runTests()
|
||||
"Error console menuitem is visible");
|
||||
|
||||
let chromeContextCommand = gScratchpadWindow.document.
|
||||
getElementById("sp-cmd-chromeContext");
|
||||
getElementById("sp-cmd-browserContext");
|
||||
ok(chromeContextCommand, "Chrome context command element exists");
|
||||
ok(!chromeContextCommand.hasAttribute("disabled"),
|
||||
"Chrome context command is disabled");
|
||||
|
@ -27,11 +27,11 @@ function runTests()
|
||||
let sp = gScratchpadWindow.Scratchpad;
|
||||
|
||||
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;
|
||||
|
||||
ok(contentMenu, "found #sp-menu-content");
|
||||
ok(chromeMenu, "found #sp-menu-chrome");
|
||||
ok(chromeMenu, "found #sp-menu-browser");
|
||||
ok(statusbar, "found Scratchpad.statusbarStatus");
|
||||
|
||||
sp.setContentContext();
|
||||
@ -54,14 +54,14 @@ function runTests()
|
||||
ok(!content.wrappedJSObject.foobarBug636725,
|
||||
"no content.foobarBug636725");
|
||||
|
||||
sp.execute();
|
||||
sp.run();
|
||||
|
||||
is(content.wrappedJSObject.foobarBug636725, "aloha",
|
||||
"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");
|
||||
|
||||
is(chromeMenu.getAttribute("checked"), "true",
|
||||
@ -77,37 +77,37 @@ function runTests()
|
||||
|
||||
ok(!window.foobarBug636725, "no window.foobarBug636725");
|
||||
|
||||
sp.execute();
|
||||
sp.run();
|
||||
|
||||
is(window.foobarBug636725, "aloha2", "window.foobarBug636725 has been set");
|
||||
|
||||
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");
|
||||
|
||||
// Check that the sandbox is cached.
|
||||
|
||||
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.execute();
|
||||
sp.run();
|
||||
|
||||
sp.textbox.value = "typeof foobarBug636725cache;";
|
||||
is(sp.execute()[1], "string",
|
||||
is(sp.run()[1], "string",
|
||||
"global variable exists across two different executions");
|
||||
|
||||
sp.resetContext();
|
||||
|
||||
is(sp.execute()[1], "undefined",
|
||||
is(sp.run()[1], "undefined",
|
||||
"global variable no longer exists after calling resetContext()");
|
||||
|
||||
sp.textbox.value = "var foobarBug636725cache2 = 'foo';";
|
||||
sp.execute();
|
||||
sp.run();
|
||||
|
||||
sp.textbox.value = "typeof foobarBug636725cache2;";
|
||||
is(sp.execute()[1], "string",
|
||||
is(sp.run()[1], "string",
|
||||
"global variable exists across two different executions");
|
||||
|
||||
sp.setContentContext();
|
||||
@ -115,7 +115,7 @@ function runTests()
|
||||
is(sp.executionContext, gScratchpadWindow.SCRATCHPAD_CONTEXT_CONTENT,
|
||||
"executionContext is content");
|
||||
|
||||
is(sp.execute()[1], "undefined",
|
||||
is(sp.run()[1], "undefined",
|
||||
"global variable no longer exists after changing the context");
|
||||
|
||||
gScratchpadWindow.close();
|
||||
|
@ -17,7 +17,7 @@ function test()
|
||||
gScratchpadWindow.addEventListener("load", runTests, false);
|
||||
}, 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()
|
||||
@ -31,7 +31,7 @@ function runTests()
|
||||
ok(sp.textbox, "textbox exists");
|
||||
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[1], content.wrappedJSObject.foobarBug636725,
|
||||
"execute()[1] is correct");
|
||||
@ -42,7 +42,7 @@ function runTests()
|
||||
is(content.wrappedJSObject.foobarBug636725, 2,
|
||||
"execute() updated window.foobarBug636725");
|
||||
|
||||
sp.print();
|
||||
sp.display();
|
||||
|
||||
is(content.wrappedJSObject.foobarBug636725, 3,
|
||||
"print() updated window.foobarBug636725");
|
||||
@ -69,7 +69,7 @@ function runTests()
|
||||
is(sp.textbox.selectionStart, 0, "selectionStart is 0");
|
||||
is(sp.textbox.selectionEnd, 29, "selectionEnd is 29");
|
||||
|
||||
exec = sp.execute();
|
||||
exec = sp.run();
|
||||
|
||||
is(exec[0], "window.foobarBug636725 = 'a';",
|
||||
"execute()[0] is correct");
|
||||
@ -88,7 +88,7 @@ function runTests()
|
||||
|
||||
sp.selectRange(0, 22);
|
||||
|
||||
sp.print();
|
||||
sp.display();
|
||||
|
||||
is(content.wrappedJSObject.foobarBug636725, "a",
|
||||
"print() worked for the selected range");
|
||||
|
@ -28,12 +28,12 @@ function runTests()
|
||||
|
||||
let sp = gScratchpadWindow.Scratchpad;
|
||||
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.print, "function", "Scratchpad.print() exists");
|
||||
is(typeof sp.display, "function", "Scratchpad.display() exists");
|
||||
|
||||
let chromeContextMenu = gScratchpadWindow.document.
|
||||
getElementById("sp-menu-chrome");
|
||||
getElementById("sp-menu-browser");
|
||||
ok(chromeContextMenu, "Chrome context menuitem element exists");
|
||||
is(chromeContextMenu.getAttribute("hidden"), "true",
|
||||
"Chrome context menuitem is hidden");
|
||||
@ -51,7 +51,7 @@ function runTests()
|
||||
"Error console menu item is hidden");
|
||||
|
||||
let chromeContextCommand = gScratchpadWindow.document.
|
||||
getElementById("sp-cmd-chromeContext");
|
||||
getElementById("sp-cmd-browserContext");
|
||||
ok(chromeContextCommand, "Chrome context command element exists");
|
||||
is(chromeContextCommand.getAttribute("disabled"), "true",
|
||||
"Chrome context command is disabled");
|
||||
|
111
browser/base/content/test/browser_scratchpad_tab_switch.js
Normal file
111
browser/base/content/test/browser_scratchpad_tab_switch.js
Normal 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();
|
||||
}
|
@ -33,10 +33,11 @@ function runTests()
|
||||
"sp-menu-open": "openFile",
|
||||
"sp-menu-save": "saveFile",
|
||||
"sp-menu-saveas": "saveFileAs",
|
||||
"sp-text-execute": "execute",
|
||||
"sp-text-run": "run",
|
||||
"sp-text-inspect": "inspect",
|
||||
"sp-text-display": "display",
|
||||
"sp-menu-content": "setContentContext",
|
||||
"sp-menu-chrome": "setChromeContext",
|
||||
"sp-menu-browser": "setBrowserContext",
|
||||
"sp-menu-resetContext": "resetContext",
|
||||
"sp-menu-errorConsole": "openErrorConsole",
|
||||
"sp-menu-webConsole": "openWebConsole",
|
||||
|
@ -1,5 +1,5 @@
|
||||
<html>
|
||||
<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>
|
||||
</html>
|
||||
|
@ -587,12 +587,10 @@ let AboutPermissions = {
|
||||
for each (let site in this._sites) {
|
||||
if (site.host.hasRootDomain(aHost)) {
|
||||
if (site == this._selectedSite) {
|
||||
// Clear site data from the DOM to maximize privacy.
|
||||
document.getElementById("site-label").value = "";
|
||||
document.getElementById("permissions-box").hidden = true;
|
||||
this._selectedSite = null;
|
||||
// Replace site-specific interface with "All Sites" interface.
|
||||
this.sitesList.selectedItem = document.getElementById("all-sites-item");
|
||||
}
|
||||
|
||||
|
||||
this.sitesList.removeChild(site.listitem);
|
||||
delete this._sites[site.host];
|
||||
}
|
||||
@ -604,6 +602,8 @@ let AboutPermissions = {
|
||||
*/
|
||||
onSitesListSelect: function(event) {
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -641,8 +641,6 @@ let AboutPermissions = {
|
||||
|
||||
this.updatePasswordsCount();
|
||||
this.updateCookiesCount();
|
||||
|
||||
document.getElementById("permissions-box").hidden = false;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -74,7 +74,7 @@
|
||||
</richlistbox>
|
||||
</vbox>
|
||||
|
||||
<vbox id="permissions-box" hidden="true" flex="1">
|
||||
<vbox id="permissions-box" flex="1">
|
||||
|
||||
<deck id="header-deck">
|
||||
<hbox id="site-header" class="pref-item" align="center">
|
||||
|
@ -240,6 +240,10 @@ var tests = [
|
||||
|
||||
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
|
||||
let testSiteItem = getSiteItem(TEST_URI_2.host);
|
||||
ok(!testSiteItem, "site removed from sites list");
|
||||
|
@ -61,33 +61,58 @@
|
||||
<!ENTITY selectAllCmd.key "A">
|
||||
<!ENTITY selectAllCmd.accesskey "A">
|
||||
|
||||
<!ENTITY execute.label "Execute">
|
||||
<!ENTITY execute.accesskey "E">
|
||||
<!ENTITY execute.key "t">
|
||||
<!ENTITY run.label "Run">
|
||||
<!ENTITY run.accesskey "R">
|
||||
<!ENTITY run.key "r">
|
||||
|
||||
<!ENTITY inspect.label "Inspect">
|
||||
<!ENTITY inspect.accesskey "I">
|
||||
<!ENTITY inspect.key "i">
|
||||
|
||||
<!ENTITY print.label "Print">
|
||||
<!ENTITY print.accesskey "p">
|
||||
<!ENTITY print.key "r">
|
||||
<!ENTITY display.label "Display">
|
||||
<!ENTITY display.accesskey "D">
|
||||
<!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.accesskey "C">
|
||||
-->
|
||||
|
||||
<!ENTITY contentContext.label "Content">
|
||||
<!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.accesskey "H">
|
||||
-->
|
||||
|
||||
<!-- 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.accesskey "R">
|
||||
|
||||
<!ENTITY executeMenu.label "Execute">
|
||||
<!ENTITY executeMenu.accesskey "X">
|
||||
|
||||
<!ENTITY toolsMenu.label "Tools">
|
||||
<!ENTITY toolsMenu.accesskey "T">
|
||||
|
||||
@ -99,5 +124,9 @@
|
||||
<!ENTITY webConsoleCmd.accesskey "W">
|
||||
<!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.">
|
||||
|
||||
|
@ -28,3 +28,8 @@ saveFileAs=Save File As
|
||||
# LOCALIZATION NOTE (saveFile.failed): This is the message displayed when file
|
||||
# save fails.
|
||||
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
|
||||
|
@ -441,20 +441,23 @@ function FindProxyForURL(url, host)
|
||||
var isHttp = matches[1] == 'http';
|
||||
var isHttps = matches[1] == 'https';
|
||||
var isWebSocket = matches[1] == 'ws';
|
||||
var isWebSocketSSL = matches[1] == 'wss';
|
||||
if (!matches[3])
|
||||
{
|
||||
if (isHttp | isWebSocket) matches[3] = '80';
|
||||
if (isHttps) matches[3] = '443';
|
||||
if (isHttps | isWebSocketSSL) matches[3] = '443';
|
||||
}
|
||||
if (isWebSocket)
|
||||
matches[1] = 'http';
|
||||
if (isWebSocketSSL)
|
||||
matches[1] = 'https';
|
||||
|
||||
var origin = matches[1] + '://' + matches[2] + ':' + matches[3];
|
||||
if (origins.indexOf(origin) < 0)
|
||||
return 'DIRECT';
|
||||
if (isHttp)
|
||||
return 'PROXY %(remote)s:%(httpport)s';
|
||||
if (isHttps || isWebSocket)
|
||||
if (isHttps || isWebSocket || isWebSocketSSL)
|
||||
return 'PROXY %(remote)s:%(sslport)s';
|
||||
return 'DIRECT';
|
||||
}""" % { "origins": origins,
|
||||
|
@ -150,6 +150,19 @@ nsNullPrincipalURI::SetPath(const nsACString &aPath)
|
||||
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
|
||||
nsNullPrincipalURI::GetPrePath(nsACString &_prePath)
|
||||
{
|
||||
@ -224,11 +237,18 @@ nsNullPrincipalURI::Clone(nsIURI **_newURI)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri =
|
||||
new nsNullPrincipalURI(mScheme + NS_LITERAL_CSTRING(":") + mPath);
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
|
||||
uri.forget(_newURI);
|
||||
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
|
||||
nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals)
|
||||
{
|
||||
@ -243,6 +263,14 @@ nsNullPrincipalURI::Equals(nsIURI *aOther, PRBool *_equals)
|
||||
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
|
||||
nsNullPrincipalURI::Resolve(const nsACString &aRelativePath,
|
||||
nsACString &_resolvedURI)
|
||||
|
@ -2027,8 +2027,8 @@ case "$target" in
|
||||
MOZ_OPTIMIZE_FLAGS="-O3 -fno-omit-frame-pointer"
|
||||
fi
|
||||
_PEDANTIC=
|
||||
CFLAGS="$CFLAGS -fpascal-strings -fno-common"
|
||||
CXXFLAGS="$CXXFLAGS -fpascal-strings -fno-common"
|
||||
CFLAGS="$CFLAGS -fno-common"
|
||||
CXXFLAGS="$CXXFLAGS -fno-common"
|
||||
DLL_SUFFIX=".dylib"
|
||||
DSO_LDOPTS=''
|
||||
STRIP="$STRIP -x -S"
|
||||
@ -4861,7 +4861,7 @@ NSS_DISABLE_DBM=
|
||||
NECKO_WIFI=1
|
||||
NECKO_COOKIES=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=
|
||||
BUILD_CTYPES=1
|
||||
XPC_IDISPATCH_SUPPORT=
|
||||
|
@ -40,6 +40,7 @@
|
||||
#define nsDOMFile_h__
|
||||
|
||||
#include "nsICharsetDetectionObserver.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIDOMFile.h"
|
||||
#include "nsIDOMFileList.h"
|
||||
#include "nsIDOMFileError.h"
|
||||
@ -56,9 +57,12 @@
|
||||
class nsIFile;
|
||||
class nsIInputStream;
|
||||
class nsIClassInfo;
|
||||
class nsIBlobBuilder;
|
||||
|
||||
nsresult NS_NewBlobBuilder(nsISupports* *aSupports);
|
||||
void ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd);
|
||||
|
||||
class nsDOMFile : public nsIDOMFile,
|
||||
public nsIDOMBlob_MOZILLA_2_0_BRANCH,
|
||||
public nsIXHRSendable,
|
||||
public nsICharsetDetectionObserver,
|
||||
public nsIJSNativeInitializer
|
||||
@ -67,7 +71,6 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMBLOB
|
||||
NS_DECL_NSIDOMFILE
|
||||
NS_DECL_NSIDOMBLOB_MOZILLA_2_0_BRANCH
|
||||
NS_DECL_NSIXHRSENDABLE
|
||||
|
||||
nsDOMFile(nsIFile *aFile, const nsAString& aContentType)
|
||||
|
@ -37,37 +37,33 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
%{C++
|
||||
#include "jsapi.h"
|
||||
%}
|
||||
|
||||
interface nsIDOMFileError;
|
||||
interface nsIInputStream;
|
||||
interface nsIURI;
|
||||
interface nsIPrincipal;
|
||||
interface nsIDOMBlob;
|
||||
|
||||
[scriptable, uuid(5822776a-049c-4de7-adb6-dd9efc39d082)]
|
||||
[scriptable, uuid(d5237f31-443a-460b-9e42-449a135346f0)]
|
||||
interface nsIDOMBlob : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long long size;
|
||||
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;
|
||||
// The caller is responsible for releasing the internalUrl from the
|
||||
// moz-filedata: protocol handler
|
||||
[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] in long long end,
|
||||
[optional] in DOMString contentType);
|
||||
};
|
||||
|
||||
[scriptable, uuid(ae1405b0-e411-481e-9606-b29ec7982687)]
|
||||
[scriptable, uuid(91c9ebd9-2a4a-4a38-9412-ef492a2799be)]
|
||||
interface nsIDOMFile : nsIDOMBlob
|
||||
{
|
||||
readonly attribute DOMString name;
|
||||
@ -84,3 +80,10 @@ interface nsIDOMFile : nsIDOMBlob
|
||||
DOMString getAsDataURL(); // 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);
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ interface nsIDOMClientRect;
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
const unsigned long TYPE_LOADING = 0;
|
||||
@ -113,14 +113,6 @@ interface nsIObjectLoadingContent : nsISupports
|
||||
*/
|
||||
[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
|
||||
* returns the nsIObjectFrame object which should be used when
|
||||
|
@ -51,10 +51,11 @@ interface nsPIDOMWindow;
|
||||
* http://dev.w3.org/html5/websockets/
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(4403cd57-07fc-477f-a062-d6ba7dd0781b)]
|
||||
[scriptable, uuid(431aea4c-568a-470e-b876-c57a29ff0fc6)]
|
||||
interface nsIWebSocket : nsISupports
|
||||
{
|
||||
readonly attribute DOMString url;
|
||||
readonly attribute DOMString protocol;
|
||||
|
||||
//ready state
|
||||
const unsigned short CONNECTING = 0;
|
||||
|
@ -307,13 +307,12 @@ nsresult
|
||||
Link::SetHash(const nsAString &aHash)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri(GetURIToMutate());
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
|
||||
if (!url) {
|
||||
if (!uri) {
|
||||
// Ignore failures to be compatible with NS4.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
(void)url->SetRef(NS_ConvertUTF16toUTF8(aHash));
|
||||
(void)uri->SetRef(NS_ConvertUTF16toUTF8(aHash));
|
||||
SetHrefAttribute(uri);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -444,15 +443,14 @@ Link::GetHash(nsAString &_hash)
|
||||
_hash.Truncate();
|
||||
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
|
||||
if (!url) {
|
||||
// Do not throw! Not having a valid URI or URL should result in an empty
|
||||
if (!uri) {
|
||||
// Do not throw! Not having a valid URI should result in an empty
|
||||
// string.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCAutoString ref;
|
||||
nsresult rv = url->GetRef(ref);
|
||||
nsresult rv = uri->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
|
||||
_hash.Assign(PRUnichar('#'));
|
||||
|
@ -92,6 +92,7 @@ CPPSRCS = \
|
||||
nsDataDocumentContentPolicy.cpp \
|
||||
nsDOMAttribute.cpp \
|
||||
nsDOMAttributeMap.cpp \
|
||||
nsDOMBlobBuilder.cpp \
|
||||
nsDOMDocumentType.cpp \
|
||||
nsDOMEventTargetWrapperCache.cpp \
|
||||
nsDOMFile.cpp \
|
||||
|
399
content/base/src/nsDOMBlobBuilder.cpp
Normal file
399
content/base/src/nsDOMBlobBuilder.cpp
Normal 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);
|
||||
}
|
@ -49,7 +49,6 @@
|
||||
#include "nsIConverterInputStream.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIIPCSerializable.h"
|
||||
@ -140,7 +139,6 @@ DOMCI_DATA(Blob, nsDOMFile)
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMFile)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFile)
|
||||
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(nsIXHRSendable)
|
||||
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
|
||||
nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
|
||||
const nsAString& aContentType, PRUint8 optional_argc,
|
||||
@ -307,7 +298,7 @@ nsDOMFile::MozSlice(PRInt64 aStart, PRInt64 aEnd,
|
||||
{
|
||||
*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;
|
||||
nsresult rv = GetSize(&thisLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -694,14 +694,10 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
|
||||
|
||||
// First, make sure we strip the ref from aURI.
|
||||
nsCOMPtr<nsIURI> clone;
|
||||
aURI->Clone(getter_AddRefs(clone));
|
||||
if (!clone) {
|
||||
nsresult rv = aURI->CloneIgnoringRef(getter_AddRefs(clone));
|
||||
if (NS_FAILED(rv) || !clone) {
|
||||
return nsnull;
|
||||
}
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(clone));
|
||||
if (url) {
|
||||
url->SetRef(EmptyCString());
|
||||
}
|
||||
|
||||
ExternalResource* resource;
|
||||
mMap.Get(clone, &resource);
|
||||
@ -712,14 +708,11 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
|
||||
nsRefPtr<PendingLoad> load;
|
||||
mPendingLoads.Get(clone, getter_AddRefs(load));
|
||||
if (load) {
|
||||
NS_ADDREF(*aPendingLoad = load);
|
||||
load.forget(aPendingLoad);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
load = new PendingLoad(aDisplayDocument);
|
||||
if (!load) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!mPendingLoads.Put(clone, load)) {
|
||||
return nsnull;
|
||||
@ -730,7 +723,7 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
|
||||
// chances are it failed for good reasons (security check, etc).
|
||||
AddExternalResource(clone, nsnull, nsnull, aDisplayDocument);
|
||||
} else {
|
||||
NS_ADDREF(*aPendingLoad = load);
|
||||
load.forget(aPendingLoad);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
|
@ -147,12 +147,15 @@ public:
|
||||
NS_DECL_NSISERIALIZABLE
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
// Override Clone() and Equals()
|
||||
NS_IMETHOD Clone(nsIURI** aClone);
|
||||
NS_IMETHOD Equals(nsIURI* aOther, PRBool *aResult);
|
||||
// Override CloneInternal() and EqualsInternal()
|
||||
virtual nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
nsIURI** aClone);
|
||||
virtual nsresult EqualsInternal(nsIURI* aOther,
|
||||
RefHandlingEnum aRefHandlingMode,
|
||||
PRBool* aResult);
|
||||
|
||||
// Override StartClone to hand back a nsFileDataURI
|
||||
virtual nsSimpleURI* StartClone()
|
||||
virtual nsSimpleURI* StartClone(RefHandlingEnum /* unused */)
|
||||
{ return new nsFileDataURI(); }
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
@ -213,12 +216,13 @@ nsFileDataURI::Write(nsIObjectOutputStream* aStream)
|
||||
}
|
||||
|
||||
// nsIURI methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileDataURI::Clone(nsIURI** aClone)
|
||||
nsresult
|
||||
nsFileDataURI::CloneInternal(nsSimpleURI::RefHandlingEnum aRefHandlingMode,
|
||||
nsIURI** aClone)
|
||||
{
|
||||
nsCOMPtr<nsIURI> simpleClone;
|
||||
nsresult rv = nsSimpleURI::Clone(getter_AddRefs(simpleClone));
|
||||
nsresult rv =
|
||||
nsSimpleURI::CloneInternal(aRefHandlingMode, getter_AddRefs(simpleClone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -236,8 +240,10 @@ nsFileDataURI::Clone(nsIURI** aClone)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileDataURI::Equals(nsIURI* aOther, PRBool *aResult)
|
||||
/* virtual */ nsresult
|
||||
nsFileDataURI::EqualsInternal(nsIURI* aOther,
|
||||
nsSimpleURI::RefHandlingEnum aRefHandlingMode,
|
||||
PRBool* aResult)
|
||||
{
|
||||
if (!aOther) {
|
||||
*aResult = PR_FALSE;
|
||||
@ -258,7 +264,8 @@ nsFileDataURI::Equals(nsIURI* aOther, PRBool *aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsSimpleURI::Equals(otherFileDataUri, aResult);
|
||||
return nsSimpleURI::EqualsInternal(otherFileDataUri, aRefHandlingMode,
|
||||
aResult);
|
||||
}
|
||||
|
||||
// nsIClassInfo methods:
|
||||
|
@ -1580,18 +1580,6 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
|
||||
}
|
||||
|
||||
// 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;
|
||||
treeItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
||||
while (parentAsItem) {
|
||||
@ -1602,17 +1590,9 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
|
||||
nsCOMPtr<nsIURI> parentURI;
|
||||
parentAsNav->GetCurrentURI(getter_AddRefs(parentURI));
|
||||
if (parentURI) {
|
||||
nsCOMPtr<nsIURI> parentClone;
|
||||
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);
|
||||
}
|
||||
|
||||
// Bug 98158/193011: We need to ignore data after the #
|
||||
PRBool equal;
|
||||
rv = cloneURI->Equals(parentClone, &equal);
|
||||
rv = aURI->EqualsExceptRef(parentURI, &equal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (equal) {
|
||||
|
@ -2161,6 +2161,7 @@ nsNodeSelectorTearoff::QuerySelectorAll(const nsAString& aSelector,
|
||||
//----------------------------------------------------------------------
|
||||
nsGenericElement::nsDOMSlots::nsDOMSlots()
|
||||
: nsINode::nsSlots(),
|
||||
mDataset(nsnull),
|
||||
mBindingParent(nsnull)
|
||||
{
|
||||
}
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "nsIDOMNodeSelector.h"
|
||||
#include "nsIDOMXPathNSResolver.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIDOMDOMStringMap.h"
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
#include "nsISMILAttr.h"
|
||||
@ -934,9 +935,16 @@ public:
|
||||
/**
|
||||
* The .style attribute (an interface that forwards to the actual
|
||||
* style rules)
|
||||
* @see nsGenericHTMLElement::GetStyle */
|
||||
* @see nsGenericHTMLElement::GetStyle
|
||||
*/
|
||||
nsCOMPtr<nsICSSDeclaration> mStyle;
|
||||
|
||||
/**
|
||||
* The .dataset attribute.
|
||||
* @see nsGenericHTMLElement::GetDataset
|
||||
*/
|
||||
nsIDOMDOMStringMap* mDataset; // [Weak]
|
||||
|
||||
/**
|
||||
* SMIL Overridde style rules (for SMIL animation of CSS properties)
|
||||
* @see nsIContent::GetSMILOverrideStyle
|
||||
|
@ -380,6 +380,7 @@ GK_ATOM(flip, "flip")
|
||||
GK_ATOM(floating, "floating")
|
||||
GK_ATOM(floatList, "Float-list")
|
||||
GK_ATOM(floor, "floor")
|
||||
GK_ATOM(flowlength, "flowlength")
|
||||
GK_ATOM(focus, "focus")
|
||||
GK_ATOM(following, "following")
|
||||
GK_ATOM(followingSibling, "following-sibling")
|
||||
|
@ -423,11 +423,12 @@ IsSupportedImage(const nsCString& aMimeType)
|
||||
static PRBool
|
||||
IsSupportedPlugin(const nsCString& aMIMEType)
|
||||
{
|
||||
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
||||
if (!host) {
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (!pluginHost) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
nsresult rv = host->IsPluginEnabledForType(aMIMEType.get());
|
||||
nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get());
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
@ -458,13 +459,18 @@ IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
|
||||
nsCAutoString ext;
|
||||
GetExtensionFromURI(uri, ext);
|
||||
|
||||
if (ext.IsEmpty())
|
||||
if (ext.IsEmpty()) {
|
||||
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;
|
||||
if (host &&
|
||||
NS_SUCCEEDED(host->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
|
||||
if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
|
||||
mimeType = typeFromExt;
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -1722,8 +1728,8 @@ nsresult
|
||||
nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
|
||||
nsACString& aType)
|
||||
{
|
||||
// Need a plugin host for any class id support
|
||||
nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (!pluginHost) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
@ -1962,11 +1968,13 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
|
||||
/* static */ PluginSupportState
|
||||
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
|
||||
{
|
||||
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
||||
if (!host) {
|
||||
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
||||
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
||||
if (!pluginHost) {
|
||||
return ePluginUnsupported;
|
||||
}
|
||||
nsresult rv = host->IsPluginEnabledForType(aContentType.get());
|
||||
|
||||
nsresult rv = pluginHost->IsPluginEnabledForType(aContentType.get());
|
||||
if (rv == NS_ERROR_PLUGIN_DISABLED)
|
||||
return ePluginDisabled;
|
||||
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
|
||||
@ -2008,18 +2016,6 @@ nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame)
|
||||
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
|
||||
nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
|
||||
const nsAString& pluginDumpID,
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsIDOMNode.h"
|
||||
@ -48,50 +47,23 @@
|
||||
#include "nsIDOMElement.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
|
||||
nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
||||
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();
|
||||
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
|
||||
if (!url)
|
||||
return;
|
||||
|
||||
nsCAutoString refPart;
|
||||
url->GetRef(refPart);
|
||||
aURI->GetRef(refPart);
|
||||
// Unescape %-escapes in the reference. The result will be in the
|
||||
// origin charset of the URL, hopefully...
|
||||
NS_UnescapeURL(refPart);
|
||||
|
||||
nsCAutoString charset;
|
||||
url->GetOriginCharset(charset);
|
||||
aURI->GetOriginCharset(charset);
|
||||
nsAutoString ref;
|
||||
nsresult rv = nsContentUtils::ConvertStringFromCharset(charset, refPart, ref);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -109,9 +81,10 @@ nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
|
||||
if (bindingParent) {
|
||||
nsXBLBinding* binding = doc->BindingManager()->GetBinding(bindingParent);
|
||||
if (binding) {
|
||||
nsCOMPtr<nsIURL> bindingDocumentURL =
|
||||
do_QueryInterface(binding->PrototypeBinding()->DocURI());
|
||||
if (EqualExceptRef(url, bindingDocumentURL)) {
|
||||
PRBool isEqualExceptRef;
|
||||
rv = aURI->EqualsExceptRef(binding->PrototypeBinding()->DocURI(),
|
||||
&isEqualExceptRef);
|
||||
if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
|
||||
// XXX sXBL/XBL2 issue
|
||||
// Our content is an anonymous XBL element from a binding inside the
|
||||
// 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());
|
||||
// We've already checked that |url| is an nsIURL. So if the document URI is
|
||||
// not an nsIURL then |url| is certainly not going to be pointing to the same
|
||||
// document as the document URI.
|
||||
if (!documentURL || !EqualExceptRef(url, documentURL)) {
|
||||
PRBool isEqualExceptRef;
|
||||
rv = aURI->EqualsExceptRef(doc->GetDocumentURI(), &isEqualExceptRef);
|
||||
if (NS_FAILED(rv) || !isEqualExceptRef) {
|
||||
nsRefPtr<nsIDocument::ExternalResourceLoad> load;
|
||||
doc = doc->RequestExternalResource(url, aFromContent, getter_AddRefs(load));
|
||||
doc = doc->RequestExternalResource(aURI, aFromContent,
|
||||
getter_AddRefs(load));
|
||||
if (!doc) {
|
||||
if (!load || !aWatch) {
|
||||
// Nothing will ever happen here
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,6 @@
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsDOMEventTargetWrapperCache.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIProxiedProtocolHandler.h"
|
||||
|
||||
#define DEFAULT_WS_SCHEME_PORT 80
|
||||
#define DEFAULT_WSS_SCHEME_PORT 443
|
||||
@ -101,8 +100,6 @@ public:
|
||||
PRBool aWantsUntrusted,
|
||||
PRUint8 optional_argc);
|
||||
|
||||
static void ReleaseGlobals();
|
||||
|
||||
// Determine if preferences allow WebSocket
|
||||
static PRBool PrefEnabled();
|
||||
|
||||
@ -116,7 +113,7 @@ protected:
|
||||
nsresult EstablishConnection();
|
||||
|
||||
nsresult CreateAndDispatchSimpleEvent(const nsString& aName);
|
||||
nsresult CreateAndDispatchMessageEvent(nsCString *aData);
|
||||
nsresult CreateAndDispatchMessageEvent(const nsACString& aData);
|
||||
nsresult CreateAndDispatchCloseEvent(PRBool aWasClean);
|
||||
|
||||
// called from mConnection accordingly to the situation
|
||||
@ -147,7 +144,8 @@ protected:
|
||||
nsCString mAsciiHost; // hostname
|
||||
PRUint32 mPort;
|
||||
nsCString mResource; // [filepath[?query]]
|
||||
nsCString mOrigin;
|
||||
nsString mUTF16Origin;
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCString mProtocol;
|
||||
|
||||
@ -175,44 +173,4 @@ private:
|
||||
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
|
||||
|
@ -481,6 +481,8 @@ _TEST_FILES2 = \
|
||||
bug638112-response.txt \
|
||||
bug638112.sjs \
|
||||
test_bug656283.html \
|
||||
test_blobbuilder.html \
|
||||
fileutils.js \
|
||||
$(NULL)
|
||||
|
||||
# This test fails on the Mac for some reason
|
||||
|
@ -6,6 +6,9 @@ import sys
|
||||
# see the list of tests in test_websocket.html
|
||||
|
||||
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":
|
||||
time.sleep(5)
|
||||
pass
|
||||
@ -42,6 +45,7 @@ def web_socket_transfer_data(request):
|
||||
if msgutil.receive_message(request) == "5":
|
||||
resp = "あいうえお"
|
||||
msgutil.send_message(request, resp.decode('utf-8'))
|
||||
msgutil.close_connection(request)
|
||||
elif request.ws_protocol == "test 7":
|
||||
try:
|
||||
while not request.client_terminated:
|
||||
@ -62,6 +66,9 @@ def web_socket_transfer_data(request):
|
||||
if msgutil.receive_message(request) == "client data":
|
||||
resp = "server data"
|
||||
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":
|
||||
# first one binary message containing the byte 0x61 ('a')
|
||||
request.connection.write('\xff\x01\x61')
|
||||
@ -69,7 +76,7 @@ def web_socket_transfer_data(request):
|
||||
request.connection.write('\x01\x61\xff')
|
||||
msgutil.close_connection(request)
|
||||
elif request.ws_protocol == "test 14":
|
||||
request.connection.write('\xff\x00')
|
||||
msgutil.close_connection(request)
|
||||
msgutil.send_message(request, "server data")
|
||||
elif request.ws_protocol == "test 15":
|
||||
msgutil.close_connection(request, True)
|
||||
|
@ -1,6 +1,9 @@
|
||||
from mod_pywebsocket import msgutil
|
||||
|
||||
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'):
|
||||
raise ValueError('Error')
|
||||
pass
|
||||
|
272
content/base/test/fileutils.js
Normal file
272
content/base/test/fileutils.js
Normal 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");
|
||||
}
|
||||
|
@ -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/" +
|
||||
"file_CrossSiteXHR_cache_server.sjs?";
|
||||
setStateURL = baseURL + "setState=";
|
||||
|
135
content/base/test/test_blobbuilder.html
Normal file
135
content/base/test/test_blobbuilder.html
Normal 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>
|
@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=575946
|
||||
<title>Test for Bug 575946</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.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>
|
||||
|
||||
@ -23,8 +24,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=575946
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var fileNum = 1;
|
||||
var testRanCounter = 0;
|
||||
var expectedTestCount = 0;
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// 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
|
||||
function testFile(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");
|
||||
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");
|
||||
testSlice(memFile, size, "image/png", fileData, "memFile");
|
||||
testSlice(fileFile, size, "", fileData, "fileFile");
|
||||
|
||||
|
||||
// Try loading directly from slice into an image
|
||||
@ -209,192 +133,6 @@ img.src = URL.createObjectURL(imgfile.mozSlice(testBinaryData.length, testBinary
|
||||
img.onload = imageLoadHandler;
|
||||
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>
|
||||
</pre>
|
||||
</body> </html>
|
||||
|
@ -51,7 +51,6 @@ var last_test = 22;
|
||||
var current_test = first_test;
|
||||
|
||||
var timeoutToAbortTest = 60000;
|
||||
var timeoutToOpenWS = 25000;
|
||||
var all_ws = [];
|
||||
|
||||
function shouldNotOpen(e)
|
||||
@ -264,7 +263,7 @@ function test6()
|
||||
ws.onmessage = function(e)
|
||||
{
|
||||
if (counter == 5) {
|
||||
ok(e.data == "あいうえお");
|
||||
ok(e.data == "あいうえお", "test 6 counter 5 data ok");
|
||||
ws.close();
|
||||
doTest(7);
|
||||
} else {
|
||||
@ -278,16 +277,25 @@ function test6()
|
||||
|
||||
function test7()
|
||||
{
|
||||
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);
|
||||
};
|
||||
// with pywebsockets for -06 ths test no longer does anything useful
|
||||
// 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
|
||||
// what we're trying to do here.
|
||||
|
||||
ok(true, "test disabled");
|
||||
current_test++;
|
||||
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()
|
||||
@ -338,21 +346,24 @@ function test10()
|
||||
function test11()
|
||||
{
|
||||
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()
|
||||
{
|
||||
ok(ws.readyState == 1, "bad readyState in test 11!");
|
||||
ok(ws.readyState == 1, "open bad readyState in test 11!");
|
||||
ws.send("client data");
|
||||
}
|
||||
ws.onmessage = function(e)
|
||||
{
|
||||
ok(e.data == "server data", "bad received message in test 11!");
|
||||
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)
|
||||
{
|
||||
ok(ws.readyState == 3, "bad readyState in test 11!");
|
||||
ok(ws.readyState == 3, "onclose bad readyState in test 11!");
|
||||
shouldCloseCleanly(e);
|
||||
doTest(12);
|
||||
}
|
||||
@ -372,23 +383,34 @@ function test12()
|
||||
ok(true, "couldn't send an unpaired surrogate!");
|
||||
}
|
||||
ws.close();
|
||||
|
||||
// there isnt really a server implementation of test 12, so just
|
||||
// ignore an error
|
||||
ws.onerror = function()
|
||||
{
|
||||
}
|
||||
|
||||
doTest(13);
|
||||
};
|
||||
}
|
||||
|
||||
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");
|
||||
ws._timesCalledOnError = 0;
|
||||
ws.onerror = function()
|
||||
{
|
||||
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()
|
||||
@ -413,6 +435,12 @@ function test15()
|
||||
shouldCloseNotCleanly(e);
|
||||
doTest(16);
|
||||
};
|
||||
|
||||
// termination of the connection might cause an error event if it happens in OPEN
|
||||
ws.onerror = function()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function test16()
|
||||
@ -428,7 +456,13 @@ function test16()
|
||||
{
|
||||
ok(false, "shouldn't send message after calling close()");
|
||||
}
|
||||
ws.onclose = shouldCloseCleanly;
|
||||
|
||||
ws.onerror = function()
|
||||
{
|
||||
}
|
||||
ws.onclose = function()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
var status_test17 = "not started";
|
||||
@ -593,9 +627,6 @@ function test22()
|
||||
};
|
||||
}
|
||||
|
||||
var domBranch;
|
||||
var oldPrefVal;
|
||||
|
||||
function finishWSTest()
|
||||
{
|
||||
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 + "!");
|
||||
}
|
||||
}
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
domBranch.setBoolPref("override-security-block", oldPrefVal);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -17,24 +17,8 @@
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var ws;
|
||||
var oldPrefVal;
|
||||
var domBranch;
|
||||
|
||||
function finishWSTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
domBranch.setBoolPref("override-security-block", oldPrefVal);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
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.onopen = function(e) {
|
||||
ws.send("data");
|
||||
@ -43,12 +27,12 @@ function testWebSocket () {
|
||||
}
|
||||
ws.onerror = function(e) {
|
||||
ok(false, "onerror called!");
|
||||
finishWSTest();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
ws.onmessage = function(e) {
|
||||
is(e.data, "Hello world!", "Wrong data");
|
||||
ws.close();
|
||||
finishWSTest();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,6 @@
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var ws;
|
||||
var oldPrefVal;
|
||||
var domBranch;
|
||||
|
||||
var params = ["protocol", "resource", "origin", "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() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
domBranch.setBoolPref("override-security-block", oldPrefVal);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
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";
|
||||
ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_ws_basic_tests", "test");
|
||||
is(ws.url, url, "Wrong Websocket.url!");
|
||||
|
@ -127,6 +127,29 @@ WebGLContext::WebGLContext()
|
||||
mFakeVertexAttrib0BufferObjectSize = 0;
|
||||
mFakeVertexAttrib0BufferObject = 0;
|
||||
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()
|
||||
@ -312,31 +335,24 @@ WebGLContext::SetContextOptions(nsIPropertyBag *aOptions)
|
||||
|
||||
WebGLContextOptions newOpts;
|
||||
|
||||
// defaults are: yes: depth, alpha, premultipliedAlpha; no: stencil
|
||||
if (!GetBoolFromPropertyBag(aOptions, "stencil", &newOpts.stencil))
|
||||
newOpts.stencil = false;
|
||||
|
||||
if (!GetBoolFromPropertyBag(aOptions, "depth", &newOpts.depth))
|
||||
newOpts.depth = true;
|
||||
|
||||
if (!GetBoolFromPropertyBag(aOptions, "alpha", &newOpts.alpha))
|
||||
newOpts.alpha = true;
|
||||
|
||||
if (!GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha))
|
||||
newOpts.premultipliedAlpha = true;
|
||||
|
||||
GetBoolFromPropertyBag(aOptions, "antialiasHint", &newOpts.antialiasHint);
|
||||
GetBoolFromPropertyBag(aOptions, "stencil", &newOpts.stencil);
|
||||
GetBoolFromPropertyBag(aOptions, "depth", &newOpts.depth);
|
||||
GetBoolFromPropertyBag(aOptions, "alpha", &newOpts.alpha);
|
||||
GetBoolFromPropertyBag(aOptions, "premultipliedAlpha", &newOpts.premultipliedAlpha);
|
||||
GetBoolFromPropertyBag(aOptions, "antialias", &newOpts.antialias);
|
||||
GetBoolFromPropertyBag(aOptions, "preserveDrawingBuffer", &newOpts.preserveDrawingBuffer);
|
||||
|
||||
// enforce that if stencil is specified, we also give back depth
|
||||
newOpts.depth |= newOpts.stencil;
|
||||
|
||||
#if 0
|
||||
LogMessage("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d\n",
|
||||
newOpts.antialiasHint ? 1 : 0,
|
||||
LogMessage("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d preserve: %d\n",
|
||||
newOpts.antialias ? 1 : 0,
|
||||
newOpts.stencil ? 1 : 0,
|
||||
newOpts.depth ? 1 : 0,
|
||||
newOpts.alpha ? 1 : 0,
|
||||
newOpts.premultipliedAlpha ? 1 : 0);
|
||||
newOpts.premultipliedAlpha ? 1 : 0,
|
||||
newOpts.preserveDrawingBuffer ? 1 : 0);
|
||||
#endif
|
||||
|
||||
if (mOptionsFrozen && newOpts != mOptions) {
|
||||
@ -703,6 +719,8 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
mResetLayer = PR_FALSE;
|
||||
|
||||
mBackbufferClearingStatus = BackbufferClearingStatus::NotClearedSinceLastPresented;
|
||||
|
||||
return canvasLayer.forget().get();
|
||||
}
|
||||
|
||||
@ -731,6 +749,9 @@ WebGLContext::GetContextAttributes(jsval *aResult)
|
||||
NULL, NULL, JSPROP_ENUMERATE) ||
|
||||
!JS_DefineProperty(cx, obj, "premultipliedAlpha",
|
||||
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))
|
||||
{
|
||||
*aResult = JSVAL_VOID;
|
||||
@ -766,6 +787,122 @@ WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval)
|
||||
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
|
||||
@ -901,6 +1038,18 @@ NAME_NOT_SUPPORTED(WebGLShader)
|
||||
NAME_NOT_SUPPORTED(WebGLFramebuffer)
|
||||
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; */
|
||||
NS_IMETHODIMP
|
||||
WebGLUniformLocation::GetLocation(WebGLint *aLocation)
|
||||
@ -969,9 +1118,3 @@ WebGLContext::IsContextLost(WebGLboolean *retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::GetExtension(const nsAString& aName, nsISupports **retval)
|
||||
{
|
||||
*retval = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -84,8 +84,13 @@ struct VertexAttrib0Status {
|
||||
enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
|
||||
};
|
||||
|
||||
struct BackbufferClearingStatus {
|
||||
enum { NotClearedSinceLastPresented, ClearedToDefaultValues, HasBeenDrawnTo };
|
||||
};
|
||||
|
||||
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 {
|
||||
@ -284,7 +289,8 @@ struct WebGLContextOptions {
|
||||
// these are defaults
|
||||
WebGLContextOptions()
|
||||
: alpha(true), depth(true), stencil(false),
|
||||
premultipliedAlpha(true), antialiasHint(false)
|
||||
premultipliedAlpha(true), antialias(false),
|
||||
preserveDrawingBuffer(false)
|
||||
{ }
|
||||
|
||||
bool operator==(const WebGLContextOptions& other) const {
|
||||
@ -293,24 +299,20 @@ struct WebGLContextOptions {
|
||||
depth == other.depth &&
|
||||
stencil == other.stencil &&
|
||||
premultipliedAlpha == other.premultipliedAlpha &&
|
||||
antialiasHint == other.antialiasHint;
|
||||
antialias == other.antialias &&
|
||||
preserveDrawingBuffer == other.preserveDrawingBuffer;
|
||||
}
|
||||
|
||||
bool operator!=(const WebGLContextOptions& other) const {
|
||||
return
|
||||
alpha != other.alpha ||
|
||||
depth != other.depth ||
|
||||
stencil != other.stencil ||
|
||||
premultipliedAlpha != other.premultipliedAlpha ||
|
||||
antialiasHint != other.antialiasHint;
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
bool alpha;
|
||||
bool depth;
|
||||
bool stencil;
|
||||
|
||||
bool premultipliedAlpha;
|
||||
bool antialiasHint;
|
||||
bool antialias;
|
||||
bool preserveDrawingBuffer;
|
||||
};
|
||||
|
||||
class WebGLContext :
|
||||
@ -377,6 +379,16 @@ public:
|
||||
// all context resources to be lost.
|
||||
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:
|
||||
void SetDontKnowIfNeedFakeBlack() {
|
||||
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
|
||||
@ -425,6 +437,17 @@ protected:
|
||||
PRInt32 mGLMaxFragmentUniformVectors;
|
||||
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 InitAndValidateGL();
|
||||
PRBool ValidateBuffers(PRInt32* maxAllowedCount, const char *info);
|
||||
@ -438,10 +461,11 @@ protected:
|
||||
PRBool ValidateStencilOpEnum(WebGLenum action, const char *info);
|
||||
PRBool ValidateFaceEnum(WebGLenum face, 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);
|
||||
PRBool ValidateDrawModeEnum(WebGLenum mode, const char *info);
|
||||
PRBool ValidateAttribIndex(WebGLuint index, const char *info);
|
||||
PRBool ValidateStencilParamsForDrawCall();
|
||||
|
||||
void Invalidate();
|
||||
void DestroyResourcesAndContext();
|
||||
@ -453,12 +477,14 @@ protected:
|
||||
WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero, WebGLint border,
|
||||
WebGLenum format, WebGLenum type,
|
||||
void *data, PRUint32 byteLength,
|
||||
int jsArrayType,
|
||||
int srcFormat, PRBool srcPremultiplied);
|
||||
nsresult TexSubImage2D_base(WebGLenum target, WebGLint level,
|
||||
WebGLint xoffset, WebGLint yoffset,
|
||||
WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
|
||||
WebGLenum format, WebGLenum type,
|
||||
void *pixels, PRUint32 byteLength,
|
||||
int jsArrayType,
|
||||
int srcFormat, PRBool srcPremultiplied);
|
||||
nsresult ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height,
|
||||
WebGLenum format, WebGLenum type, void *data, PRUint32 byteLength);
|
||||
@ -566,8 +592,18 @@ protected:
|
||||
GLuint mFakeVertexAttrib0BufferObject;
|
||||
int mFakeVertexAttrib0BufferStatus;
|
||||
|
||||
WebGLint mStencilRef;
|
||||
WebGLuint mStencilValueMask, mStencilWriteMask;
|
||||
WebGLint mStencilRefFront, mStencilRefBack;
|
||||
WebGLuint mStencilValueMaskFront, mStencilValueMaskBack,
|
||||
mStencilWriteMaskFront, mStencilWriteMaskBack;
|
||||
realGLboolean mColorWriteMask[4];
|
||||
realGLboolean mDepthWriteMask;
|
||||
realGLboolean mScissorTestEnabled;
|
||||
realGLboolean mDitherEnabled;
|
||||
WebGLfloat mColorClearValue[4];
|
||||
WebGLint mStencilClearValue;
|
||||
WebGLfloat mDepthClearValue;
|
||||
|
||||
int mBackbufferClearingStatus;
|
||||
|
||||
public:
|
||||
// console logging helpers
|
||||
@ -878,7 +914,7 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
ImageInfo& ImageInfoAt(size_t level, size_t face) {
|
||||
ImageInfo& ImageInfoAt(size_t level, size_t face = 0) {
|
||||
#ifdef DEBUG
|
||||
if (face >= mFacesCount)
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
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, "
|
||||
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
} else if (!ImageInfoAt(0, 0).IsPowerOfTwo()) {
|
||||
} else if (!ImageInfoAt(0).IsPowerOfTwo()) {
|
||||
mContext->LogMessageIfVerbose
|
||||
("%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);
|
||||
@ -1152,12 +1194,12 @@ public:
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!ImageInfoAt(0, 0).IsPositive()) {
|
||||
if (!ImageInfoAt(0).IsPositive()) {
|
||||
mContext->LogMessageIfVerbose
|
||||
("%s is a 2D texture and its width or height is equal to zero.",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(0, 0).IsPowerOfTwo()) {
|
||||
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(0).IsPowerOfTwo()) {
|
||||
mContext->LogMessageIfVerbose
|
||||
("%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 "
|
||||
@ -1766,97 +1808,37 @@ protected:
|
||||
if (mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return;
|
||||
|
||||
PRBool initializeColorBuffer = mColorAttachment.HasUninitializedRenderbuffer();
|
||||
PRBool initializeDepthBuffer = mDepthAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer();
|
||||
PRBool initializeStencilBuffer = mStencilAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer();
|
||||
PRUint32 mask = 0;
|
||||
|
||||
realGLboolean savedColorMask[4] = {0};
|
||||
realGLboolean savedDepthMask = 0;
|
||||
GLuint savedStencilMask = 0;
|
||||
GLfloat savedColorClearValue[4] = {0.f};
|
||||
GLfloat savedDepthClearValue = 0.f;
|
||||
GLint savedStencilClearValue = 0;
|
||||
GLuint clearBits = 0;
|
||||
if (mColorAttachment.HasUninitializedRenderbuffer())
|
||||
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
|
||||
realGLboolean wasScissorTestEnabled = mContext->gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST);
|
||||
mContext->gl->fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
|
||||
realGLboolean wasDitherEnabled = mContext->gl->fIsEnabled(LOCAL_GL_DITHER);
|
||||
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 (mDepthAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
{
|
||||
mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (initializeDepthBuffer) {
|
||||
mContext->gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &savedDepthMask);
|
||||
mContext->gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &savedDepthClearValue);
|
||||
mContext->gl->fDepthMask(1);
|
||||
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;
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
{
|
||||
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
// the one useful line of code
|
||||
mContext->gl->fClear(clearBits);
|
||||
mContext->ForceClearFramebufferWithDefaultValues(mask, nsIntRect(0,0,width(),height()));
|
||||
|
||||
if (initializeColorBuffer) {
|
||||
mContext->gl->fColorMask(savedColorMask[0],
|
||||
savedColorMask[1],
|
||||
savedColorMask[2],
|
||||
savedColorMask[3]);
|
||||
mContext->gl->fClearColor(savedColorClearValue[0],
|
||||
savedColorClearValue[1],
|
||||
savedColorClearValue[2],
|
||||
savedColorClearValue[3]);
|
||||
if (mColorAttachment.HasUninitializedRenderbuffer())
|
||||
mColorAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
if (initializeDepthBuffer) {
|
||||
mContext->gl->fDepthMask(savedDepthMask);
|
||||
mContext->gl->fClearDepth(savedDepthClearValue);
|
||||
if (mDepthAttachment.Renderbuffer())
|
||||
mDepthAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
if (mDepthAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
|
||||
if (initializeStencilBuffer) {
|
||||
mContext->gl->fStencilMask(savedStencilMask);
|
||||
mContext->gl->fClearStencil(savedStencilClearValue);
|
||||
if (mStencilAttachment.Renderbuffer())
|
||||
mStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
|
||||
if (initializeDepthBuffer && initializeStencilBuffer) {
|
||||
if (mDepthStencilAttachment.Renderbuffer())
|
||||
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);
|
||||
if (mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
WebGLuint mName;
|
||||
@ -1939,6 +1921,26 @@ protected:
|
||||
|
||||
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
|
||||
**/
|
||||
|
@ -65,6 +65,7 @@
|
||||
using namespace mozilla;
|
||||
|
||||
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
|
||||
* we can avoid having to type this 500 times. Note that these MUST
|
||||
@ -586,27 +587,81 @@ WebGLContext::Clear(PRUint32 mask)
|
||||
{
|
||||
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);
|
||||
if (mask != m) {
|
||||
if (mask != m)
|
||||
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);
|
||||
Invalidate();
|
||||
if (needClearCallHere) {
|
||||
gl->fClear(mask);
|
||||
mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
|
||||
@ -1080,7 +1135,14 @@ WebGLContext::DepthFunc(WebGLenum func)
|
||||
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
|
||||
WebGLContext::DepthRange(WebGLfloat zNear, WebGLfloat zFar)
|
||||
@ -1301,6 +1363,9 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
||||
if (first < 0 || count < 0)
|
||||
return ErrorInvalidValue("DrawArrays: negative first or count");
|
||||
|
||||
if (!ValidateStencilParamsForDrawCall())
|
||||
return NS_OK;
|
||||
|
||||
// If count is 0, there's nothing to do.
|
||||
if (count == 0)
|
||||
return NS_OK;
|
||||
@ -1324,8 +1389,12 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
} else {
|
||||
EnsureBackbufferClearedAsNeeded();
|
||||
}
|
||||
|
||||
BindFakeBlackTextures();
|
||||
DoFakeVertexAttrib0(checked_firstPlusCount.value());
|
||||
@ -1335,6 +1404,7 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
||||
UndoFakeVertexAttrib0();
|
||||
UnbindFakeBlackTextures();
|
||||
|
||||
mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
|
||||
Invalidate();
|
||||
|
||||
return NS_OK;
|
||||
@ -1349,6 +1419,9 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
||||
if (count < 0 || byteOffset < 0)
|
||||
return ErrorInvalidValue("DrawElements: negative count or offset");
|
||||
|
||||
if (!ValidateStencilParamsForDrawCall())
|
||||
return NS_OK;
|
||||
|
||||
// If count is 0, there's nothing to do.
|
||||
if (count == 0)
|
||||
return NS_OK;
|
||||
@ -1422,8 +1495,12 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
} else {
|
||||
EnsureBackbufferClearedAsNeeded();
|
||||
}
|
||||
|
||||
BindFakeBlackTextures();
|
||||
DoFakeVertexAttrib0(checked_maxIndexPlusOne.value());
|
||||
@ -1433,6 +1510,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
||||
UndoFakeVertexAttrib0();
|
||||
UnbindFakeBlackTextures();
|
||||
|
||||
mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
|
||||
Invalidate();
|
||||
|
||||
return NS_OK;
|
||||
@ -1443,6 +1521,15 @@ NS_IMETHODIMP WebGLContext::Enable(WebGLenum cap)
|
||||
if (!ValidateCapabilityEnum(cap, "enable"))
|
||||
return NS_OK;
|
||||
|
||||
switch(cap) {
|
||||
case LOCAL_GL_SCISSOR_TEST:
|
||||
mScissorTestEnabled = 1;
|
||||
break;
|
||||
case LOCAL_GL_DITHER:
|
||||
mDitherEnabled = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fEnable(cap);
|
||||
return NS_OK;
|
||||
@ -1453,6 +1540,15 @@ NS_IMETHODIMP WebGLContext::Disable(WebGLenum cap)
|
||||
if (!ValidateCapabilityEnum(cap, "disable"))
|
||||
return NS_OK;
|
||||
|
||||
switch(cap) {
|
||||
case LOCAL_GL_SCISSOR_TEST:
|
||||
mScissorTestEnabled = 0;
|
||||
break;
|
||||
case LOCAL_GL_DITHER:
|
||||
mDitherEnabled = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fDisable(cap);
|
||||
return NS_OK;
|
||||
@ -2857,9 +2953,14 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
// prevent readback of arbitrary video memory through uninitialized renderbuffers!
|
||||
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
if (mBoundFramebuffer) {
|
||||
// prevent readback of arbitrary video memory through uninitialized renderbuffers!
|
||||
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
} else {
|
||||
EnsureBackbufferClearedAsNeeded();
|
||||
}
|
||||
|
||||
|
||||
if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, boundWidth, boundHeight)) {
|
||||
// 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"))
|
||||
return NS_OK;
|
||||
|
||||
mStencilRef = ref;
|
||||
mStencilValueMask = mask;
|
||||
mStencilRefFront = ref;
|
||||
mStencilRefBack = ref;
|
||||
mStencilValueMaskFront = mask;
|
||||
mStencilValueMaskBack = mask;
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fStencilFunc(func, ref, mask);
|
||||
@ -3086,12 +3189,22 @@ WebGLContext::StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref,
|
||||
!ValidateComparisonEnum(func, "stencilFuncSeparate: func"))
|
||||
return NS_OK;
|
||||
|
||||
if (face != LOCAL_GL_FRONT_AND_BACK && (ref != mStencilRef || mask != mStencilValueMask))
|
||||
return ErrorInvalidOperation("stencilFuncSeparate: WebGL doesn't currently allow specifying "
|
||||
"different values for front and back.");
|
||||
|
||||
mStencilRef = ref;
|
||||
mStencilValueMask = mask;
|
||||
switch (face) {
|
||||
case LOCAL_GL_FRONT_AND_BACK:
|
||||
mStencilRefFront = ref;
|
||||
mStencilRefBack = ref;
|
||||
mStencilValueMaskFront = mask;
|
||||
mStencilValueMaskBack = mask;
|
||||
break;
|
||||
case LOCAL_GL_FRONT:
|
||||
mStencilRefFront = ref;
|
||||
mStencilValueMaskFront = mask;
|
||||
break;
|
||||
case LOCAL_GL_BACK:
|
||||
mStencilRefBack = ref;
|
||||
mStencilValueMaskBack = mask;
|
||||
break;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fStencilFuncSeparate(face, func, ref, mask);
|
||||
@ -3101,7 +3214,8 @@ WebGLContext::StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref,
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::StencilMask(WebGLuint mask)
|
||||
{
|
||||
mStencilWriteMask = mask;
|
||||
mStencilWriteMaskFront = mask;
|
||||
mStencilWriteMaskBack = mask;
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fStencilMask(mask);
|
||||
@ -3114,10 +3228,18 @@ WebGLContext::StencilMaskSeparate(WebGLenum face, WebGLuint mask)
|
||||
if (!ValidateFaceEnum(face, "stencilMaskSeparate: face"))
|
||||
return NS_OK;
|
||||
|
||||
if (face != LOCAL_GL_FRONT_AND_BACK && mask != mStencilWriteMask)
|
||||
return ErrorInvalidOperation("stencilMaskSeparate: WebGL doesn't currently allow specifying "
|
||||
"different values for front and back.");
|
||||
mStencilWriteMask = mask;
|
||||
switch (face) {
|
||||
case LOCAL_GL_FRONT_AND_BACK:
|
||||
mStencilWriteMaskFront = mask;
|
||||
mStencilWriteMaskBack = mask;
|
||||
break;
|
||||
case LOCAL_GL_FRONT:
|
||||
mStencilWriteMaskFront = mask;
|
||||
break;
|
||||
case LOCAL_GL_BACK:
|
||||
mStencilWriteMaskBack = mask;
|
||||
break;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fStencilMaskSeparate(face, mask);
|
||||
@ -3163,18 +3285,21 @@ struct WebGLImageConverter
|
||||
memset(this, 0, sizeof(WebGLImageConverter));
|
||||
}
|
||||
|
||||
template<typename SrcType, typename DstType,
|
||||
void unpackingFunc(const SrcType*, PRUint8*),
|
||||
void packingFunc(const PRUint8*, DstType*)>
|
||||
template<typename SrcType, typename DstType, typename UnpackType,
|
||||
void unpackingFunc(const SrcType*, UnpackType*),
|
||||
void packingFunc(const UnpackType*, DstType*)>
|
||||
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) {
|
||||
size_t dst_row = flip ? (height - 1 - src_row) : src_row;
|
||||
PRUint8 *dst_row_ptr = dst + dst_row * dstStride;
|
||||
const PRUint8 *src_row_ptr = src + src_row * srcStride;
|
||||
const PRUint8 *src_row_end = src_row_ptr + width * srcTexelSize; // != src_row_ptr + byteStride
|
||||
while (src_row_ptr != src_row_end) {
|
||||
PRUint8 tmp[4];
|
||||
UnpackType tmp[4];
|
||||
unpackingFunc(reinterpret_cast<const SrcType*>(src_row_ptr), tmp);
|
||||
packingFunc(tmp, reinterpret_cast<DstType*>(dst_row_ptr));
|
||||
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,
|
||||
// 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
|
||||
const PRUint8* src_row = src;
|
||||
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: \
|
||||
switch (premultiplicationOp) { \
|
||||
case WebGLTexelPremultiplicationOp::Premultiply: \
|
||||
converter.run<SrcType, DstType, \
|
||||
converter.run<SrcType, DstType, PRUint8, \
|
||||
WebGLTexelConversions::unpackFunc, \
|
||||
WebGLTexelConversions::packFunc##Premultiply>(); \
|
||||
break; \
|
||||
case WebGLTexelPremultiplicationOp::Unmultiply: \
|
||||
converter.run<SrcType, DstType, \
|
||||
converter.run<SrcType, DstType, PRUint8, \
|
||||
WebGLTexelConversions::unpackFunc, \
|
||||
WebGLTexelConversions::packFunc##Unmultiply>(); \
|
||||
break; \
|
||||
default: \
|
||||
converter.run<SrcType, DstType, \
|
||||
converter.run<SrcType, DstType, PRUint8, \
|
||||
WebGLTexelConversions::unpackFunc, \
|
||||
WebGLTexelConversions::packFunc>(); \
|
||||
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) \
|
||||
/* A8 needs to be special-cased as it doesn't have color channels to premultiply */ \
|
||||
case WebGLTexelFormat::A8: \
|
||||
converter.run<SrcType, PRUint8, \
|
||||
converter.run<SrcType, PRUint8, PRUint8, \
|
||||
WebGLTexelConversions::unpackFunc, \
|
||||
WebGLTexelConversions::packRGBA8ToA8>(); \
|
||||
break; \
|
||||
@ -3279,6 +3406,39 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t
|
||||
} \
|
||||
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) {
|
||||
HANDLE_SRCFORMAT(RGBA8, 4, PRUint8, unpackRGBA8ToRGBA8)
|
||||
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(RGBA4444, 2, PRUint16, unpackRGBA4444ToRGBA8)
|
||||
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:
|
||||
NS_ASSERTION(PR_FALSE, "Coding error?! Should never reach this point.");
|
||||
return;
|
||||
@ -3358,7 +3522,10 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
||||
return NS_OK; \
|
||||
if (isNull) \
|
||||
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); \
|
||||
if (mCurrentProgram->Generation() != location_object->ProgramGeneration()) \
|
||||
return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \
|
||||
@ -3595,11 +3762,9 @@ WebGLContext::ValidateProgram(nsIWebGLProgram *pobj)
|
||||
MakeContextCurrent();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (gl->Vendor() == gl::GLContext::VendorNVIDIA) {
|
||||
LogMessageIfVerbose("validateProgram: implemented as a no-operation "
|
||||
"on Mac/NVIDIA to work around a driver crash");
|
||||
return NS_OK;
|
||||
}
|
||||
// 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 on Mac to work around crashes");
|
||||
return NS_OK;
|
||||
#endif
|
||||
|
||||
gl->fValidateProgram(progname);
|
||||
@ -3940,6 +4105,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
|
||||
WebGLint border,
|
||||
WebGLenum format, WebGLenum type,
|
||||
void *data, PRUint32 byteLength,
|
||||
int jsArrayType, // a TypedArray format enum, or -1 if not relevant
|
||||
int srcFormat, PRBool srcPremultiplied)
|
||||
{
|
||||
switch (target) {
|
||||
@ -3996,7 +4162,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
|
||||
return ErrorInvalidValue("TexImage2D: border must be 0");
|
||||
|
||||
PRUint32 texelSize = 0;
|
||||
if (!ValidateTexFormatAndType(format, type, &texelSize, "texImage2D"))
|
||||
if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texImage2D"))
|
||||
return NS_OK;
|
||||
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * texelSize;
|
||||
@ -4028,6 +4194,10 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
|
||||
|
||||
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) {
|
||||
int dstFormat = GetWebGLTexelFormat(format, type);
|
||||
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,
|
||||
pixels ? pixels->data : 0,
|
||||
pixels ? pixels->byteLength : 0,
|
||||
-1,
|
||||
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,
|
||||
pixels ? pixels->data : 0,
|
||||
pixels ? pixels->byteLength : 0,
|
||||
(int) pixels->type,
|
||||
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,
|
||||
pixels ? pixels->data : 0,
|
||||
pixels ? pixels->byteLength : 0,
|
||||
-1,
|
||||
WebGLTexelFormat::RGBA8, PR_FALSE);
|
||||
}
|
||||
|
||||
@ -4125,6 +4298,7 @@ WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum interna
|
||||
isurf->Width(), isurf->Height(), isurf->Stride(), 0,
|
||||
format, type,
|
||||
isurf->Data(), byteLength,
|
||||
-1,
|
||||
srcFormat, mPixelStorePremultiplyAlpha);
|
||||
}
|
||||
|
||||
@ -4140,6 +4314,7 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
|
||||
WebGLsizei width, WebGLsizei height, WebGLsizei srcStrideOrZero,
|
||||
WebGLenum format, WebGLenum type,
|
||||
void *pixels, PRUint32 byteLength,
|
||||
int jsArrayType,
|
||||
int srcFormat, PRBool srcPremultiplied)
|
||||
{
|
||||
switch (target) {
|
||||
@ -4176,7 +4351,7 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
|
||||
}
|
||||
|
||||
PRUint32 texelSize = 0;
|
||||
if (!ValidateTexFormatAndType(format, type, &texelSize, "texSubImage2D"))
|
||||
if (!ValidateTexFormatAndType(format, type, jsArrayType, &texelSize, "texSubImage2D"))
|
||||
return NS_OK;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
@ -4254,6 +4429,7 @@ WebGLContext::TexSubImage2D_buf(WebGLenum target, WebGLint level,
|
||||
return TexSubImage2D_base(target, level, xoffset, yoffset,
|
||||
width, height, 0, format, type,
|
||||
pixels->data, pixels->byteLength,
|
||||
-1,
|
||||
WebGLTexelFormat::Auto, PR_FALSE);
|
||||
}
|
||||
|
||||
@ -4270,6 +4446,7 @@ WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level,
|
||||
return TexSubImage2D_base(target, level, xoffset, yoffset,
|
||||
width, height, 0, format, type,
|
||||
pixels->data, pixels->byteLength,
|
||||
pixels->type,
|
||||
WebGLTexelFormat::Auto, PR_FALSE);
|
||||
}
|
||||
|
||||
@ -4286,6 +4463,7 @@ WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level,
|
||||
return TexSubImage2D_base(target, level, xoffset, yoffset,
|
||||
width, height, 4*width, format, type,
|
||||
pixels->data, pixels->byteLength,
|
||||
-1,
|
||||
WebGLTexelFormat::RGBA8, PR_FALSE);
|
||||
}
|
||||
|
||||
@ -4309,6 +4487,7 @@ WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level,
|
||||
isurf->Width(), isurf->Height(), isurf->Stride(),
|
||||
format, type,
|
||||
isurf->Data(), byteLength,
|
||||
-1,
|
||||
srcFormat, PR_TRUE);
|
||||
}
|
||||
|
||||
@ -4385,8 +4564,7 @@ BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *u
|
||||
|
||||
int mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
|
||||
{
|
||||
if (type == LOCAL_GL_UNSIGNED_BYTE)
|
||||
{
|
||||
if (type == LOCAL_GL_UNSIGNED_BYTE) {
|
||||
switch (format) {
|
||||
case LOCAL_GL_RGBA:
|
||||
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.");
|
||||
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 {
|
||||
switch (type) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,8 @@
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#if defined(USE_ANGLE)
|
||||
#include "angle/ShaderLang.h"
|
||||
#endif
|
||||
@ -327,53 +329,78 @@ PRBool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
|
||||
}
|
||||
}
|
||||
|
||||
PRBool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type,
|
||||
PRUint32 *texelSize, const char *info)
|
||||
PRBool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
|
||||
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) {
|
||||
case LOCAL_GL_ALPHA:
|
||||
case LOCAL_GL_LUMINANCE:
|
||||
*texelSize = 1;
|
||||
*texelSize = 1 * texMultiplier;
|
||||
return PR_TRUE;
|
||||
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||
*texelSize = 2;
|
||||
*texelSize = 2 * texMultiplier;
|
||||
return PR_TRUE;
|
||||
case LOCAL_GL_RGB:
|
||||
*texelSize = 3;
|
||||
*texelSize = 3 * texMultiplier;
|
||||
return PR_TRUE;
|
||||
case LOCAL_GL_RGBA:
|
||||
*texelSize = 4;
|
||||
*texelSize = 4 * texMultiplier;
|
||||
return PR_TRUE;
|
||||
default:
|
||||
ErrorInvalidEnum("%s: invalid format 0x%x", info, format);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -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
|
||||
WebGLContext::InitAndValidateGL()
|
||||
{
|
||||
@ -547,10 +592,6 @@ WebGLContext::InitAndValidateGL()
|
||||
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*) &mPixelStorePackAlignment);
|
||||
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
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
@ -148,6 +148,38 @@ void unpackA8ToRGBA8(const uint8_t* __restrict source, uint8_t* __restrict desti
|
||||
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.
|
||||
//
|
||||
@ -360,6 +392,66 @@ void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* __restrict source, uin
|
||||
| ((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 namespace WebGLTexelConversions
|
||||
|
@ -172,15 +172,16 @@ static PRInt64 GetCanvasMemoryUsed(void *) {
|
||||
return gCanvasMemoryUsed;
|
||||
}
|
||||
|
||||
// This isn't "heap-used/content/canvas/2d-pixel-bytes" because the pixels of a
|
||||
// canvas may not be stored on the heap. And if they are, they will be tracked
|
||||
// by the underlying surface implementations. See bug 655638 for details.
|
||||
// This is MR_OTHER because it's not always clear where in memory the pixels of
|
||||
// a canvas are stored. Furthermore, this memory will be tracked by the
|
||||
// underlying surface implementations. See bug 655638 for details.
|
||||
NS_MEMORY_REPORTER_IMPLEMENT(CanvasMemory,
|
||||
"canvas-2d-pixel-bytes",
|
||||
"Memory used by 2D canvases. Each canvas "
|
||||
"requires (width * height * 4) bytes.",
|
||||
GetCanvasMemoryUsed,
|
||||
NULL)
|
||||
"canvas-2d-pixel-bytes",
|
||||
MR_OTHER,
|
||||
"Memory used by 2D canvases. Each canvas requires (width * height * 4) "
|
||||
"bytes.",
|
||||
GetCanvasMemoryUsed,
|
||||
NULL)
|
||||
|
||||
static void
|
||||
CopyContext(gfxContext* dest, gfxContext* src)
|
||||
|
@ -78,8 +78,10 @@ successfullyParsed = true;
|
||||
</script>
|
||||
</head>
|
||||
<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>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -84,9 +84,11 @@ if (!gl) {
|
||||
testPassed("No OES_texture_float support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled OES_texture_float extension");
|
||||
dump('XXXXXX ' + gl.getExtension("OES_texture_float") + '\n');
|
||||
runTextureCreationTest(testProgram, true);
|
||||
runRenderTargetTest(testProgram);
|
||||
runUniqueObjectTest();
|
||||
// this sub-test is currently failing, see discussion in bug 630672
|
||||
// runUniqueObjectTest();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
conformance/buffer-preserve-test.html
|
||||
conformance/context-attributes.html
|
||||
conformance/gl-getshadersource.html
|
||||
conformance/gl-get-active-attribute.html
|
||||
conformance/gl-uniform-bool.html
|
||||
@ -19,4 +17,3 @@ conformance/object-deletion-behaviour.html
|
||||
conformance/read-pixels-test.html
|
||||
conformance/tex-sub-image-2d-bad-args.html
|
||||
conformance/uninitialized-test.html
|
||||
conformance/webgl-specific.html
|
||||
|
@ -1,7 +1,4 @@
|
||||
conformance/buffer-preserve-test.html
|
||||
conformance/canvas-test.html
|
||||
conformance/canvas-test.html
|
||||
conformance/context-attributes.html
|
||||
conformance/gl-getshadersource.html
|
||||
conformance/gl-object-get-calls.html
|
||||
conformance/texture-npot.html
|
||||
@ -12,7 +9,6 @@ conformance/read-pixels-test.html
|
||||
conformance/tex-input-validation.html
|
||||
conformance/tex-sub-image-2d-bad-args.html
|
||||
conformance/uninitialized-test.html
|
||||
conformance/webgl-specific.html
|
||||
conformance/more/functions/copyTexImage2D.html
|
||||
conformance/more/functions/copyTexSubImage2D.html
|
||||
conformance/more/functions/copyTexSubImage2DBadArgs.html
|
||||
|
@ -1,5 +1,3 @@
|
||||
conformance/buffer-preserve-test.html
|
||||
conformance/context-attributes.html
|
||||
conformance/gl-getshadersource.html
|
||||
conformance/glsl-conformance.html
|
||||
conformance/invalid-passed-params.html
|
||||
@ -7,7 +5,6 @@ conformance/object-deletion-behaviour.html
|
||||
conformance/read-pixels-test.html
|
||||
conformance/tex-sub-image-2d-bad-args.html
|
||||
conformance/uninitialized-test.html
|
||||
conformance/webgl-specific.html
|
||||
conformance/more/conformance/quickCheckAPI.html
|
||||
conformance/more/functions/copyTexImage2D.html
|
||||
conformance/more/functions/copyTexSubImage2D.html
|
||||
|
BIN
content/canvas/test/webgl/resources/thunderbird-logo-64x64.png
Normal file
BIN
content/canvas/test/webgl/resources/thunderbird-logo-64x64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
@ -1225,20 +1225,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
|
||||
nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(actionslot, ".action");
|
||||
NS_NAMED_LITERAL_CSTRING(numlinesslot, ".numlines");
|
||||
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());
|
||||
PRBool useSysNumLines = UseSystemScrollSettingFor(msEvent);
|
||||
PRInt32 action = GetWheelActionFor(msEvent);
|
||||
|
||||
if (!useSysNumLines) {
|
||||
// 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
|
||||
// directions.
|
||||
|
||||
nsCAutoString numLinesKey(baseKey);
|
||||
numLinesKey.Append(numlinesslot);
|
||||
PRInt32 numLines = nsContentUtils::GetIntPref(numLinesKey.get());
|
||||
PRInt32 numLines = GetScrollLinesFor(msEvent);
|
||||
|
||||
PRBool swapDirs = (numLines < 0);
|
||||
PRInt32 userSize = swapDirs ? -numLines : numLines;
|
||||
@ -2573,6 +2559,66 @@ nsEventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
|
||||
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
|
||||
nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
@ -3062,45 +3108,8 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
if (*aStatus != nsEventStatus_eConsumeNoDefault) {
|
||||
// Build the preference keys, based on the event properties.
|
||||
NS_NAMED_LITERAL_CSTRING(actionslot, ".action");
|
||||
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;
|
||||
}
|
||||
}
|
||||
PRBool useSysNumLines = UseSystemScrollSettingFor(msEvent);
|
||||
PRInt32 action = ComputeWheelActionFor(msEvent, useSysNumLines);
|
||||
|
||||
switch (action) {
|
||||
case MOUSE_SCROLL_N_LINES:
|
||||
@ -4686,13 +4695,35 @@ nsEventStateManager::DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
|
||||
nsIFrame* aTargetFrame)
|
||||
{
|
||||
nsMouseScrollEvent* msEvent = aEvent->mInput.mMouseScrollEvent;
|
||||
nsIScrollableFrame::ScrollUnit unit;
|
||||
if (msEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage) {
|
||||
unit = nsIScrollableFrame::PAGES;
|
||||
} else {
|
||||
unit = nsIScrollableFrame::LINES;
|
||||
|
||||
// Don't use high resolution scrolling when user customize the scrolling
|
||||
// speed.
|
||||
if (!UseSystemScrollSettingFor(msEvent)) {
|
||||
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
|
||||
|
@ -342,6 +342,33 @@ protected:
|
||||
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
|
||||
nsresult ChangeTextSize(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
|
||||
|
||||
/*
|
||||
|
@ -83,16 +83,11 @@ PRBool nsXMLEventsListener::InitXMLEventsListener(nsIDocument * aDocument,
|
||||
nsIURI *baseURI = aDocument->GetDocBaseURI();
|
||||
rv = NS_NewURI( getter_AddRefs(handlerURI), handlerURIStr, nsnull, baseURI);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIURL> handlerURL(do_QueryInterface(handlerURI));
|
||||
if (handlerURL) {
|
||||
handlerURL->GetRef(handlerRef);
|
||||
handlerURL->SetRef(EmptyCString());
|
||||
//We support only XML Events Basic.
|
||||
docURI->Equals(handlerURL, &equals);
|
||||
if (equals) {
|
||||
handler =
|
||||
aDocument->GetElementById(NS_ConvertUTF8toUTF16(handlerRef));
|
||||
}
|
||||
handlerURI->GetRef(handlerRef);
|
||||
// We support only XML Events Basic.
|
||||
rv = docURI->EqualsExceptRef(handlerURI, &equals);
|
||||
if (NS_SUCCEEDED(rv) && equals) {
|
||||
handler = aDocument->GetElementById(NS_ConvertUTF8toUTF16(handlerRef));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ CPPSRCS = \
|
||||
nsDOMValidityState.cpp \
|
||||
nsIConstraintValidation.cpp \
|
||||
nsRadioVisitor.cpp \
|
||||
nsDOMStringMap.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_MEDIA
|
||||
|
334
content/html/content/src/nsDOMStringMap.cpp
Normal file
334
content/html/content/src/nsDOMStringMap.cpp
Normal 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;
|
||||
}
|
80
content/html/content/src/nsDOMStringMap.h
Normal file
80
content/html/content/src/nsDOMStringMap.h
Normal 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
|
@ -103,6 +103,8 @@
|
||||
|
||||
#include "nsIDOMText.h"
|
||||
|
||||
#include "nsDOMStringMap.h"
|
||||
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIEditorIMESupport.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
@ -302,7 +304,7 @@ nsGenericHTMLElement::DOMQueryInterface(nsIDOMHTMLElement *aElement,
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
// No closing bracket, because NS_INTERFACE_MAP_END does that for us.
|
||||
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst) const
|
||||
{
|
||||
@ -364,6 +366,33 @@ nsGenericHTMLElement::SetAttribute(const nsAString& aName,
|
||||
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
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetId(nsAString& aId)
|
||||
@ -1231,6 +1260,12 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* 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,
|
||||
|
@ -64,6 +64,7 @@ class nsIEditor;
|
||||
struct nsRect;
|
||||
struct nsSize;
|
||||
class nsHTMLFormElement;
|
||||
class nsIDOMDOMStringMap;
|
||||
|
||||
typedef nsMappedAttributeElement nsGenericHTMLElementBase;
|
||||
|
||||
@ -150,6 +151,9 @@ public:
|
||||
nsresult GetContentEditable(nsAString& aContentEditable);
|
||||
nsresult GetIsContentEditable(PRBool* 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
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
@ -591,19 +591,25 @@ nsHTMLCanvasElement::UpdateContext(nsIPropertyBag *aNewContextOptions)
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsIntSize sz = GetWidthHeight();
|
||||
|
||||
rv = mCurrentContext->SetIsOpaque(GetIsOpaque());
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
mCurrentContext = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mCurrentContext->SetContextOptions(aNewContextOptions);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
mCurrentContext = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsIntSize sz = GetWidthHeight();
|
||||
rv = mCurrentContext->SetDimensions(sz.width, sz.height);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
mCurrentContext = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -84,7 +84,6 @@ public:
|
||||
RestoreSelectionState(nsTextEditorState *aState, nsTextControlFrame *aFrame,
|
||||
PRInt32 aStart, PRInt32 aEnd)
|
||||
: mFrame(aFrame),
|
||||
mWeakFrame(aFrame),
|
||||
mStart(aStart),
|
||||
mEnd(aEnd),
|
||||
mTextEditorState(aState)
|
||||
@ -92,19 +91,24 @@ public:
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mWeakFrame.IsAlive()) {
|
||||
if (mFrame) {
|
||||
// SetSelectionRange leads to Selection::AddRange which flushes Layout -
|
||||
// need to block script to avoid nested PrepareEditor calls (bug 642800).
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
mFrame->SetSelectionRange(mStart, mEnd);
|
||||
mTextEditorState->HideSelectionIfBlurred();
|
||||
}
|
||||
mTextEditorState->FinishedRestoringSelection();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Let the text editor tell us we're no longer relevant - avoids use of nsWeakFrame
|
||||
void Revoke() {
|
||||
mFrame = nsnull;
|
||||
}
|
||||
|
||||
private:
|
||||
nsTextControlFrame* mFrame;
|
||||
nsWeakFrame mWeakFrame;
|
||||
PRInt32 mStart;
|
||||
PRInt32 mEnd;
|
||||
nsTextEditorState* mTextEditorState;
|
||||
@ -645,7 +649,7 @@ protected:
|
||||
|
||||
protected:
|
||||
|
||||
nsWeakFrame mFrame;
|
||||
nsIFrame* mFrame;
|
||||
|
||||
nsITextControlElement* const mTxtCtrlElement;
|
||||
|
||||
@ -673,7 +677,8 @@ protected:
|
||||
*/
|
||||
|
||||
nsTextInputListener::nsTextInputListener(nsITextControlElement* aTxtCtrlElement)
|
||||
: mTxtCtrlElement(aTxtCtrlElement)
|
||||
: mFrame(nsnull)
|
||||
, mTxtCtrlElement(aTxtCtrlElement)
|
||||
, mSelectionWasCollapsed(PR_TRUE)
|
||||
, mHadUndoItems(PR_FALSE)
|
||||
, mHadRedoItems(PR_FALSE)
|
||||
@ -703,7 +708,9 @@ NS_IMETHODIMP
|
||||
nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel, PRInt16 aReason)
|
||||
{
|
||||
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;
|
||||
|
||||
// Fire the select event
|
||||
@ -748,7 +755,7 @@ nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection*
|
||||
|
||||
mSelectionWasCollapsed = collapsed;
|
||||
|
||||
if (!mFrame.IsAlive() || !nsContentUtils::IsFocusedContent(mFrame->GetContent()))
|
||||
if (!weakFrame.IsAlive() || !nsContentUtils::IsFocusedContent(mFrame->GetContent()))
|
||||
return NS_OK;
|
||||
|
||||
return UpdateTextInputCommands(NS_LITERAL_STRING("select"));
|
||||
@ -799,7 +806,6 @@ DoCommandCallback(const char *aCommand, void *aData)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::KeyDown(nsIDOMEvent *aDOMEvent)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
|
||||
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
@ -818,7 +824,6 @@ nsTextInputListener::KeyDown(nsIDOMEvent *aDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::KeyPress(nsIDOMEvent *aDOMEvent)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
|
||||
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
@ -837,7 +842,6 @@ nsTextInputListener::KeyPress(nsIDOMEvent *aDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::KeyUp(nsIDOMEvent *aDOMEvent)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
|
||||
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
@ -859,8 +863,9 @@ nsTextInputListener::KeyUp(nsIDOMEvent *aDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::EditAction()
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsITextControlFrame* frameBase = do_QueryFrame(mFrame.GetFrame());
|
||||
nsWeakFrame weakFrame = mFrame;
|
||||
|
||||
nsITextControlFrame* frameBase = do_QueryFrame(mFrame);
|
||||
nsTextControlFrame* frame = static_cast<nsTextControlFrame*> (frameBase);
|
||||
NS_ASSERTION(frame, "Where is our frame?");
|
||||
//
|
||||
@ -887,7 +892,7 @@ nsTextInputListener::EditAction()
|
||||
mHadRedoItems = numRedoItems != 0;
|
||||
}
|
||||
|
||||
if (!mFrame.IsAlive()) {
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -916,8 +921,6 @@ nsTextInputListener::EditAction()
|
||||
nsresult
|
||||
nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
|
||||
nsIContent* content = mFrame->GetContent();
|
||||
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
|
||||
|
||||
@ -967,6 +970,7 @@ nsTextInputListener::GetKeyBindings()
|
||||
|
||||
nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement)
|
||||
: mTextCtrlElement(aOwningElement),
|
||||
mRestoringSelection(nsnull),
|
||||
mBoundFrame(nsnull),
|
||||
mTextListener(nsnull),
|
||||
mEditorInitialized(PR_FALSE),
|
||||
@ -1385,8 +1389,13 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
|
||||
// Restore our selection after being bound to a new frame
|
||||
if (mSelState) {
|
||||
nsContentUtils::AddScriptRunner(new RestoreSelectionState(this, mBoundFrame, mSelState->mStart, mSelState->mEnd));
|
||||
mSelState = nsnull;
|
||||
if (mRestoringSelection) // paranoia
|
||||
mRestoringSelection->Revoke();
|
||||
mRestoringSelection = new RestoreSelectionState(this, mBoundFrame, mSelState->mStart, mSelState->mEnd);
|
||||
if (mRestoringSelection) {
|
||||
nsContentUtils::AddScriptRunner(mRestoringSelection);
|
||||
mSelState = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -1419,6 +1428,11 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
||||
nsAutoString value;
|
||||
GetValue(value, PR_TRUE);
|
||||
|
||||
if (mRestoringSelection) {
|
||||
mRestoringSelection->Revoke();
|
||||
mRestoringSelection = nsnull;
|
||||
}
|
||||
|
||||
// Save our selection state if needed.
|
||||
// Note that nsTextControlFrame::GetSelectionRange attempts to initialize the
|
||||
// editor before grabbing the range, and because this is not an acceptable
|
||||
|
@ -140,6 +140,8 @@ struct SelectionState;
|
||||
* frame is bound to the text editor state object.
|
||||
*/
|
||||
|
||||
class RestoreSelectionState;
|
||||
|
||||
class nsTextEditorState {
|
||||
public:
|
||||
explicit nsTextEditorState(nsITextControlElement* aOwningElement);
|
||||
@ -213,6 +215,8 @@ public:
|
||||
void HideSelectionIfBlurred();
|
||||
|
||||
private:
|
||||
friend class RestoreSelectionState;
|
||||
|
||||
// not copy constructible
|
||||
nsTextEditorState(const nsTextEditorState&);
|
||||
// not assignable
|
||||
@ -225,6 +229,8 @@ private:
|
||||
void DestroyEditor();
|
||||
void Clear();
|
||||
|
||||
void FinishedRestoringSelection() { mRestoringSelection = nsnull; }
|
||||
|
||||
class InitializationGuard {
|
||||
public:
|
||||
explicit InitializationGuard(nsTextEditorState& aState) :
|
||||
@ -253,6 +259,7 @@ private:
|
||||
nsITextControlElement* const mTextCtrlElement;
|
||||
nsRefPtr<nsTextInputSelectionImpl> mSelCon;
|
||||
nsAutoPtr<SelectionState> mSelState;
|
||||
RestoreSelectionState* mRestoringSelection;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
nsCOMPtr<nsIContent> mRootNode;
|
||||
nsCOMPtr<nsIContent> mPlaceholderDiv;
|
||||
|
@ -274,6 +274,7 @@ _TEST_FILES = \
|
||||
test_bug643051.html \
|
||||
test_bug583514.html \
|
||||
test_bug514437.html \
|
||||
test_bug560112.html \
|
||||
test_bug649134.html \
|
||||
$(NULL)
|
||||
|
||||
|
212
content/html/content/test/test_bug560112.html
Normal file
212
content/html/content/test/test_bug560112.html
Normal 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>
|
@ -305,16 +305,13 @@ nsXBLPrototypeBinding::Init(const nsACString& aID,
|
||||
nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// The binding URI might not be a nsIURL (e.g. for data: URIs). In that case,
|
||||
// we always use the first binding, so we don't need to keep track of the ID.
|
||||
nsCOMPtr<nsIURL> bindingURL = do_QueryInterface(mBindingURI);
|
||||
if (bindingURL) {
|
||||
if (aFirstBinding) {
|
||||
rv = mBindingURI->Clone(getter_AddRefs(mAlternateBindingURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
bindingURL->SetRef(aID);
|
||||
// The binding URI might be an immutable URI (e.g. for about: URIs). In that case,
|
||||
// we'll fail in SetRef below, but that doesn't matter much for now.
|
||||
if (aFirstBinding) {
|
||||
rv = mBindingURI->Clone(getter_AddRefs(mAlternateBindingURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mBindingURI->SetRef(aID);
|
||||
|
||||
mXBLDocInfoWeak = aInfo;
|
||||
|
||||
|
@ -862,9 +862,7 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCAutoString ref;
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
|
||||
if (url)
|
||||
url->GetRef(ref);
|
||||
aURI->GetRef(ref);
|
||||
|
||||
nsCOMPtr<nsIDocument> boundDocument = aBoundElement->GetOwnerDoc();
|
||||
|
||||
@ -1129,12 +1127,8 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
|
||||
nsRefPtr<nsXBLDocumentInfo> info;
|
||||
|
||||
nsCOMPtr<nsIURI> documentURI;
|
||||
rv = aBindingURI->Clone(getter_AddRefs(documentURI));
|
||||
rv = aBindingURI->CloneIgnoringRef(getter_AddRefs(documentURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURL> documentURL(do_QueryInterface(documentURI));
|
||||
if (documentURL)
|
||||
documentURL->SetRef(EmptyCString());
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
// We've got a file. Check our XBL document cache.
|
||||
|
@ -743,15 +743,10 @@ TX_CompileStylesheet(nsINode* aNode, txMozillaXSLTProcessor* aProcessor,
|
||||
nsIURI* docUri = doc->GetDocumentURI();
|
||||
NS_ENSURE_TRUE(docUri, NS_ERROR_FAILURE);
|
||||
|
||||
docUri->Clone(getter_AddRefs(uri));
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
|
||||
|
||||
// We need to remove the ref, a URL with a ref would mean that we have an
|
||||
// We need to remove the ref, a URI with a ref would mean that we have an
|
||||
// embedded stylesheet.
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(uri);
|
||||
if (url) {
|
||||
url->SetRef(EmptyCString());
|
||||
}
|
||||
docUri->CloneIgnoringRef(getter_AddRefs(uri));
|
||||
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
|
||||
|
||||
uri->GetSpec(spec);
|
||||
NS_ConvertUTF8toUTF16 stylesheetURI(spec);
|
||||
|
@ -328,34 +328,29 @@ nsXULContentUtils::MakeElementURI(nsIDocument* aDocument,
|
||||
// Convert an element's ID to a URI that can be used to refer to
|
||||
// the element in the XUL graph.
|
||||
|
||||
nsIURI *docURL = aDocument->GetDocumentURI();
|
||||
NS_ENSURE_TRUE(docURL, NS_ERROR_UNEXPECTED);
|
||||
nsIURI *docURI = aDocument->GetDocumentURI();
|
||||
NS_ENSURE_TRUE(docURI, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIURI> docURIClone;
|
||||
nsresult rv = docURL->Clone(getter_AddRefs(docURIClone));
|
||||
nsRefPtr<nsIURI> docURIClone;
|
||||
nsresult rv = docURI->Clone(getter_AddRefs(docURIClone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURL> mutableURL(do_QueryInterface(docURIClone));
|
||||
if (!mutableURL) {
|
||||
nsCString uri;
|
||||
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;
|
||||
rv = docURIClone->SetRef(NS_ConvertUTF16toUTF8(aElementID));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return docURIClone->GetSpec(aURI);
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(mutableURL, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
rv = mutableURL->SetRef(NS_ConvertUTF16toUTF8(aElementID));
|
||||
// docURIClone is apparently immutable. Fine - we can append ref manually.
|
||||
rv = docURI->GetSpec(aURI);
|
||||
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());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(uri);
|
||||
if (url) {
|
||||
nsCAutoString ref;
|
||||
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();
|
||||
}
|
||||
nsCAutoString ref;
|
||||
uri->GetRef(ref);
|
||||
CopyUTF8toUTF16(ref, aElementID);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -122,9 +122,15 @@ ConsoleAPI.prototype = {
|
||||
if (!aID)
|
||||
return;
|
||||
|
||||
let stack = this.getStackTrace();
|
||||
// Skip the first frame since it contains an internal call.
|
||||
let frame = stack[1];
|
||||
let consoleEvent = {
|
||||
ID: aID,
|
||||
level: aLevel,
|
||||
filename: frame.filename,
|
||||
lineNumber: frame.lineNumber,
|
||||
functionName: frame.functionName,
|
||||
arguments: aArguments
|
||||
};
|
||||
|
||||
@ -157,7 +163,7 @@ ConsoleAPI.prototype = {
|
||||
}
|
||||
|
||||
return stack;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let NSGetFactory = XPCOMUtils.generateNSGetFactory([ConsoleAPI]);
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include "WrapperFactory.h"
|
||||
#include "AccessCheck.h"
|
||||
|
||||
#include "xpcprivate.h"
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsCRT.h"
|
||||
@ -135,6 +137,8 @@
|
||||
#include "nsIDOMNameList.h"
|
||||
#include "nsIDOMNSElement.h"
|
||||
|
||||
#include "nsDOMStringMap.h"
|
||||
|
||||
// HTMLFormElement helper includes
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
@ -473,6 +477,8 @@
|
||||
#include "nsIDOMFileError.h"
|
||||
#include "nsIDOMFormData.h"
|
||||
|
||||
#include "nsIDOMDOMStringMap.h"
|
||||
|
||||
#include "nsIDOMDesktopNotification.h"
|
||||
#include "nsIDOMNavigatorDesktopNotification.h"
|
||||
|
||||
@ -569,6 +575,14 @@ static const char kDOMStringBundleURL[] =
|
||||
nsIXPCScriptable::WANT_GETPROPERTY | \
|
||||
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 \
|
||||
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \
|
||||
nsIXPCScriptable::WANT_ADDPROPERTY)
|
||||
@ -1337,6 +1351,11 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(MozURLProperty, nsDOMGenericSH,
|
||||
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,
|
||||
DEFAULT_SCRIPTABLE_FLAGS |
|
||||
@ -1434,6 +1453,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLActiveInfo, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(WebGLExtension, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
|
||||
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(ChromeWorker, nsDOMWorker::NewChromeWorker)
|
||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFile::NewFile)
|
||||
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
|
||||
};
|
||||
|
||||
nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
|
||||
@ -3982,12 +4004,10 @@ nsDOMClassInfo::Init()
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob_MOZILLA_2_0_BRANCH)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
@ -4008,6 +4028,14 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozURLProperty)
|
||||
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_ENTRY(nsIDOMWindow)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
|
||||
@ -4185,6 +4213,10 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLActiveInfo)
|
||||
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_ENTRY(nsIDOMPaintRequest)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
@ -8534,6 +8566,139 @@ nsContentListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
|
||||
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
|
||||
nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
|
@ -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*
|
||||
|
||||
|
@ -406,6 +406,9 @@ DOMCI_CLASS(FileException)
|
||||
DOMCI_CLASS(FileError)
|
||||
DOMCI_CLASS(FileReader)
|
||||
DOMCI_CLASS(MozURLProperty)
|
||||
DOMCI_CLASS(MozBlobBuilder)
|
||||
|
||||
DOMCI_CLASS(DOMStringMap)
|
||||
|
||||
// DOM modal content window class, almost identical to Window
|
||||
DOMCI_CLASS(ModalContentWindow)
|
||||
@ -471,8 +474,8 @@ DOMCI_CLASS(WebGLFramebuffer)
|
||||
DOMCI_CLASS(WebGLRenderbuffer)
|
||||
DOMCI_CLASS(WebGLUniformLocation)
|
||||
DOMCI_CLASS(WebGLActiveInfo)
|
||||
DOMCI_CLASS(WebGLExtension)
|
||||
|
||||
// WebGL Buffers
|
||||
DOMCI_CLASS(PaintRequest)
|
||||
DOMCI_CLASS(PaintRequestList)
|
||||
|
||||
|
@ -79,6 +79,8 @@
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsPluginArray.h"
|
||||
#include "nsIPluginHost.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsIPluginInstanceOwner.h"
|
||||
#include "nsGeolocation.h"
|
||||
#include "nsDesktopNotification.h"
|
||||
#include "nsContentCID.h"
|
||||
@ -6548,20 +6550,17 @@ nsGlobalWindow::InitJavaProperties()
|
||||
// can fail. If it fails, we won't try again...
|
||||
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);
|
||||
if (!mDummyJavaPluginOwner) {
|
||||
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
|
||||
// events during the above call, which can lead to this window being
|
||||
|
@ -1140,6 +1140,7 @@ protected:
|
||||
|
||||
nsresult CheckURL(nsIURI *url, nsIDocShellLoadInfo** aLoadInfo);
|
||||
|
||||
nsString mCachedHash;
|
||||
nsWeakPtr mDocShell;
|
||||
};
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user