Merge mozilla-central and tracemonkey.

This commit is contained in:
Chris Leary 2011-05-23 00:02:05 -07:00
commit 52221a8477
337 changed files with 15632 additions and 6286 deletions

View File

@ -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");

View File

@ -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);

View File

@ -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;
}

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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;
};

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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();
}

View File

@ -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)

View File

@ -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,

View File

@ -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,

View File

@ -1005,6 +1005,19 @@ pref("devtools.chrome.enabled", false);
// Change to -1 if you do not want the Web Console to remember its last height.
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");

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
},
};

View File

@ -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;"

View File

@ -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

View File

@ -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 \

View File

@ -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);
}

View File

@ -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");

View File

@ -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();

View File

@ -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");

View File

@ -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");

View File

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

View File

@ -33,10 +33,11 @@ function runTests()
"sp-menu-open": "openFile",
"sp-menu-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",

View File

@ -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>

View File

@ -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;
},
/**

View File

@ -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">

View File

@ -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");

View File

@ -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.">

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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=

View File

@ -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)

View File

@ -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);
};

View File

@ -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

View File

@ -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;

View File

@ -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('#'));

View File

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

View File

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

View File

@ -49,7 +49,6 @@
#include "nsIConverterInputStream.h"
#include "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);

View File

@ -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;

View File

@ -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:

View File

@ -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) {

View File

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

View File

@ -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

View File

@ -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")

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=575946
<title>Test for Bug 575946</title>
<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>

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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!");

View File

@ -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;
}

View File

@ -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
**/

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1225,20 +1225,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
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

View File

@ -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
/*

View File

@ -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));
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* William Chen <wchen@mozilla.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDOMStringMap_h
#define nsDOMStringMap_h
#include "nsIDOMDOMStringMap.h"
#include "nsCycleCollectionParticipant.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsString.h"
class nsGenericHTMLElement;
class nsDOMStringMap : public nsIDOMDOMStringMap
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMDOMSTRINGMAP
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
nsDOMStringMap(nsGenericHTMLElement* aElement);
// GetDataPropList is not defined in IDL due to difficulty
// of returning arrays in IDL. Instead, we cast to this
// class if this method needs to be called.
nsresult GetDataPropList(nsTArray<nsString>& aResult);
nsresult RemovePropInternal(nsIAtom* aAttr);
nsGenericHTMLElement* GetElement();
private:
virtual ~nsDOMStringMap();
protected:
nsRefPtr<nsGenericHTMLElement> mElement;
// Flag to guard against infinite recursion.
PRBool mRemovingProp;
PRBool DataPropToAttr(const nsAString& aProp, nsAString& aResult);
PRBool AttrToDataProp(const nsAString& aAttr, nsAString& aResult);
};
#endif

View File

@ -103,6 +103,8 @@
#include "nsIDOMText.h"
#include "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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

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

View File

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

View File

@ -305,16 +305,13 @@ nsXBLPrototypeBinding::Init(const nsACString& aID,
nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI));
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;

View File

@ -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.

View File

@ -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);

View File

@ -328,34 +328,29 @@ nsXULContentUtils::MakeElementURI(nsIDocument* aDocument,
// Convert an element's ID to a URI that can be used to refer to
// 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;
}

View File

@ -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]);

View File

@ -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,

View File

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

View File

@ -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)

View File

@ -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

View File

@ -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