merge fx-team to m-c

This commit is contained in:
Rob Campbell 2012-03-08 10:30:11 -04:00
commit 3bf1f57058
489 changed files with 15962 additions and 8064 deletions

View File

@ -43,7 +43,7 @@
interface nsIEditor; interface nsIEditor;
[scriptable, uuid(52837507-202d-4e72-a482-5f068a1fd720)] [scriptable, uuid(e242d495-5cde-4b1c-8c84-2525b14939f5)]
interface nsIAccessibleEditableText : nsISupports interface nsIAccessibleEditableText : nsISupports
{ {
/** /**
@ -103,19 +103,4 @@ interface nsIAccessibleEditableText : nsISupports
* clipboard into the text represented by this object. * clipboard into the text represented by this object.
*/ */
void pasteText (in long position); void pasteText (in long position);
/**
* Returns an editor associated with the accessible.
*/
[noscript] readonly attribute nsIEditor associatedEditor;
}; };
/*
Assumptions:
selectAttributes method takes an nsISupports parameter.
'set' methods throw exception on failure.
'wstring' inputs are potentially multibyte (UTF-16 for
instance); 'string' and UTF-8 may be a better choice.
*/

View File

@ -696,6 +696,16 @@ nsApplicationAccessibleWrap::Unload()
// } // }
} }
NS_IMETHODIMP
nsApplicationAccessibleWrap::GetName(nsAString& aName)
{
// ATK doesn't provide a way to obtain an application name (for example,
// Firefox or Thunderbird) like IA2 does. Thus let's return an application
// name as accessible name that was used to get a branding name (for example,
// Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
return GetAppName(aName);
}
NS_IMETHODIMP NS_IMETHODIMP
nsApplicationAccessibleWrap::GetNativeInterface(void **aOutAccessible) nsApplicationAccessibleWrap::GetNativeInterface(void **aOutAccessible)
{ {

View File

@ -57,6 +57,8 @@ public:
virtual bool Init(); virtual bool Init();
// nsAccessible // nsAccessible
NS_IMETHOD GetName(nsAString &aName);
virtual bool AppendChild(nsAccessible* aChild); virtual bool AppendChild(nsAccessible* aChild);
virtual bool RemoveChild(nsAccessible* aChild); virtual bool RemoveChild(nsAccessible* aChild);

View File

@ -680,8 +680,7 @@ NotificationController::CreateTextChangeEventFor(AccMutationEvent* aEvent)
// Don't fire event for the first html:br in an editor. // Don't fire event for the first html:br in an editor.
if (aEvent->mAccessible->Role() == roles::WHITESPACE) { if (aEvent->mAccessible->Role() == roles::WHITESPACE) {
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor = textAccessible->GetEditor();
textAccessible->GetAssociatedEditor(getter_AddRefs(editor));
if (editor) { if (editor) {
bool isEmpty = false; bool isEmpty = false;
editor->GetDocumentIsEmpty(&isEmpty); editor->GetDocumentIsEmpty(&isEmpty);

View File

@ -969,10 +969,8 @@ void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame
*aBoundingFrame = ancestorFrame; *aBoundingFrame = ancestorFrame;
// If any other frame type, we only need to deal with the primary frame // If any other frame type, we only need to deal with the primary frame
// Otherwise, there may be more frames attached to the same content node // Otherwise, there may be more frames attached to the same content node
if (!nsCoreUtils::IsCorrectFrameType(ancestorFrame, if (ancestorFrame->GetType() != nsGkAtoms::inlineFrame &&
nsGkAtoms::inlineFrame) && ancestorFrame->GetType() != nsGkAtoms::textFrame)
!nsCoreUtils::IsCorrectFrameType(ancestorFrame,
nsGkAtoms::textFrame))
break; break;
ancestorFrame = ancestorFrame->GetParent(); ancestorFrame = ancestorFrame->GetParent();
} }
@ -996,8 +994,7 @@ void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame
nsIFrame *iterNextFrame = nsnull; nsIFrame *iterNextFrame = nsnull;
if (nsCoreUtils::IsCorrectFrameType(iterFrame, if (iterFrame->GetType() == nsGkAtoms::inlineFrame) {
nsGkAtoms::inlineFrame)) {
// Only do deeper bounds search if we're on an inline frame // Only do deeper bounds search if we're on an inline frame
// Inline frames can contain larger frames inside of them // Inline frames can contain larger frames inside of them
iterNextFrame = iterFrame->GetFirstPrincipalChild(); iterNextFrame = iterFrame->GetFirstPrincipalChild();

View File

@ -214,6 +214,11 @@ public:
*/ */
virtual PRUint64 NativeState(); virtual PRUint64 NativeState();
/**
* Return bit set of invisible and offscreen states.
*/
PRUint64 VisibilityState();
/** /**
* Returns attributes for accessible without explicitly setted ARIA * Returns attributes for accessible without explicitly setted ARIA
* attributes. * attributes.
@ -702,8 +707,6 @@ protected:
virtual nsIFrame* GetBoundsFrame(); virtual nsIFrame* GetBoundsFrame();
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame); virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
PRUint64 VisibilityState();
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Name helpers // Name helpers

View File

@ -503,17 +503,6 @@ nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror); return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
} }
bool
nsCoreUtils::IsCorrectFrameType(nsIFrame *aFrame, nsIAtom *aAtom)
{
NS_ASSERTION(aFrame != nsnull,
"aFrame is null in call to IsCorrectFrameType!");
NS_ASSERTION(aAtom != nsnull,
"aAtom is null in call to IsCorrectFrameType!");
return aFrame->GetType() == aAtom;
}
already_AddRefed<nsIDOMNode> already_AddRefed<nsIDOMNode>
nsCoreUtils::GetDOMNodeForContainer(nsIDocShellTreeItem *aContainer) nsCoreUtils::GetDOMNodeForContainer(nsIDocShellTreeItem *aContainer)
{ {

View File

@ -241,14 +241,6 @@ public:
*/ */
static bool IsErrorPage(nsIDocument *aDocument); static bool IsErrorPage(nsIDocument *aDocument);
/**
* Retrun true if the type of given frame equals to the given frame type.
*
* @param aFrame the frame
* @param aAtom the frame type
*/
static bool IsCorrectFrameType(nsIFrame* aFrame, nsIAtom* aAtom);
/** /**
* Return presShell for the document containing the given DOM node. * Return presShell for the document containing the given DOM node.
*/ */

View File

@ -333,8 +333,7 @@ nsDocAccessible::NativeState()
state |= states::INVISIBLE | states::OFFSCREEN; state |= states::INVISIBLE | states::OFFSCREEN;
} }
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor = GetEditor();
GetAssociatedEditor(getter_AddRefs(editor));
state |= editor ? states::EDITABLE : states::READONLY; state |= editor ? states::EDITABLE : states::READONLY;
return state; return state;
@ -553,37 +552,32 @@ nsDocAccessible::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor)
return NS_OK; return NS_OK;
} }
// nsIAccessibleHyperText method // nsHyperTextAccessible method
NS_IMETHODIMP nsDocAccessible::GetAssociatedEditor(nsIEditor **aEditor) already_AddRefed<nsIEditor>
nsDocAccessible::GetEditor() const
{ {
NS_ENSURE_ARG_POINTER(aEditor);
*aEditor = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
// Check if document is editable (designMode="on" case). Otherwise check if // Check if document is editable (designMode="on" case). Otherwise check if
// the html:body (for HTML document case) or document element is editable. // the html:body (for HTML document case) or document element is editable.
if (!mDocument->HasFlag(NODE_IS_EDITABLE) && if (!mDocument->HasFlag(NODE_IS_EDITABLE) &&
!mContent->HasFlag(NODE_IS_EDITABLE)) !mContent->HasFlag(NODE_IS_EDITABLE))
return NS_OK; return nsnull;
nsCOMPtr<nsISupports> container = mDocument->GetContainer(); nsCOMPtr<nsISupports> container = mDocument->GetContainer();
nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(container)); nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(container));
if (!editingSession) if (!editingSession)
return NS_OK; // No editing session interface return nsnull; // No editing session interface
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor;
editingSession->GetEditorForWindow(mDocument->GetWindow(), getter_AddRefs(editor)); editingSession->GetEditorForWindow(mDocument->GetWindow(), getter_AddRefs(editor));
if (!editor) { if (!editor)
return NS_OK; return nsnull;
}
bool isEditable; bool isEditable = false;
editor->GetIsDocumentEditable(&isEditable); editor->GetIsDocumentEditable(&isEditable);
if (isEditable) { if (isEditable)
NS_ADDREF(*aEditor = editor); return editor.forget();
}
return NS_OK; return nsnull;
} }
// nsDocAccessible public method // nsDocAccessible public method

View File

@ -133,8 +133,8 @@ public:
virtual nsresult HandleAccEvent(AccEvent* aAccEvent); virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
#endif #endif
// nsIAccessibleText // nsHyperTextAccessible
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor); virtual already_AddRefed<nsIEditor> GetEditor() const;
// nsDocAccessible // nsDocAccessible

View File

@ -544,11 +544,12 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible::DoAction(PRUint8 index)
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
} }
NS_IMETHODIMP nsHTMLTextFieldAccessible::GetAssociatedEditor(nsIEditor **aEditor) already_AddRefed<nsIEditor>
nsHTMLTextFieldAccessible::GetEditor() const
{ {
*aEditor = nsnull;
nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(mContent)); nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(mContent));
NS_ENSURE_TRUE(editableElt, NS_ERROR_FAILURE); if (!editableElt)
return nsnull;
// nsGenericHTMLElement::GetEditor has a security check. // nsGenericHTMLElement::GetEditor has a security check.
// Make sure we're not restricted by the permissions of // Make sure we're not restricted by the permissions of
@ -558,7 +559,7 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible::GetAssociatedEditor(nsIEditor **aEditor
bool pushed = stack && NS_SUCCEEDED(stack->Push(nsnull)); bool pushed = stack && NS_SUCCEEDED(stack->Push(nsnull));
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor;
nsresult rv = editableElt->GetEditor(aEditor); editableElt->GetEditor(getter_AddRefs(editor));
if (pushed) { if (pushed) {
JSContext* cx; JSContext* cx;
@ -566,7 +567,7 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible::GetAssociatedEditor(nsIEditor **aEditor
NS_ASSERTION(!cx, "context should be null"); NS_ASSERTION(!cx, "context should be null");
} }
return rv; return editor.forget();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -138,8 +138,8 @@ public:
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 index); NS_IMETHOD DoAction(PRUint8 index);
// nsIAccessibleEditableText // nsHyperTextAccessible
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor); virtual already_AddRefed<nsIEditor> GetEditor() const;
// nsAccessible // nsAccessible
virtual void ApplyARIAState(PRUint64* aState); virtual void ApplyARIAState(PRUint64* aState);

View File

@ -47,6 +47,7 @@
#include "States.h" #include "States.h"
#include "nsIClipboard.h" #include "nsIClipboard.h"
#include "nsContentUtils.h"
#include "nsFocusManager.h" #include "nsFocusManager.h"
#include "nsIDOMCharacterData.h" #include "nsIDOMCharacterData.h"
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
@ -165,8 +166,7 @@ nsHyperTextAccessible::NativeState()
{ {
PRUint64 states = nsAccessibleWrap::NativeState(); PRUint64 states = nsAccessibleWrap::NativeState();
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor = GetEditor();
GetAssociatedEditor(getter_AddRefs(editor));
if (editor) { if (editor) {
PRUint32 flags; PRUint32 flags;
editor->GetFlags(&flags); editor->GetFlags(&flags);
@ -710,8 +710,7 @@ nsHyperTextAccessible::HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
// If the given offsets are 0 and associated editor is empty then return // If the given offsets are 0 and associated editor is empty then return
// collapsed range with editor root element as range container. // collapsed range with editor root element as range container.
if (aStartHTOffset == 0 && aEndHTOffset == 0) { if (aStartHTOffset == 0 && aEndHTOffset == 0) {
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor = GetEditor();
GetAssociatedEditor(getter_AddRefs(editor));
if (editor) { if (editor) {
bool isEmpty = false; bool isEmpty = false;
editor->GetDocumentIsEmpty(&isEmpty); editor->GetDocumentIsEmpty(&isEmpty);
@ -1153,15 +1152,14 @@ nsHyperTextAccessible::GetTextAttributes(bool aIncludeDefAttrs,
// Compute spelling attributes on text accessible only. // Compute spelling attributes on text accessible only.
nsIFrame *offsetFrame = accAtOffset->GetFrame(); nsIFrame *offsetFrame = accAtOffset->GetFrame();
if (offsetFrame && offsetFrame->GetType() == nsGkAtoms::textFrame) { if (offsetFrame && offsetFrame->GetType() == nsGkAtoms::textFrame) {
nsCOMPtr<nsIDOMNode> node = accAtOffset->DOMNode();
PRInt32 nodeOffset = 0; PRInt32 nodeOffset = 0;
nsresult rv = RenderedToContentOffset(offsetFrame, offsetInAcc, nsresult rv = RenderedToContentOffset(offsetFrame, offsetInAcc,
&nodeOffset); &nodeOffset);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Set 'misspelled' text attribute. // Set 'misspelled' text attribute.
rv = GetSpellTextAttribute(node, nodeOffset, &startOffset, &endOffset, rv = GetSpellTextAttribute(accAtOffset->GetNode(), nodeOffset,
&startOffset, &endOffset,
aAttributes ? *aAttributes : nsnull); aAttributes ? *aAttributes : nsnull);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
@ -1455,8 +1453,10 @@ NS_IMETHODIMP nsHyperTextAccessible::SetTextContents(const nsAString &aText)
NS_IMETHODIMP NS_IMETHODIMP
nsHyperTextAccessible::InsertText(const nsAString &aText, PRInt32 aPosition) nsHyperTextAccessible::InsertText(const nsAString &aText, PRInt32 aPosition)
{ {
nsCOMPtr<nsIEditor> editor; if (IsDefunct())
GetAssociatedEditor(getter_AddRefs(editor)); return NS_ERROR_FAILURE;
nsCOMPtr<nsIEditor> editor = GetEditor();
nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor)); nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
NS_ENSURE_STATE(peditor); NS_ENSURE_STATE(peditor);
@ -1470,8 +1470,10 @@ nsHyperTextAccessible::InsertText(const nsAString &aText, PRInt32 aPosition)
NS_IMETHODIMP NS_IMETHODIMP
nsHyperTextAccessible::CopyText(PRInt32 aStartPos, PRInt32 aEndPos) nsHyperTextAccessible::CopyText(PRInt32 aStartPos, PRInt32 aEndPos)
{ {
nsCOMPtr<nsIEditor> editor; if (IsDefunct())
GetAssociatedEditor(getter_AddRefs(editor)); return NS_ERROR_FAILURE;
nsCOMPtr<nsIEditor> editor = GetEditor();
NS_ENSURE_STATE(editor); NS_ENSURE_STATE(editor);
nsresult rv = SetSelectionRange(aStartPos, aEndPos); nsresult rv = SetSelectionRange(aStartPos, aEndPos);
@ -1483,8 +1485,10 @@ nsHyperTextAccessible::CopyText(PRInt32 aStartPos, PRInt32 aEndPos)
NS_IMETHODIMP NS_IMETHODIMP
nsHyperTextAccessible::CutText(PRInt32 aStartPos, PRInt32 aEndPos) nsHyperTextAccessible::CutText(PRInt32 aStartPos, PRInt32 aEndPos)
{ {
nsCOMPtr<nsIEditor> editor; if (IsDefunct())
GetAssociatedEditor(getter_AddRefs(editor)); return NS_ERROR_FAILURE;
nsCOMPtr<nsIEditor> editor = GetEditor();
NS_ENSURE_STATE(editor); NS_ENSURE_STATE(editor);
nsresult rv = SetSelectionRange(aStartPos, aEndPos); nsresult rv = SetSelectionRange(aStartPos, aEndPos);
@ -1496,8 +1500,10 @@ nsHyperTextAccessible::CutText(PRInt32 aStartPos, PRInt32 aEndPos)
NS_IMETHODIMP NS_IMETHODIMP
nsHyperTextAccessible::DeleteText(PRInt32 aStartPos, PRInt32 aEndPos) nsHyperTextAccessible::DeleteText(PRInt32 aStartPos, PRInt32 aEndPos)
{ {
nsCOMPtr<nsIEditor> editor; if (IsDefunct())
GetAssociatedEditor(getter_AddRefs(editor)); return NS_ERROR_FAILURE;
nsCOMPtr<nsIEditor> editor = GetEditor();
NS_ENSURE_STATE(editor); NS_ENSURE_STATE(editor);
nsresult rv = SetSelectionRange(aStartPos, aEndPos); nsresult rv = SetSelectionRange(aStartPos, aEndPos);
@ -1509,8 +1515,10 @@ nsHyperTextAccessible::DeleteText(PRInt32 aStartPos, PRInt32 aEndPos)
NS_IMETHODIMP NS_IMETHODIMP
nsHyperTextAccessible::PasteText(PRInt32 aPosition) nsHyperTextAccessible::PasteText(PRInt32 aPosition)
{ {
nsCOMPtr<nsIEditor> editor; if (IsDefunct())
GetAssociatedEditor(getter_AddRefs(editor)); return NS_ERROR_FAILURE;
nsCOMPtr<nsIEditor> editor = GetEditor();
NS_ENSURE_STATE(editor); NS_ENSURE_STATE(editor);
nsresult rv = SetSelectionRange(aPosition, aPosition); nsresult rv = SetSelectionRange(aPosition, aPosition);
@ -1519,44 +1527,37 @@ nsHyperTextAccessible::PasteText(PRInt32 aPosition)
return editor->Paste(nsIClipboard::kGlobalClipboard); return editor->Paste(nsIClipboard::kGlobalClipboard);
} }
NS_IMETHODIMP already_AddRefed<nsIEditor>
nsHyperTextAccessible::GetAssociatedEditor(nsIEditor **aEditor) nsHyperTextAccessible::GetEditor() const
{ {
NS_ENSURE_ARG_POINTER(aEditor);
*aEditor = nsnull;
if (IsDefunct())
return NS_ERROR_FAILURE;
if (!mContent->HasFlag(NODE_IS_EDITABLE)) { if (!mContent->HasFlag(NODE_IS_EDITABLE)) {
// If we're inside an editable container, then return that container's editor // If we're inside an editable container, then return that container's editor
nsCOMPtr<nsIAccessible> ancestor, current = this; nsAccessible* ancestor = Parent();
while (NS_SUCCEEDED(current->GetParent(getter_AddRefs(ancestor))) && ancestor) { while (ancestor) {
nsRefPtr<nsHyperTextAccessible> ancestorTextAccessible; nsHyperTextAccessible* hyperText = ancestor->AsHyperText();
ancestor->QueryInterface(NS_GET_IID(nsHyperTextAccessible), if (hyperText) {
getter_AddRefs(ancestorTextAccessible));
if (ancestorTextAccessible) {
// Recursion will stop at container doc because it has its own impl // Recursion will stop at container doc because it has its own impl
// of GetAssociatedEditor() // of GetEditor()
return ancestorTextAccessible->GetAssociatedEditor(aEditor); return hyperText->GetEditor();
} }
current = ancestor;
ancestor = ancestor->Parent();
} }
return NS_OK;
return nsnull;
} }
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
nsCoreUtils::GetDocShellTreeItemFor(mContent); nsCoreUtils::GetDocShellTreeItemFor(mContent);
nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(docShellTreeItem)); nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(docShellTreeItem));
if (!editingSession) if (!editingSession)
return NS_OK; // No editing session interface return nsnull; // No editing session interface
NS_ENSURE_TRUE(mDoc, NS_ERROR_FAILURE);
nsIDocument* docNode = mDoc->GetDocumentNode();
NS_ENSURE_TRUE(docNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor;
return editingSession->GetEditorForWindow(docNode->GetWindow(), aEditor); nsIDocument* docNode = mDoc->GetDocumentNode();
editingSession->GetEditorForWindow(docNode->GetWindow(),
getter_AddRefs(editor));
return editor.forget();
} }
/** /**
@ -1770,8 +1771,7 @@ nsHyperTextAccessible::GetSelectionDOMRanges(PRInt16 aType,
nsCOMPtr<nsINode> startNode = GetNode(); nsCOMPtr<nsINode> startNode = GetNode();
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor = GetEditor();
GetAssociatedEditor(getter_AddRefs(editor));
if (editor) { if (editor) {
nsCOMPtr<nsIDOMElement> editorRoot; nsCOMPtr<nsIDOMElement> editorRoot;
editor->GetRootElement(getter_AddRefs(editorRoot)); editor->GetRootElement(getter_AddRefs(editorRoot));
@ -1789,13 +1789,11 @@ nsHyperTextAccessible::GetSelectionDOMRanges(PRInt16 aType,
// Remove collapsed ranges // Remove collapsed ranges
PRUint32 numRanges = aRanges->Length(); PRUint32 numRanges = aRanges->Length();
for (PRUint32 count = 0; count < numRanges; count ++) { for (PRUint32 idx = 0; idx < numRanges; idx ++) {
bool isCollapsed = false; if ((*aRanges)[idx]->Collapsed()) {
(*aRanges)[count]->GetCollapsed(&isCollapsed); aRanges->RemoveElementAt(idx);
if (isCollapsed) {
aRanges->RemoveElementAt(count);
--numRanges; --numRanges;
--count; --idx;
} }
} }
} }
@ -1837,29 +1835,19 @@ nsHyperTextAccessible::GetSelectionBounds(PRInt32 aSelectionNum,
nsRange* range = ranges[aSelectionNum]; nsRange* range = ranges[aSelectionNum];
// Get start point // Get start and end points.
nsCOMPtr<nsIDOMNode> startDOMNode; nsINode* startNode = range->GetStartParent();
range->GetStartContainer(getter_AddRefs(startDOMNode)); nsINode* endNode = range->GetEndParent();
nsCOMPtr<nsINode> startNode(do_QueryInterface(startDOMNode)); PRInt32 startOffset = range->StartOffset(), endOffset = range->EndOffset();
PRInt32 startOffset = 0;
range->GetStartOffset(&startOffset);
// Get end point // Make sure start is before end, by swapping DOM points. This occurs when
nsCOMPtr<nsIDOMNode> endDOMNode; // the user selects backwards in the text.
range->GetEndContainer(getter_AddRefs(endDOMNode)); PRInt32 rangeCompare = nsContentUtils::ComparePoints(endNode, endOffset,
nsCOMPtr<nsINode> endNode(do_QueryInterface(endDOMNode)); startNode, startOffset);
PRInt32 endOffset = 0; if (rangeCompare < 0) {
range->GetEndOffset(&endOffset); nsINode* tempNode = startNode;
startNode = endNode;
PRInt16 rangeCompareResult = 0; endNode = tempNode;
nsresult rv = range->CompareBoundaryPoints(nsIDOMRange::START_TO_END, range,
&rangeCompareResult);
NS_ENSURE_SUCCESS(rv, rv);
if (rangeCompareResult < 0) {
// Make sure start is before end, by swapping offsets
// This occurs when the user selects backwards in the text
startNode.swap(endNode);
PRInt32 tempOffset = startOffset; PRInt32 tempOffset = startOffset;
startOffset = endOffset; startOffset = endOffset;
endOffset = tempOffset; endOffset = tempOffset;
@ -2324,25 +2312,17 @@ nsHyperTextAccessible::RangeBoundToHypertextOffset(nsRange *aRange,
bool aIsStartHTOffset, bool aIsStartHTOffset,
PRInt32 *aHTOffset) PRInt32 *aHTOffset)
{ {
nsCOMPtr<nsIDOMNode> DOMNode; nsINode* node = nsnull;
PRInt32 nodeOffset = 0; PRInt32 nodeOffset = 0;
nsresult rv;
if (aIsStartBound) { if (aIsStartBound) {
rv = aRange->GetStartContainer(getter_AddRefs(DOMNode)); node = aRange->GetStartParent();
NS_ENSURE_SUCCESS(rv, rv); nodeOffset = aRange->StartOffset();
rv = aRange->GetStartOffset(&nodeOffset);
NS_ENSURE_SUCCESS(rv, rv);
} else { } else {
rv = aRange->GetEndContainer(getter_AddRefs(DOMNode)); node = aRange->GetEndParent();
NS_ENSURE_SUCCESS(rv, rv); nodeOffset = aRange->EndOffset();
rv = aRange->GetEndOffset(&nodeOffset);
NS_ENSURE_SUCCESS(rv, rv);
} }
nsCOMPtr<nsINode> node(do_QueryInterface(DOMNode));
nsAccessible *startAcc = nsAccessible *startAcc =
DOMPointToHypertextOffset(node, nodeOffset, aHTOffset); DOMPointToHypertextOffset(node, nodeOffset, aHTOffset);
@ -2354,7 +2334,7 @@ nsHyperTextAccessible::RangeBoundToHypertextOffset(nsRange *aRange,
// nsHyperTextAccessible // nsHyperTextAccessible
nsresult nsresult
nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode, nsHyperTextAccessible::GetSpellTextAttribute(nsINode* aNode,
PRInt32 aNodeOffset, PRInt32 aNodeOffset,
PRInt32 *aHTStartOffset, PRInt32 *aHTStartOffset,
PRInt32 *aHTEndOffset, PRInt32 *aHTEndOffset,
@ -2367,25 +2347,19 @@ nsHyperTextAccessible::GetSpellTextAttribute(nsIDOMNode *aNode,
if (!rangeCount) if (!rangeCount)
return NS_OK; return NS_OK;
nsCOMPtr<nsIDOMNode> DOMNode = do_QueryInterface(aNode);
for (PRUint32 index = 0; index < rangeCount; index++) { for (PRUint32 index = 0; index < rangeCount; index++) {
nsRange* range = ranges[index]; nsRange* range = ranges[index];
PRInt16 result; PRInt16 result;
nsresult rv = range->ComparePoint(aNode, aNodeOffset, &result); nsresult rv = range->ComparePoint(DOMNode, aNodeOffset, &result);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// ComparePoint checks boundary points, but we need to check that // ComparePoint checks boundary points, but we need to check that
// text at aNodeOffset is inside the range. // text at aNodeOffset is inside the range.
// See also bug 460690. // See also bug 460690.
if (result == 0) { if (result == 0) {
nsCOMPtr<nsIDOMNode> end; if (aNode == range->GetEndParent() && aNodeOffset == range->EndOffset())
rv = range->GetEndContainer(getter_AddRefs(end));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 endOffset;
rv = range->GetEndOffset(&endOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (aNode == end && aNodeOffset == endOffset) {
result = 1; result = 1;
}
} }
if (result == 1) { // range is before point if (result == 1) { // range is before point

View File

@ -264,6 +264,14 @@ public:
return GetChildAt(GetChildIndexAtOffset(aOffset)); return GetChildAt(GetChildIndexAtOffset(aOffset));
} }
//////////////////////////////////////////////////////////////////////////////
// EditableTextAccessible
/**
* Return the editor associated with the accessible.
*/
virtual already_AddRefed<nsIEditor> GetEditor() const;
protected: protected:
// nsHyperTextAccessible // nsHyperTextAccessible
@ -409,7 +417,7 @@ protected:
* @param aEndOffset [in, out] the end offset * @param aEndOffset [in, out] the end offset
* @param aAttributes [out, optional] result attributes * @param aAttributes [out, optional] result attributes
*/ */
nsresult GetSpellTextAttribute(nsIDOMNode *aNode, PRInt32 aNodeOffset, nsresult GetSpellTextAttribute(nsINode* aNode, PRInt32 aNodeOffset,
PRInt32 *aStartOffset, PRInt32 *aStartOffset,
PRInt32 *aEndOffset, PRInt32 *aEndOffset,
nsIPersistentProperties *aAttributes); nsIPersistentProperties *aAttributes);

View File

@ -273,8 +273,7 @@ nsXFormsEditableAccessible::NativeState()
} }
} }
nsCOMPtr<nsIEditor> editor; nsCOMPtr<nsIEditor> editor = GetEditor();
GetAssociatedEditor(getter_AddRefs(editor));
NS_ENSURE_TRUE(editor, state); NS_ENSURE_TRUE(editor, state);
PRUint32 flags; PRUint32 flags;
editor->GetFlags(&flags); editor->GetFlags(&flags);
@ -286,11 +285,14 @@ nsXFormsEditableAccessible::NativeState()
return state; return state;
} }
NS_IMETHODIMP already_AddRefed<nsIEditor>
nsXFormsEditableAccessible::GetAssociatedEditor(nsIEditor **aEditor) nsXFormsEditableAccessible::GetEditor() const
{ {
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mContent)); nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mContent));
return sXFormsService->GetEditor(DOMNode, aEditor);
nsCOMPtr<nsIEditor> editor;
sXFormsService->GetEditor(DOMNode, getter_AddRefs(editor));
return editor.forget();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -144,8 +144,8 @@ class nsXFormsEditableAccessible : public nsXFormsAccessible
public: public:
nsXFormsEditableAccessible(nsIContent* aContent, nsDocAccessible* aDoc); nsXFormsEditableAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
// nsIAccessibleEditableText // nsHyperTextAccessible
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor); virtual already_AddRefed<nsIEditor> GetEditor() const;
// nsAccessible // nsAccessible
virtual PRUint64 NativeState(); virtual PRUint64 NativeState();

View File

@ -850,14 +850,17 @@ nsXULTextFieldAccessible::CanHaveAnonChildren()
return false; return false;
} }
NS_IMETHODIMP nsXULTextFieldAccessible::GetAssociatedEditor(nsIEditor **aEditor) already_AddRefed<nsIEditor>
nsXULTextFieldAccessible::GetEditor() const
{ {
*aEditor = nsnull;
nsCOMPtr<nsIContent> inputField = GetInputField(); nsCOMPtr<nsIContent> inputField = GetInputField();
nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(inputField)); nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(inputField));
NS_ENSURE_TRUE(editableElt, NS_ERROR_FAILURE); if (!editableElt)
return editableElt->GetEditor(aEditor); return nsnull;
nsCOMPtr<nsIEditor> editor;
editableElt->GetEditor(getter_AddRefs(editor));
return editor.forget();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -260,8 +260,8 @@ public:
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 index); NS_IMETHOD DoAction(PRUint8 index);
// nsIAccessibleEditableText // nsHyperTextAccessible
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor); virtual already_AddRefed<nsIEditor> GetEditor() const;
// nsAccessible // nsAccessible
virtual void ApplyARIAState(PRUint64* aState); virtual void ApplyARIAState(PRUint64* aState);

View File

@ -613,9 +613,9 @@ function getNodePrettyName(aNode)
function getObjAddress(aObj) function getObjAddress(aObj)
{ {
var exp = /native\s*@\s*(0x[a-f0-9]+)/g; var exp = /native\s*@\s*(0x[a-f0-9]+)/g;
var match = exp.exec(aObj.valueOf()); var match = exp.exec(aObj.toString());
if (match) if (match)
return match[1]; return match[1];
return aObj.valueOf(); return aObj.toString();
} }

View File

@ -15,41 +15,46 @@
<script type="application/javascript"> <script type="application/javascript">
function doTest() function doTest()
{ {
var accessible = getApplicationAccessible(); var accessible = getApplicationAccessible();
if (!accessible) { if (!accessible) {
SimpleTest.finish(); SimpleTest.finish();
return; return;
} }
// nsIAccessible::name var bundleServ =
var bundleServ = Components.classes["@mozilla.org/intl/stringbundle;1"] Components.classes["@mozilla.org/intl/stringbundle;1"].
.getService(Components.interfaces.nsIStringBundleService); getService(Components.interfaces.nsIStringBundleService);
var bundle = bundleServ.createBundle("chrome://branding/locale/brand.properties"); var brandBundle =
bundleServ.createBundle("chrome://branding/locale/brand.properties");
var applicationName = ""; var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
getService(Components.interfaces.nsIXULAppInfo);
// nsIAccessible::name
var applicationName = "";
if (LINUX || SOLARIS) {
applicationName = appInfo.name;
} else {
try { try {
applicationName = bundle.GetStringFromName("brandShortName"); applicationName = brandBundle.GetStringFromName("brandShortName");
} catch(e) { } catch(e) {
} }
if (applicationName == "") if (applicationName == "")
applicationName = "Gecko based application"; applicationName = "Gecko based application";
}
is (accessible.name, applicationName, "wrong application accessible name");
is (accessible.name, applicationName, "wrong application accessible name"); // nsIAccessibleApplication
is(accessible.appName, appInfo.name, "Wrong application name");
is(accessible.appVersion, appInfo.version, "Wrong application version");
is(accessible.platformName, "Gecko", "Wrong platform name");
is(accessible.platformVersion, appInfo.platformVersion,
"Wrong platform version");
// nsIAccessibleApplication SimpleTest.finish();
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
getService(Components.interfaces.nsIXULAppInfo);
is(accessible.appName, appInfo.name, "Wrong application name");
is(accessible.appVersion, appInfo.version, "Wrong application version");
is(accessible.platformName, "Gecko", "Wrong platform name");
is(accessible.platformVersion, appInfo.platformVersion,
"Wrong platform version");
SimpleTest.finish();
} }
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest); addA11yLoadEvent(doTest);
</script> </script>

View File

@ -304,12 +304,20 @@ function eventQueue(aEventType)
// Start processing of next invoker. // Start processing of next invoker.
invoker = this.getNextInvoker(); invoker = this.getNextInvoker();
this.setEventHandler(invoker);
if (gLogger.isEnabled()) { if (gLogger.isEnabled()) {
gLogger.logToConsole("Event queue: \n invoke: " + invoker.getID()); gLogger.logToConsole("Event queue: \n invoke: " + invoker.getID());
gLogger.logToDOM("EQ: invoke: " + invoker.getID(), true); gLogger.logToDOM("EQ: invoke: " + invoker.getID(), true);
} }
this.setEventHandler(invoker); var infoText = "Invoke the '" + invoker.getID() + "' test { ";
for (var idx = 0; idx < this.mEventSeq.length; idx++) {
infoText += this.isEventUnexpected(idx) ? "un" : "";
infoText += "expected '" + this.getEventTypeAsString(idx) + "' event; ";
}
infoText += " }";
info(infoText);
if (invoker.invoke() == INVOKER_ACTION_FAILED) { if (invoker.invoke() == INVOKER_ACTION_FAILED) {
// Invoker failed to prepare action, fail and finish tests. // Invoker failed to prepare action, fail and finish tests.

View File

@ -384,14 +384,11 @@
{ {
if (SEAMONKEY) { if (SEAMONKEY) {
todo(false, "Skipping this test on SeaMonkey ftb. (Bug 718237)"); todo(false, "Skipping this test on SeaMonkey ftb. (Bug 718237)");
shutdownAutoComplete();
SimpleTest.finish(); SimpleTest.finish();
return; return;
} }
// register 'test-a11y-search' autocomplete search
initAutoComplete([ "hello", "hi" ],
[ "Beep beep'm beep beep yeah", "Baby you can drive my car" ]);
gInitQueue = new eventQueue(); gInitQueue = new eventQueue();
gInitQueue.push(new loadFormAutoComplete("iframe")); gInitQueue.push(new loadFormAutoComplete("iframe"));
gInitQueue.push(new initFormAutoCompleteBy("iframe", "hello")); gInitQueue.push(new initFormAutoCompleteBy("iframe", "hello"));
@ -461,6 +458,12 @@
} }
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
// Register 'test-a11y-search' autocomplete search.
// XPFE AutoComplete needs to register early.
initAutoComplete([ "hello", "hi" ],
[ "Beep beep'm beep beep yeah", "Baby you can drive my car" ]);
addA11yLoadEvent(initTests); addA11yLoadEvent(initTests);
]]> ]]>
</script> </script>

View File

@ -35,10 +35,6 @@
var gQueue = null; var gQueue = null;
function doTest() function doTest()
{ {
// register 'test-a11y-search' autocomplete search
initAutoComplete([ "hello", "hi" ],
[ "Beep beep'm beep beep yeah", "Baby you can drive my car" ]);
gQueue = new eventQueue(); gQueue = new eventQueue();
gQueue.push(new openCombobox("menulist")); gQueue.push(new openCombobox("menulist"));
@ -73,6 +69,12 @@
} }
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
// Register 'test-a11y-search' autocomplete search.
// XPFE AutoComplete needs to register early.
initAutoComplete([ "hello", "hi" ],
[ "Beep beep'm beep beep yeah", "Baby you can drive my car" ]);
addA11yLoadEvent(doTest); addA11yLoadEvent(doTest);
]]> ]]>
</script> </script>

View File

@ -181,7 +181,11 @@ const ContentPanning = {
case 'click': case 'click':
evt.stopPropagation(); evt.stopPropagation();
evt.preventDefault(); evt.preventDefault();
evt.target.removeEventListener('click', this, true);
let target = evt.target;
let view = target.ownerDocument ? target.ownerDocument.defaultView
: target;
view.removeEventListener('click', this, true, true);
break; break;
} }
}, },
@ -190,16 +194,24 @@ const ContentPanning = {
onTouchStart: function cp_onTouchStart(evt) { onTouchStart: function cp_onTouchStart(evt) {
this.dragging = true; this.dragging = true;
this.panning = false;
let oldTarget = this.target;
[this.target, this.scrollCallback] = this.getPannable(evt.target);
// If there is a pan animation running (from a previous pan gesture) and // If there is a pan animation running (from a previous pan gesture) and
// the user touch back the screen, stop this animation immediatly and // the user touch back the screen, stop this animation immediatly and
// prevent the possible click action. // prevent the possible click action if the touch happens on the same
// target.
this.preventNextClick = false;
if (KineticPanning.active) { if (KineticPanning.active) {
KineticPanning.stop(); KineticPanning.stop();
this.preventNextClick = true;
if (oldTarget && oldTarget == this.target)
this.preventNextClick = true;
} }
this.scrollCallback = this.getPannable(evt.originalTarget);
this.position.set(evt.screenX, evt.screenY); this.position.set(evt.screenX, evt.screenY);
KineticPanning.record(new Point(0, 0), evt.timeStamp); KineticPanning.record(new Point(0, 0), evt.timeStamp);
}, },
@ -211,14 +223,15 @@ const ContentPanning = {
this.onTouchMove(evt); this.onTouchMove(evt);
let pan = KineticPanning.isPan();
let click = evt.detail; let click = evt.detail;
if (click && (pan || this.preventNextClick)) if (this.target && click && (this.panning || this.preventNextClick)) {
evt.target.addEventListener('click', this, true); let target = this.target;
let view = target.ownerDocument ? target.ownerDocument.defaultView
: target;
view.addEventListener('click', this, true, true);
}
this.preventNextClick = false; if (this.panning)
if (pan)
KineticPanning.start(this); KineticPanning.start(this);
}, },
@ -232,6 +245,13 @@ const ContentPanning = {
KineticPanning.record(delta, evt.timeStamp); KineticPanning.record(delta, evt.timeStamp);
this.scrollCallback(delta.scale(-1)); this.scrollCallback(delta.scale(-1));
// If a pan action happens, cancel the active state of the
// current target.
if (!this.panning && KineticPanning.isPan()) {
this.panning = true;
this._resetActive();
}
}, },
@ -249,7 +269,7 @@ const ContentPanning = {
getPannable: function cp_getPannable(node) { getPannable: function cp_getPannable(node) {
if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML') if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML')
return null; return [null, null];
let content = node.ownerDocument.defaultView; let content = node.ownerDocument.defaultView;
while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) { while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
@ -266,12 +286,12 @@ const ContentPanning = {
let isScroll = (overflow.indexOf('scroll') != -1); let isScroll = (overflow.indexOf('scroll') != -1);
if (isScroll || isAuto) if (isScroll || isAuto)
return this._generateCallback(node); return [node, this._generateCallback(node)];
node = node.parentNode; node = node.parentNode;
} }
return this._generateCallback(content); return [content, this._generateCallback(content)];
}, },
_generateCallback: function cp_generateCallback(content) { _generateCallback: function cp_generateCallback(content) {
@ -290,6 +310,19 @@ const ContentPanning = {
} }
} }
return scroll; return scroll;
},
get _domUtils() {
delete this._domUtils;
return this._domUtils = Cc['@mozilla.org/inspector/dom-utils;1']
.getService(Ci.inIDOMUtils);
},
_resetActive: function cp_resetActive() {
let root = this.target.ownerDocument || this.target.document;
const kStateActive = 0x00000001;
this._domUtils.setContentState(root.documentElement, kStateActive);
} }
}; };
@ -370,6 +403,7 @@ const KineticPanning = {
return; return;
this.momentums = []; this.momentums = [];
this.distance.set(0, 0);
this.target.onKineticEnd(); this.target.onKineticEnd();
this.target = null; this.target = null;
@ -378,23 +412,24 @@ const KineticPanning = {
momentums: [], momentums: [],
record: function kp_record(delta, timestamp) { record: function kp_record(delta, timestamp) {
this.momentums.push({ 'time': timestamp, 'dx' : delta.x, 'dy' : delta.y }); this.momentums.push({ 'time': timestamp, 'dx' : delta.x, 'dy' : delta.y });
this.distance.add(delta.x, delta.y);
}, },
isPan: function cp_isPan() { get threshold() {
let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor) let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils) .getInterface(Ci.nsIDOMWindowUtils)
.displayDPI; .displayDPI;
let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi; let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
let deltaX = 0; delete this.threshold;
let deltaY = 0; return this.threshold = threshold;
let start = this.momentums[0].time; },
return this.momentums.slice(1).some(function(momentum) {
deltaX += momentum.dx; distance: new Point(0, 0),
deltaY += momentum.dy; isPan: function cp_isPan() {
return (Math.abs(deltaX) > threshold) || (Math.abs(deltaY) > threshold); return (Math.abs(this.distance.x) > this.threshold ||
}); Math.abs(this.distance.y) > this.threshold);
}, },
_startAnimation: function kp_startAnimation() { _startAnimation: function kp_startAnimation() {

View File

@ -1563,49 +1563,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
gHomeButton.updateTooltip(homeButton); gHomeButton.updateTooltip(homeButton);
gHomeButton.updatePersonalToolbarStyle(homeButton); gHomeButton.updatePersonalToolbarStyle(homeButton);
#ifdef HAVE_SHELL_SERVICE
// Perform default browser checking (after window opens).
var shell = getShellService();
if (shell) {
#ifdef DEBUG
var shouldCheck = false;
#else
var shouldCheck = shell.shouldCheckDefaultBrowser;
#endif
var willRecoverSession = false;
try {
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
getService(Ci.nsISessionStartup);
willRecoverSession =
(ss.sessionType == Ci.nsISessionStartup.RECOVER_SESSION);
}
catch (ex) { /* never mind; suppose SessionStore is broken */ }
if (shouldCheck && !shell.isDefaultBrowser(true) && !willRecoverSession) {
// Delay the set-default-browser prompt so it doesn't block
// initialisation of the session store service.
setTimeout(function () {
var brandBundle = document.getElementById("bundle_brand");
var shellBundle = document.getElementById("bundle_shell");
var brandShortName = brandBundle.getString("brandShortName");
var promptTitle = shellBundle.getString("setDefaultBrowserTitle");
var promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage",
[brandShortName]);
var checkboxLabel = shellBundle.getFormattedString("setDefaultBrowserDontAsk",
[brandShortName]);
var checkEveryTime = { value: shouldCheck };
var ps = Services.prompt;
var rv = ps.confirmEx(window, promptTitle, promptMessage,
ps.STD_YES_NO_BUTTONS,
null, null, null, checkboxLabel, checkEveryTime);
if (rv == 0)
shell.setDefaultBrowser(true, false);
shell.shouldCheckDefaultBrowser = checkEveryTime.value;
}, 0);
}
}
#endif
// BiDi UI // BiDi UI
gBidiUI = isBidiEnabled(); gBidiUI = isBidiEnabled();
if (gBidiUI) { if (gBidiUI) {
@ -3989,10 +3946,22 @@ var FullScreen = {
} }
}, },
exitDomFullScreen : function(e) { exitDomFullScreen : function() {
document.mozCancelFullScreen(); document.mozCancelFullScreen();
}, },
handleEvent: function (event) {
switch (event.type) {
case "deactivate":
// We must call exitDomFullScreen asynchronously, since "deactivate" is
// dispatched in the middle of the focus manager's window lowering code,
// and the focus manager gets confused if we exit fullscreen mode in the
// middle of window lowering. See bug 729872.
setTimeout(this.exitDomFullScreen.bind(this), 0);
break;
}
},
enterDomFullScreen : function(event) { enterDomFullScreen : function(event) {
if (!document.mozFullScreen) { if (!document.mozFullScreen) {
return; return;
@ -4039,7 +4008,7 @@ var FullScreen = {
// Exit DOM full-screen mode when the browser window loses focus (ALT+TAB, etc). // Exit DOM full-screen mode when the browser window loses focus (ALT+TAB, etc).
if (gPrefService.getBoolPref("full-screen-api.exit-on-deactivate")) { if (gPrefService.getBoolPref("full-screen-api.exit-on-deactivate")) {
window.addEventListener("deactivate", this.exitDomFullScreen, true); window.addEventListener("deactivate", this);
} }
// Cancel any "hide the toolbar" animation which is in progress, and make // Cancel any "hide the toolbar" animation which is in progress, and make
@ -4074,7 +4043,7 @@ var FullScreen = {
gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen); gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen); gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen); gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
window.removeEventListener("deactivate", this.exitDomFullScreen, true); window.removeEventListener("deactivate", this);
} }
}, },
@ -5362,6 +5331,7 @@ function setToolbarVisibility(toolbar, isVisible) {
var TabsOnTop = { var TabsOnTop = {
init: function TabsOnTop_init() { init: function TabsOnTop_init() {
this._initialized = true;
this.syncUI(); this.syncUI();
Services.prefs.addObserver(this._prefName, this, false); Services.prefs.addObserver(this._prefName, this, false);
}, },
@ -5375,6 +5345,9 @@ var TabsOnTop = {
}, },
syncUI: function () { syncUI: function () {
if (!this._initialized)
return;
let userEnabled = Services.prefs.getBoolPref(this._prefName); let userEnabled = Services.prefs.getBoolPref(this._prefName);
let enabled = userEnabled && gBrowser.tabContainer.visible; let enabled = userEnabled && gBrowser.tabContainer.visible;
@ -6121,103 +6094,114 @@ function charsetLoadListener(event) {
} }
} }
/* Begin Page Style Functions */
function getAllStyleSheets(frameset) {
var styleSheetsArray = Array.slice(frameset.document.styleSheets);
for (let i = 0; i < frameset.frames.length; i++) {
let frameSheets = getAllStyleSheets(frameset.frames[i]);
styleSheetsArray = styleSheetsArray.concat(frameSheets);
}
return styleSheetsArray;
}
function stylesheetFillPopup(menuPopup) { var gPageStyleMenu = {
var noStyle = menuPopup.firstChild;
var persistentOnly = noStyle.nextSibling;
var sep = persistentOnly.nextSibling;
while (sep.nextSibling)
menuPopup.removeChild(sep.nextSibling);
var styleSheets = getAllStyleSheets(window.content); getAllStyleSheets: function (frameset) {
var currentStyleSheets = {}; var styleSheetsArray = Array.slice(frameset.document.styleSheets);
var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled; for (let i = 0; i < frameset.frames.length; i++) {
var haveAltSheets = false; let frameSheets = this.getAllStyleSheets(frameset.frames[i]);
var altStyleSelected = false; styleSheetsArray = styleSheetsArray.concat(frameSheets);
}
return styleSheetsArray;
},
for (let i = 0; i < styleSheets.length; ++i) { stylesheetFillPopup: function (menuPopup) {
let currentStyleSheet = styleSheets[i]; var noStyle = menuPopup.firstChild;
var persistentOnly = noStyle.nextSibling;
var sep = persistentOnly.nextSibling;
while (sep.nextSibling)
menuPopup.removeChild(sep.nextSibling);
if (!currentStyleSheet.title) var styleSheets = this.getAllStyleSheets(window.content);
continue; var currentStyleSheets = {};
var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled;
var haveAltSheets = false;
var altStyleSelected = false;
// Skip any stylesheets whose media attribute doesn't match. for (let i = 0; i < styleSheets.length; ++i) {
if (currentStyleSheet.media.length > 0) { let currentStyleSheet = styleSheets[i];
let mediaQueryList = currentStyleSheet.media.mediaText;
if (!window.content.matchMedia(mediaQueryList).matches) if (!currentStyleSheet.title)
continue; continue;
// Skip any stylesheets whose media attribute doesn't match.
if (currentStyleSheet.media.length > 0) {
let mediaQueryList = currentStyleSheet.media.mediaText;
if (!window.content.matchMedia(mediaQueryList).matches)
continue;
}
if (!currentStyleSheet.disabled)
altStyleSelected = true;
haveAltSheets = true;
let lastWithSameTitle = null;
if (currentStyleSheet.title in currentStyleSheets)
lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
if (!lastWithSameTitle) {
let menuItem = document.createElement("menuitem");
menuItem.setAttribute("type", "radio");
menuItem.setAttribute("label", currentStyleSheet.title);
menuItem.setAttribute("data", currentStyleSheet.title);
menuItem.setAttribute("checked", !currentStyleSheet.disabled && !styleDisabled);
menuPopup.appendChild(menuItem);
currentStyleSheets[currentStyleSheet.title] = menuItem;
} else if (currentStyleSheet.disabled) {
lastWithSameTitle.removeAttribute("checked");
}
} }
if (!currentStyleSheet.disabled) noStyle.setAttribute("checked", styleDisabled);
altStyleSelected = true; persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled);
persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false;
sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
return true;
},
haveAltSheets = true; stylesheetInFrame: function (frame, title) {
return Array.some(frame.document.styleSheets,
function (stylesheet) stylesheet.title == title);
},
let lastWithSameTitle = null; stylesheetSwitchFrame: function (frame, title) {
if (currentStyleSheet.title in currentStyleSheets) var docStyleSheets = frame.document.styleSheets;
lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
if (!lastWithSameTitle) { for (let i = 0; i < docStyleSheets.length; ++i) {
let menuItem = document.createElement("menuitem"); let docStyleSheet = docStyleSheets[i];
menuItem.setAttribute("type", "radio");
menuItem.setAttribute("label", currentStyleSheet.title); if (title == "_nostyle")
menuItem.setAttribute("data", currentStyleSheet.title); docStyleSheet.disabled = true;
menuItem.setAttribute("checked", !currentStyleSheet.disabled && !styleDisabled); else if (docStyleSheet.title)
menuPopup.appendChild(menuItem); docStyleSheet.disabled = (docStyleSheet.title != title);
currentStyleSheets[currentStyleSheet.title] = menuItem; else if (docStyleSheet.disabled)
} else if (currentStyleSheet.disabled) { docStyleSheet.disabled = false;
lastWithSameTitle.removeAttribute("checked");
} }
} },
noStyle.setAttribute("checked", styleDisabled); stylesheetSwitchAll: function (frameset, title) {
persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled); if (!title || title == "_nostyle" || this.stylesheetInFrame(frameset, title))
persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false; this.stylesheetSwitchFrame(frameset, title);
sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
return true;
}
function stylesheetInFrame(frame, title) { for (let i = 0; i < frameset.frames.length; i++)
return Array.some(frame.document.styleSheets, this.stylesheetSwitchAll(frameset.frames[i], title);
function (stylesheet) stylesheet.title == title); },
}
function stylesheetSwitchFrame(frame, title) { setStyleDisabled: function (disabled) {
var docStyleSheets = frame.document.styleSheets; getMarkupDocumentViewer().authorStyleDisabled = disabled;
},
};
for (let i = 0; i < docStyleSheets.length; ++i) { /* Legacy global page-style functions */
let docStyleSheet = docStyleSheets[i]; var getAllStyleSheets = gPageStyleMenu.getAllStyleSheets;
var stylesheetFillPopup = gPageStyleMenu.stylesheetFillPopup;
var stylesheetInFrame = gPageStyleMenu.stylesheetInFrame;
var stylesheetSwitchFrame = gPageStyleMenu.stylesheetSwitchFrame;
var stylesheetSwitchAll = gPageStyleMenu.stylesheetSwitchAll;
var setStyleDisabled = gPageStyleMenu.setStyleDisabled;
if (title == "_nostyle")
docStyleSheet.disabled = true;
else if (docStyleSheet.title)
docStyleSheet.disabled = (docStyleSheet.title != title);
else if (docStyleSheet.disabled)
docStyleSheet.disabled = false;
}
}
function stylesheetSwitchAll(frameset, title) {
if (!title || title == "_nostyle" || stylesheetInFrame(frameset, title))
stylesheetSwitchFrame(frameset, title);
for (let i = 0; i < frameset.frames.length; i++)
stylesheetSwitchAll(frameset.frames[i], title);
}
function setStyleDisabled(disabled) {
getMarkupDocumentViewer().authorStyleDisabled = disabled;
}
/* End of the Page Style functions */
var BrowserOffline = { var BrowserOffline = {
_inited: false, _inited: false,

View File

@ -3,7 +3,6 @@
*/ */
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://services-sync/main.js"); Cu.import("resource://services-sync/main.js");
let gTests = [ { let gTests = [ {

View File

@ -428,6 +428,49 @@ BrowserGlue.prototype = {
let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL"); let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL");
Services.telemetry.getHistogramById("FX_KEYWORD_URL_USERSET").add(keywordURLUserSet); Services.telemetry.getHistogramById("FX_KEYWORD_URL_USERSET").add(keywordURLUserSet);
// Perform default browser checking.
var shell;
try {
shell = Components.classes["@mozilla.org/browser/shell-service;1"]
.getService(Components.interfaces.nsIShellService);
} catch (e) { }
if (shell) {
#ifdef DEBUG
var shouldCheck = false;
#else
var shouldCheck = shell.shouldCheckDefaultBrowser;
#endif
var willRecoverSession = false;
try {
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
getService(Ci.nsISessionStartup);
willRecoverSession =
(ss.sessionType == Ci.nsISessionStartup.RECOVER_SESSION);
}
catch (ex) { /* never mind; suppose SessionStore is broken */ }
if (shouldCheck && !shell.isDefaultBrowser(true) && !willRecoverSession) {
Services.tm.mainThread.dispatch(function() {
var brandBundle = win.document.getElementById("bundle_brand");
var shellBundle = win.document.getElementById("bundle_shell");
var brandShortName = brandBundle.getString("brandShortName");
var promptTitle = shellBundle.getString("setDefaultBrowserTitle");
var promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage",
[brandShortName]);
var checkboxLabel = shellBundle.getFormattedString("setDefaultBrowserDontAsk",
[brandShortName]);
var checkEveryTime = { value: shouldCheck };
var ps = Services.prompt;
var rv = ps.confirmEx(win, promptTitle, promptMessage,
ps.STD_YES_NO_BUTTONS,
null, null, null, checkboxLabel, checkEveryTime);
if (rv == 0)
shell.setDefaultBrowser(true, false);
shell.shouldCheckDefaultBrowser = checkEveryTime.value;
}, Ci.nsIThread.DISPATCH_NORMAL);
}
}
}, },
_onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) { _onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {

View File

@ -167,73 +167,33 @@ PlacesViewBase.prototype = {
}, },
_cleanPopup: function PVB_cleanPopup(aPopup) { _cleanPopup: function PVB_cleanPopup(aPopup) {
// Remove places popup children and update markers to keep track of // Remove Places nodes from the popup.
// their indices. let child = aPopup._startMarker;
let start = aPopup._startMarker != -1 ? aPopup._startMarker + 1 : 0; while (child.nextSibling != aPopup._endMarker) {
let end = aPopup._endMarker != -1 ? aPopup._endMarker : if (child.nextSibling._placesNode)
aPopup.childNodes.length; aPopup.removeChild(child.nextSibling);
let items = []; else
child = child.nextSibling;
// Automatically adjust the start and the end markers.
let firstNonStaticNodeFound = false;
for (let i = start; i < end; ++i) {
let item = aPopup.childNodes[i];
if (item.getAttribute("builder") == "end") {
// we need to do this for menus that have static content at the end but
// are initially empty, eg. the history menu, we need to know where to
// start inserting new items.
aPopup._endMarker = i;
break;
}
if (item._placesNode) {
items.push(item);
firstNonStaticNodeFound = true;
}
else {
// This is static content.
if (!firstNonStaticNodeFound) {
// We are at the beginning of the popup, in static content.
// The markers are initialized in menu.xml, in the base binding.
aPopup._startMarker++;
}
else {
// We are at the end of the popup, after places nodes
aPopup._endMarker = i;
break;
}
}
}
for (let i = 0; i < items.length; ++i) {
aPopup.removeChild(items[i]);
if (aPopup._endMarker != -1)
aPopup._endMarker--;
} }
}, },
_rebuildPopup: function PVB__rebuildPopup(aPopup) { _rebuildPopup: function PVB__rebuildPopup(aPopup) {
this._cleanPopup(aPopup);
let resultNode = aPopup._placesNode; let resultNode = aPopup._placesNode;
if (!resultNode.containerOpen) if (!resultNode.containerOpen)
return; return;
if (resultNode._feedURI) { if (resultNode._feedURI) {
aPopup.removeAttribute("emptyplacesresult"); this._setEmptyPopupStatus(aPopup, false);
if (aPopup._emptyMenuItem) {
aPopup._emptyMenuItem.hidden = true;
}
aPopup._built = true; aPopup._built = true;
this._populateLivemarkPopup(aPopup); this._populateLivemarkPopup(aPopup);
return; return;
} }
this._cleanPopup(aPopup);
let cc = resultNode.childCount; let cc = resultNode.childCount;
if (cc > 0) { if (cc > 0) {
aPopup.removeAttribute("emptyplacesresult"); this._setEmptyPopupStatus(aPopup, false);
if (aPopup._emptyMenuItem)
aPopup._emptyMenuItem.hidden = true;
for (let i = 0; i < cc; ++i) { for (let i = 0; i < cc; ++i) {
let child = resultNode.getChild(i); let child = resultNode.getChild(i);
@ -241,11 +201,7 @@ PlacesViewBase.prototype = {
} }
} }
else { else {
aPopup.setAttribute("emptyplacesresult", "true"); this._setEmptyPopupStatus(aPopup, true);
// This menu is empty. If there is no static content, add
// an element to show it is empty.
if (aPopup._startMarker == -1 && aPopup._endMarker == -1)
this._showEmptyMenuItem(aPopup);
} }
aPopup._built = true; aPopup._built = true;
}, },
@ -260,17 +216,28 @@ PlacesViewBase.prototype = {
aChild.parentNode.removeChild(aChild); aChild.parentNode.removeChild(aChild);
}, },
_showEmptyMenuItem: function PVB__showEmptyMenuItem(aPopup) { _setEmptyPopupStatus:
if (aPopup._emptyMenuItem) { function PVB__setEmptyPopupStatus(aPopup, aEmpty) {
aPopup._emptyMenuItem.hidden = false; if (!aPopup._emptyMenuitem) {
return; let label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder");
aPopup._emptyMenuitem = document.createElement("menuitem");
aPopup._emptyMenuitem.setAttribute("label", label);
aPopup._emptyMenuitem.setAttribute("disabled", true);
} }
let label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder"); if (aEmpty) {
aPopup._emptyMenuItem = document.createElement("menuitem"); aPopup.setAttribute("emptyplacesresult", "true");
aPopup._emptyMenuItem.setAttribute("label", label); // Don't add the menuitem if there is static content.
aPopup._emptyMenuItem.setAttribute("disabled", true); if (!aPopup._startMarker.previousSibling &&
aPopup.appendChild(aPopup._emptyMenuItem); !aPopup._endMarker.nextSibling)
aPopup.insertBefore(aPopup._emptyMenuitem, aPopup._endMarker);
}
else {
aPopup.removeAttribute("emptyplacesresult");
try {
aPopup.removeChild(aPopup._emptyMenuitem);
} catch (ex) {}
}
}, },
_createMenuItemForPlacesNode: _createMenuItemForPlacesNode:
@ -308,6 +275,12 @@ PlacesViewBase.prototype = {
function (aStatus, aLivemark) { function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) { if (Components.isSuccessCode(aStatus)) {
element.setAttribute("livemark", "true"); element.setAttribute("livemark", "true");
#ifdef XP_MACOSX
// OS X native menubar doesn't track list-style-images since
// it doesn't have a frame (bug 733415). Thus enforce updating.
element.setAttribute("image", "");
element.removeAttribute("image");
#endif
// Set an expando on the node, controller will use it to build // Set an expando on the node, controller will use it to build
// its metadata. // its metadata.
aPlacesNode._feedURI = aLivemark.feedURI; aPlacesNode._feedURI = aLivemark.feedURI;
@ -319,12 +292,11 @@ PlacesViewBase.prototype = {
let popup = document.createElement("menupopup"); let popup = document.createElement("menupopup");
popup._placesNode = PlacesUtils.asContainer(aPlacesNode); popup._placesNode = PlacesUtils.asContainer(aPlacesNode);
if (this._nativeView) {
popup._startMarker = -1; if (!this._nativeView) {
popup._endMarker = -1;
}
else
popup.setAttribute("placespopup", "true"); popup.setAttribute("placespopup", "true");
}
#ifdef XP_MACOSX #ifdef XP_MACOSX
// No context menu on mac. // No context menu on mac.
popup.setAttribute("context", "placesContext"); popup.setAttribute("context", "placesContext");
@ -354,26 +326,8 @@ PlacesViewBase.prototype = {
_insertNewItemToPopup: _insertNewItemToPopup:
function PVB__insertNewItemToPopup(aNewChild, aPopup, aBefore) { function PVB__insertNewItemToPopup(aNewChild, aPopup, aBefore) {
let element = this._createMenuItemForPlacesNode(aNewChild); let element = this._createMenuItemForPlacesNode(aNewChild);
let before = aBefore || aPopup._endMarker;
if (aBefore) { aPopup.insertBefore(element, before);
aPopup.insertBefore(element, aBefore);
}
else {
// Add the new element to the menu. If there is static content at
// the end of the menu, add the element before that. Otherwise,
// just add to the end.
if (aPopup._endMarker != -1) {
let lastElt = aPopup.childNodes[aPopup._endMarker];
aPopup.insertBefore(element, lastElt);
}
else {
aPopup.appendChild(element);
}
}
if (aPopup._endMarker != -1)
aPopup._endMarker++;
return element; return element;
}, },
@ -384,10 +338,8 @@ PlacesViewBase.prototype = {
if (!siteUrl && aPopup._siteURIMenuitem) { if (!siteUrl && aPopup._siteURIMenuitem) {
aPopup.removeChild(aPopup._siteURIMenuitem); aPopup.removeChild(aPopup._siteURIMenuitem);
aPopup._siteURIMenuitem = null; aPopup._siteURIMenuitem = null;
aPopup._startMarker--;
aPopup.removeChild(aPopup._siteURIMenuseparator); aPopup.removeChild(aPopup._siteURIMenuseparator);
aPopup._siteURIMenuseparator = null; aPopup._siteURIMenuseparator = null;
aPopup._startMarker--;
} }
else if (siteUrl && !aPopup._siteURIMenuitem) { else if (siteUrl && !aPopup._siteURIMenuitem) {
// Add "Open (Feed Name)" menuitem. // Add "Open (Feed Name)" menuitem.
@ -407,14 +359,10 @@ PlacesViewBase.prototype = {
PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label", PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
[aPopup.parentNode.getAttribute("label")]) [aPopup.parentNode.getAttribute("label")])
aPopup._siteURIMenuitem.setAttribute("label", label); aPopup._siteURIMenuitem.setAttribute("label", label);
aPopup.insertBefore(aPopup._siteURIMenuitem, aPopup.insertBefore(aPopup._siteURIMenuitem, aPopup._startMarker);
aPopup.childNodes.item(aPopup._startMarker + 1));
aPopup._startMarker++;
aPopup._siteURIMenuseparator = document.createElement("menuseparator"); aPopup._siteURIMenuseparator = document.createElement("menuseparator");
aPopup.insertBefore(aPopup._siteURIMenuseparator, aPopup.insertBefore(aPopup._siteURIMenuseparator, aPopup._startMarker);
aPopup.childNodes.item(aPopup._startMarker + 1));
aPopup._startMarker++;
} }
}, },
@ -427,7 +375,6 @@ PlacesViewBase.prototype = {
*/ */
_setLivemarkStatusMenuItem: _setLivemarkStatusMenuItem:
function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) { function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
let itemId = aPopup._placesNode.itemId;
let statusMenuitem = aPopup._statusMenuitem; let statusMenuitem = aPopup._statusMenuitem;
let stringId = ""; let stringId = "";
if (aStatus == Ci.mozILivemark.STATUS_LOADING) if (aStatus == Ci.mozILivemark.STATUS_LOADING)
@ -439,12 +386,11 @@ PlacesViewBase.prototype = {
// Create the status menuitem and cache it in the popup object. // Create the status menuitem and cache it in the popup object.
statusMenuitem = document.createElement("menuitem"); statusMenuitem = document.createElement("menuitem");
statusMenuitem.setAttribute("livemarkStatus", stringId); statusMenuitem.setAttribute("livemarkStatus", stringId);
statusMenuitem.className = "livemarkstatus-menuitem";
statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId)); statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
statusMenuitem.setAttribute("disabled", true); statusMenuitem.setAttribute("disabled", true);
aPopup.insertBefore(statusMenuitem, aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
aPopup.childNodes.item(aPopup._startMarker + 1));
aPopup._statusMenuitem = statusMenuitem; aPopup._statusMenuitem = statusMenuitem;
aPopup._startMarker++;
} }
else if (stringId && else if (stringId &&
statusMenuitem.getAttribute("livemarkStatus") != stringId) { statusMenuitem.getAttribute("livemarkStatus") != stringId) {
@ -455,7 +401,6 @@ PlacesViewBase.prototype = {
// The livemark has finished loading. // The livemark has finished loading.
aPopup.removeChild(aPopup._statusMenuitem); aPopup.removeChild(aPopup._statusMenuitem);
aPopup._statusMenuitem = null; aPopup._statusMenuitem = null;
aPopup._startMarker--;
} }
}, },
@ -517,6 +462,12 @@ PlacesViewBase.prototype = {
let menu = elt.parentNode; let menu = elt.parentNode;
if (!menu.hasAttribute("livemark")) { if (!menu.hasAttribute("livemark")) {
menu.setAttribute("livemark", "true"); menu.setAttribute("livemark", "true");
#ifdef XP_MACOSX
// OS X native menubar doesn't track list-style-images since
// it doesn't have a frame (bug 733415). Thus enforce updating.
menu.setAttribute("image", "");
menu.removeAttribute("image");
#endif
} }
PlacesUtils.livemarks.getLivemark( PlacesUtils.livemarks.getLivemark(
@ -580,13 +531,8 @@ PlacesViewBase.prototype = {
// Figure out if we need to show the "<Empty>" menu-item. // Figure out if we need to show the "<Empty>" menu-item.
// TODO Bug 517701: This doesn't seem to handle the case of an empty // TODO Bug 517701: This doesn't seem to handle the case of an empty
// root. // root.
if (!parentElt.hasChildNodes() || if (parentElt._startMarker.nextSibling == parentElt._endMarker)
(parentElt.childNodes.length == 1 && this._setEmptyPopupStatus(parentElt, true);
parentElt.firstChild == parentElt._emptyMenuItem))
this._showEmptyMenuItem(parentElt);
if (parentElt._endMarker != -1)
parentElt._endMarker--;
} }
}, },
@ -620,8 +566,9 @@ PlacesViewBase.prototype = {
if (aPlacesNode.parent && aPlacesNode.parent._feedURI) { if (aPlacesNode.parent && aPlacesNode.parent._feedURI) {
// Find the node in the parent. // Find the node in the parent.
let popup = aPlacesNode.parent._DOMElement; let popup = aPlacesNode.parent._DOMElement;
for (let i = popup._startMarker; i < popup.childNodes.length; i++) { for (let child = popup._startMarker.nextSibling;
let child = popup.childNodes[i]; child != popup._endMarker;
child = child.nextSibling) {
if (child._placesNode && child._placesNode.uri == aPlacesNode.uri) { if (child._placesNode && child._placesNode.uri == aPlacesNode.uri) {
if (aCount) if (aCount)
child.setAttribute("visited", "true"); child.setAttribute("visited", "true");
@ -649,11 +596,11 @@ PlacesViewBase.prototype = {
if (!parentElt._built) if (!parentElt._built)
return; return;
let index = parentElt._startMarker + 1 + aIndex; let index = Array.indexOf(parentElt.childNodes, parentElt._startMarker) +
aIndex + 1;
this._insertNewItemToPopup(aPlacesNode, parentElt, this._insertNewItemToPopup(aPlacesNode, parentElt,
parentElt.childNodes[index]); parentElt.childNodes[index]);
if (parentElt._emptyMenuItem) this._setEmptyPopupStatus(parentElt, false);
parentElt._emptyMenuItem.hidden = true;
}, },
nodeMoved: nodeMoved:
@ -684,7 +631,8 @@ PlacesViewBase.prototype = {
if (parentElt._built) { if (parentElt._built) {
// Move the node. // Move the node.
parentElt.removeChild(elt); parentElt.removeChild(elt);
let index = parentElt._startMarker + 1 + aNewIndex; let index = Array.indexOf(parentElt.childNodes, parentElt._startMarker) +
aNewIndex + 1;
parentElt.insertBefore(elt, parentElt.childNodes[index]); parentElt.insertBefore(elt, parentElt.childNodes[index]);
} }
}, },
@ -821,11 +769,9 @@ PlacesViewBase.prototype = {
if (aPopup._endOptOpenAllInTabs) { if (aPopup._endOptOpenAllInTabs) {
aPopup.removeChild(aPopup._endOptOpenAllInTabs); aPopup.removeChild(aPopup._endOptOpenAllInTabs);
aPopup._endOptOpenAllInTabs = null; aPopup._endOptOpenAllInTabs = null;
aPopup._endMarker--;
aPopup.removeChild(aPopup._endOptSeparator); aPopup.removeChild(aPopup._endOptSeparator);
aPopup._endOptSeparator = null; aPopup._endOptSeparator = null;
aPopup._endMarker--;
} }
} }
else if (!aPopup._endOptOpenAllInTabs) { else if (!aPopup._endOptOpenAllInTabs) {
@ -833,7 +779,6 @@ PlacesViewBase.prototype = {
aPopup._endOptSeparator = document.createElement("menuseparator"); aPopup._endOptSeparator = document.createElement("menuseparator");
aPopup._endOptSeparator.className = "bookmarks-actions-menuseparator"; aPopup._endOptSeparator.className = "bookmarks-actions-menuseparator";
aPopup.appendChild(aPopup._endOptSeparator); aPopup.appendChild(aPopup._endOptSeparator);
aPopup._endMarker++;
// Add the "Open All in Tabs" menuitem. // Add the "Open All in Tabs" menuitem.
aPopup._endOptOpenAllInTabs = document.createElement("menuitem"); aPopup._endOptOpenAllInTabs = document.createElement("menuitem");
@ -846,13 +791,51 @@ PlacesViewBase.prototype = {
aPopup._endOptOpenAllInTabs.setAttribute("label", aPopup._endOptOpenAllInTabs.setAttribute("label",
gNavigatorBundle.getString("menuOpenAllInTabs.label")); gNavigatorBundle.getString("menuOpenAllInTabs.label"));
aPopup.appendChild(aPopup._endOptOpenAllInTabs); aPopup.appendChild(aPopup._endOptOpenAllInTabs);
aPopup._endMarker++; }
},
_ensureMarkers: function PVB__ensureMarkers(aPopup) {
if (aPopup._startMarker)
return;
// _startMarker is an hidden menuseparator that lives before places nodes.
aPopup._startMarker = document.createElement("menuseparator");
aPopup._startMarker.hidden = true;
aPopup.insertBefore(aPopup._startMarker, aPopup.firstChild);
// _endMarker is an hidden menuseparator that lives after places nodes.
aPopup._endMarker = document.createElement("menuseparator");
aPopup._endMarker.hidden = true;
aPopup.appendChild(aPopup._endMarker);
// Move the markers to the right position.
let firstNonStaticNodeFound = false;
for (let i = 0; i < aPopup.childNodes.length; i++) {
let child = aPopup.childNodes[i];
// Menus that have static content at the end, but are initially empty,
// use a special "builder" attribute to figure out where to start
// inserting places nodes.
if (child.getAttribute("builder") == "end") {
aPopup.insertBefore(aPopup._endMarker, child);
break;
}
if (child._placesNode && !firstNonStaticNodeFound) {
firstNonStaticNodeFound = true;
aPopup.insertBefore(aPopup._startMarker, child);
}
}
if (!firstNonStaticNodeFound) {
aPopup.insertBefore(aPopup._startMarker, aPopup._endMarker);
} }
}, },
_onPopupShowing: function PVB__onPopupShowing(aEvent) { _onPopupShowing: function PVB__onPopupShowing(aEvent) {
// Avoid handling popupshowing of inner views. // Avoid handling popupshowing of inner views.
let popup = aEvent.originalTarget; let popup = aEvent.originalTarget;
this._ensureMarkers(popup);
if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) { if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
if (!popup._placesNode.containerOpen) if (!popup._placesNode.containerOpen)
popup._placesNode.containerOpen = true; popup._placesNode.containerOpen = true;
@ -1808,8 +1791,6 @@ function PlacesMenu(aPopupShowingEvent, aPlace) {
#ifdef XP_MACOSX #ifdef XP_MACOSX
if (this._viewElt.parentNode.localName == "menubar") { if (this._viewElt.parentNode.localName == "menubar") {
this._nativeView = true; this._nativeView = true;
this._rootElt._startMarker = -1;
this._rootElt._endMarker = -1;
} }
#endif #endif
@ -1829,8 +1810,6 @@ PlacesMenu.prototype = {
_removeChild: function PM_removeChild(aChild) { _removeChild: function PM_removeChild(aChild) {
PlacesViewBase.prototype._removeChild.apply(this, arguments); PlacesViewBase.prototype._removeChild.apply(this, arguments);
if (this._endMarker != -1)
this._endMarker--;
}, },
uninit: function PM_uninit() { uninit: function PM_uninit() {

View File

@ -72,10 +72,6 @@
"popup-internal-box"); "popup-internal-box");
</field> </field>
<!-- markers for start and end of valid places items -->
<field name="_startMarker">-1</field>
<field name="_endMarker">-1</field>
<!-- This is the view that manage the popup --> <!-- This is the view that manage the popup -->
<field name="_rootView">PlacesUIUtils.getViewForNode(this);</field> <field name="_rootView">PlacesUIUtils.getViewForNode(this);</field>
@ -83,17 +79,16 @@
<method name="_hideDropIndicator"> <method name="_hideDropIndicator">
<parameter name="aEvent"/> <parameter name="aEvent"/>
<body><![CDATA[ <body><![CDATA[
var target = aEvent.target; let target = aEvent.target;
// in some view we have _startMarker and _endMarker, we should not // Don't draw the drop indicator outside of markers.
// draw the drop indicator outside of them // The markers are hidden, since otherwise sometimes popups acquire
var betweenMarkers = true; // scrollboxes on OS X, so we can't use them directly.
if (this._startMarker != -1 && let firstChildTop = this._startMarker.nextSibling.boxObject.y;
target.boxObject.y <= this.childNodes[this._startMarker].boxObject.y) let lastChildBottom = this._endMarker.previousSibling.boxObject.y +
betweenMarkers = false; this._endMarker.previousSibling.boxObject.height;
if (this._endMarker != -1 && let betweenMarkers = target.boxObject.y >= firstChildTop ||
target.boxObject.y >= this.childNodes[this._endMarker].boxObject.y) target.boxObject.y <= lastChildBottom;
betweenMarkers = false;
// Hide the dropmarker if current node is not a Places node. // Hide the dropmarker if current node is not a Places node.
return !(target && target._placesNode && betweenMarkers); return !(target && target._placesNode && betweenMarkers);

View File

@ -42,7 +42,7 @@ let test_bookmarks = {
menu: [ menu: [
{ title: "Mozilla Firefox", { title: "Mozilla Firefox",
children: [ children: [
{ title: "Help and Tutorials", { title: "Help and Tutorials",
url: "http://en-us.www.mozilla.com/en-US/firefox/help/", url: "http://en-us.www.mozilla.com/en-US/firefox/help/",
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==" icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
}, },
@ -57,8 +57,8 @@ let test_bookmarks = {
{ title: "About Us", { title: "About Us",
url: "http://en-us.www.mozilla.com/en-US/about/", url: "http://en-us.www.mozilla.com/en-US/about/",
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==" icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
}, }
], ]
}, },
{ title: "test", { title: "test",
description: "folder test comment", description: "folder test comment",
@ -72,10 +72,10 @@ let test_bookmarks = {
keyword: "test", keyword: "test",
sidebar: true, sidebar: true,
postData: "hidden1%3Dbar&text1%3D%25s", postData: "hidden1%3Dbar&text1%3D%25s",
charset: "ISO-8859-1", charset: "ISO-8859-1"
}, }
] ]
}, }
], ],
toolbar: [ toolbar: [
{ title: "Getting Started", { title: "Getting Started",
@ -84,14 +84,14 @@ let test_bookmarks = {
}, },
{ title: "Latest Headlines", { title: "Latest Headlines",
url: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/", url: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
feedUrl: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml", feedUrl: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml"
} }
], ],
unfiled: [ unfiled: [
{ title: "Example.tld", { title: "Example.tld",
url: "http://example.tld/", url: "http://example.tld/"
}, }
], ]
}; };
// Pre-Places bookmarks.html file pointer. // Pre-Places bookmarks.html file pointer.
@ -303,6 +303,8 @@ add_test(function test_import_ontop()
function testImportedBookmarks() function testImportedBookmarks()
{ {
for (let group in test_bookmarks) { for (let group in test_bookmarks) {
do_print("[testImportedBookmarks()] Checking group '" + group + "'");
let root; let root;
switch (group) { switch (group) {
case "menu": case "menu":
@ -335,6 +337,7 @@ function testImportedBookmarksToFolder(aFolder)
for (let i = 0; i < root.childCount; i++) { for (let i = 0; i < root.childCount; i++) {
let child = root.getChild(i); let child = root.getChild(i);
// This check depends on all "menu" bookmarks being listed first in the imported file :-|
if (i < rootFolderCount) { if (i < rootFolderCount) {
checkItem(test_bookmarks.menu[i], child); checkItem(test_bookmarks.menu[i], child);
} }
@ -343,9 +346,8 @@ function testImportedBookmarksToFolder(aFolder)
let group = /Toolbar/.test(container.title) ? test_bookmarks.toolbar let group = /Toolbar/.test(container.title) ? test_bookmarks.toolbar
: test_bookmarks.unfiled; : test_bookmarks.unfiled;
container.containerOpen = true; container.containerOpen = true;
print(container.title); do_print("[testImportedBookmarksToFolder()] Checking container '" + container.title + "'");
for (let t = 0; t < container.childCount; t++) { for (let t = 0; t < container.childCount; t++) {
print(group[t].title + " " + container.getChild(t).title);
checkItem(group[t], container.getChild(t)); checkItem(group[t], container.getChild(t));
} }
container.containerOpen = false; container.containerOpen = false;

View File

@ -199,7 +199,7 @@ menuitem.bookmark-item {
} }
/* Bookmark items */ /* Bookmark items */
.bookmark-item:not([container]) { .bookmark-item {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
} }

View File

@ -229,15 +229,20 @@ toolbarbutton.bookmark-item > menupopup {
list-style-image: url("chrome://global/skin/tree/folder.png"); list-style-image: url("chrome://global/skin/tree/folder.png");
} }
.query-item[container] { .bookmark-item[container][livemark] {
list-style-image: url("chrome://browser/skin/places/history.png");
}
.bookmark-item[livemark] {
list-style-image: url("chrome://browser/skin/page-livemarks.png"); list-style-image: url("chrome://browser/skin/page-livemarks.png");
} }
.bookmark-item[query] { .bookmark-item[container][livemark] .bookmark-item {
list-style-image: url("chrome://browser/skin/places/livemark-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
.bookmark-item[container][livemark] .bookmark-item[visited] {
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
.bookmark-item[container][query] {
list-style-image: url("chrome://browser/skin/places/query.png"); list-style-image: url("chrome://browser/skin/places/query.png");
} }
@ -257,20 +262,23 @@ toolbarbutton.bookmark-item > menupopup {
list-style-image: url("chrome://global/skin/tree/folder.png"); list-style-image: url("chrome://global/skin/tree/folder.png");
} }
.bookmark-item[livemark] .menuitem-iconic { /* Workaround for native menubar inheritance */
list-style-image: url("chrome://browser/skin/places/livemark-item.png"); .openintabs-menuitem,
-moz-image-region: rect(0px, 16px, 16px, 0px); .openlivemarksite-menuitem,
} .livemarkstatus-menuitem {
.bookmark-item[livemark] .menuitem-iconic[visited] {
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
.bookmark-item menuitem[openInTabs],
.bookmark-item menuitem[siteURI] {
list-style-image: none; list-style-image: none;
} }
.bookmark-item[cutting] > .toolbarbutton-icon,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon {
opacity: 0.5;
}
.bookmark-item[cutting] > .toolbarbutton-text,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text {
opacity: 0.7;
}
#wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box { #wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box {
background: url("chrome://browser/skin/places/bookmarksToolbar.png") no-repeat center; background: url("chrome://browser/skin/places/bookmarksToolbar.png") no-repeat center;
} }
@ -287,16 +295,6 @@ toolbarbutton.bookmark-item > menupopup {
height: 16px; height: 16px;
} }
.bookmark-item[cutting] > .toolbarbutton-icon,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon {
opacity: 0.5;
}
.bookmark-item[cutting] > .toolbarbutton-text,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text {
opacity: 0.7;
}
#bookmarksToolbarFolderMenu, #bookmarksToolbarFolderMenu,
#BMB_bookmarksToolbar { #BMB_bookmarksToolbar {
list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png"); list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");

View File

@ -1224,7 +1224,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
padding: 0; padding: 0;
background-clip: padding-box; background-clip: padding-box;
border: 1px solid ThreeDShadow; border: 1px solid ThreeDShadow;
border-radius: 2.5px; border-radius: 2px;
} }
#urlbar { #urlbar {

View File

@ -74,6 +74,6 @@
-moz-padding-start: 4px; -moz-padding-start: 4px;
background-clip: padding-box; background-clip: padding-box;
border: 1px solid rgba(0,0,0,.32); border: 1px solid rgba(0,0,0,.32);
border-radius: 2.5px; border-radius: 2px;
} }
} }

View File

@ -738,8 +738,11 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
def killAndGetStack(self, proc, utilityPath, debuggerInfo): def killAndGetStack(self, proc, utilityPath, debuggerInfo):
"""Kill the process, preferrably in a way that gets us a stack trace.""" """Kill the process, preferrably in a way that gets us a stack trace."""
if not debuggerInfo and not self.haveDumpedScreen: if not debuggerInfo:
self.dumpScreen(utilityPath) if self.haveDumpedScreen:
self.log.info("Not taking screenshot here: see the one that was previously logged")
else:
self.dumpScreen(utilityPath)
if self.CRASHREPORTER and not debuggerInfo: if self.CRASHREPORTER and not debuggerInfo:
if self.UNIXISH: if self.UNIXISH:
@ -796,8 +799,11 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
if stackFixerFunction: if stackFixerFunction:
line = stackFixerFunction(line) line = stackFixerFunction(line)
self.log.info(line.rstrip().decode("UTF-8", "ignore")) self.log.info(line.rstrip().decode("UTF-8", "ignore"))
if not debuggerInfo and not self.haveDumpedScreen and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line: if not debuggerInfo and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line:
self.dumpScreen(utilityPath) if self.haveDumpedScreen:
self.log.info("Not taking screenshot here: see the one that was previously logged")
else:
self.dumpScreen(utilityPath)
(line, didTimeout) = self.readWithTimeout(logsource, timeout) (line, didTimeout) = self.readWithTimeout(logsource, timeout)
if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds = maxTime): if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds = maxTime):

View File

@ -459,7 +459,7 @@ class ShutdownLeakLogger(object):
DOM windows (that are still around after test suite shutdown, despite running DOM windows (that are still around after test suite shutdown, despite running
the GC) to the tests that created them and prints leak statistics. the GC) to the tests that created them and prints leak statistics.
""" """
MAX_LEAK_COUNT = 130 MAX_LEAK_COUNT = 123
def __init__(self, logger): def __init__(self, logger):
self.logger = logger self.logger = logger

View File

@ -77,5 +77,5 @@ public interface Driver {
* @return A 2-D array of pixels (indexed by y, then x). The pixels * @return A 2-D array of pixels (indexed by y, then x). The pixels
* are in ARGB-8888 format. * are in ARGB-8888 format.
*/ */
int[][] getPaintedSurface(); PaintedSurface getPaintedSurface();
} }

View File

@ -48,6 +48,8 @@ import java.io.IOException;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.lang.Class; import java.lang.Class;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -291,7 +293,7 @@ public class FennecNativeDriver implements Driver {
return null; return null;
} }
public int[][] getPaintedSurface() { public PaintedSurface getPaintedSurface() {
GLSurfaceView view = getSurfaceView(); GLSurfaceView view = getSurfaceView();
if (view == null) { if (view == null) {
return null; return null;
@ -309,14 +311,34 @@ public class FennecNativeDriver implements Driver {
int w = view.getWidth(); int w = view.getWidth();
int h = view.getHeight(); int h = view.getHeight();
pixelBuffer.position(0); pixelBuffer.position(0);
int[][] pixels = new int[h][w]; String mapFile = "/mnt/sdcard/pixels.map";
for (int y = h - 1; y >= 0; y--) {
for (int x = 0; x < w; x++) { FileOutputStream fos = null;
int agbr = pixelBuffer.get(); DataOutputStream dos = null;
pixels[y][x] = (agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000); try {
fos = new FileOutputStream(mapFile);
dos = new DataOutputStream(fos);
for (int y = h - 1; y >= 0; y--) {
for (int x = 0; x < w; x++) {
int agbr = pixelBuffer.get();
dos.writeInt((agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000));
}
}
return new PaintedSurface(mapFile, w, h);
} catch (IOException e) {
throw new RoboCopException("exception with pixel writer on file: " + mapFile);
} finally {
try {
if (dos != null && fos != null) {
dos.flush();
dos.close();
fos.close();
}
} catch (IOException e) {
throw new RoboCopException("exception closing pixel writer on file: " + mapFile);
} }
} }
return pixels;
} }
public int mHeight=0; public int mHeight=0;

View File

@ -61,11 +61,15 @@ _JAVA_HARNESS = \
FennecNativeDriver.java \ FennecNativeDriver.java \
FennecNativeElement.java \ FennecNativeElement.java \
RoboCopException.java \ RoboCopException.java \
PaintedSurface.java \
$(NULL) $(NULL)
_JAVA_TESTS = $(patsubst $(TESTPATH)/%.in,%,$(wildcard $(TESTPATH)/*.java.in)) _JAVA_TESTS = $(patsubst $(TESTPATH)/%.in,%,$(wildcard $(TESTPATH)/*.java.in))
_TEST_FILES = $(wildcard $(TESTPATH)/*.html) _TEST_FILES = \
$(wildcard $(TESTPATH)/*.html) \
$(wildcard $(TESTPATH)/*.sjs) \
$(NULL)
_ROBOCOP_TOOLS = \ _ROBOCOP_TOOLS = \
$(TESTPATH)/robocop.ini \ $(TESTPATH)/robocop.ini \

View File

@ -0,0 +1,62 @@
#filter substitution
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package @ANDROID_PACKAGE_NAME@;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class PaintedSurface {
private String mFileName = null;
private int mWidth = -1;
private int mHeight = -1;
private MappedByteBuffer mPixelBuffer = null;
public PaintedSurface(String filename, int width, int height) {
mFileName = filename;
mWidth = width;
mHeight = height;
try {
File f = new File(filename);
int pixelSize = (int)f.length();
FileInputStream pixelFile = new FileInputStream(filename);
mPixelBuffer = pixelFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, pixelSize);
} catch (java.io.FileNotFoundException e) {
e.printStackTrace();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
public final int getPixelAt(int x, int y) {
if (mPixelBuffer == null) {
throw new RoboCopException("Trying to access PaintedSurface with no active PixelBuffer");
}
if (x >= mWidth || x < 0) {
throw new RoboCopException("Trying to access PaintedSurface with invalid x value");
}
if (y >= mHeight || y < 0) {
throw new RoboCopException("Trying to access PaintedSurface with invalid y value");
}
// The rows are reversed so row 0 is at the end and we start with the last row.
// This is why we do mHeight-y;
int index = (x + ((mHeight - y - 1) * mWidth)) * 4;
int b1 = mPixelBuffer.get(index) & 0xFF;
int b2 = mPixelBuffer.get(index + 1) & 0xFF;
int b3 = mPixelBuffer.get(index + 2) & 0xFF;
int b4 = mPixelBuffer.get(index + 3) & 0xFF;
int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0);
return value;
}
}

View File

@ -67,11 +67,12 @@ NS_IMPL_THREADSAFE_ADDREF(nsNullPrincipalURI)
NS_IMPL_THREADSAFE_RELEASE(nsNullPrincipalURI) NS_IMPL_THREADSAFE_RELEASE(nsNullPrincipalURI)
NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI) NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURI)
if (aIID.Equals(kNullPrincipalURIImplementationCID)) if (aIID.Equals(kNullPrincipalURIImplementationCID))
foundInterface = static_cast<nsIURI *>(this); foundInterface = static_cast<nsIURI *>(this);
else else
NS_INTERFACE_MAP_ENTRY(nsIURI) NS_INTERFACE_MAP_ENTRY(nsIURI)
NS_INTERFACE_MAP_ENTRY(nsISizeOf)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -299,3 +300,19 @@ nsNullPrincipalURI::SchemeIs(const char *aScheme, bool *_schemeIs)
*_schemeIs = (0 == nsCRT::strcasecmp(mScheme.get(), aScheme)); *_schemeIs = (0 == nsCRT::strcasecmp(mScheme.get(), aScheme));
return NS_OK; return NS_OK;
} }
////////////////////////////////////////////////////////////////////////////////
//// nsISizeOf
size_t
nsNullPrincipalURI::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
return mScheme.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
size_t
nsNullPrincipalURI::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}

View File

@ -45,6 +45,7 @@
#define __nsNullPrincipalURI_h__ #define __nsNullPrincipalURI_h__
#include "nsIURI.h" #include "nsIURI.h"
#include "nsISizeOf.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsString.h" #include "nsString.h"
@ -54,11 +55,16 @@
{0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} } {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
class nsNullPrincipalURI : public nsIURI class nsNullPrincipalURI : public nsIURI
, public nsISizeOf
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIURI NS_DECL_NSIURI
// nsISizeOf
virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
nsNullPrincipalURI(const nsCString &aSpec); nsNullPrincipalURI(const nsCString &aSpec);
private: private:

View File

@ -301,6 +301,10 @@ MOZ_NATIVE_NSS = @MOZ_NATIVE_NSS@
MOZ_B2G_RIL = @MOZ_B2G_RIL@ MOZ_B2G_RIL = @MOZ_B2G_RIL@
MOZ_B2G_BT = @MOZ_B2G_BT@ MOZ_B2G_BT = @MOZ_B2G_BT@
MOZ_ASAN = @MOZ_ASAN@
MOZ_CFLAGS_NSS = @MOZ_CFLAGS_NSS@
MOZ_NO_WLZDEFS = @MOZ_NO_WLZDEFS@
BUILD_CTYPES = @BUILD_CTYPES@ BUILD_CTYPES = @BUILD_CTYPES@
COMPILE_ENVIRONMENT = @COMPILE_ENVIRONMENT@ COMPILE_ENVIRONMENT = @COMPILE_ENVIRONMENT@

View File

@ -148,6 +148,9 @@ xpcshell-tests:
$(testxpcsrcdir)/runxpcshelltests.py \ $(testxpcsrcdir)/runxpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \ --symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \ --build-info-json=$(DEPTH)/mozinfo.json \
--tests-root-dir=$(testxpcobjdir) \
--xunit-file=$(testxpcobjdir)/$(relativesrcdir)/results.xml \
--xunit-suite-name=xpcshell \
$(EXTRA_TEST_ARGS) \ $(EXTRA_TEST_ARGS) \
$(LIBXUL_DIST)/bin/xpcshell \ $(LIBXUL_DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))

View File

@ -628,9 +628,10 @@ if test "$GXX" = "yes"; then
GNU_CXX=1 GNU_CXX=1
CXX_VERSION=`$CXX -v 2>&1 | grep 'gcc version'` CXX_VERSION=`$CXX -v 2>&1 | grep 'gcc version'`
fi fi
if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c GNU`" != "0"; then
GNU_AS=1 GNU_AS=1
fi fi
rm -f conftest.out
if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
GNU_LD=1 GNU_LD=1
fi fi
@ -1836,6 +1837,33 @@ if test -n "$CLANG_CXX"; then
_WARNINGS_CXXFLAGS="-Qunused-arguments ${_WARNINGS_CXXFLAGS}" _WARNINGS_CXXFLAGS="-Qunused-arguments ${_WARNINGS_CXXFLAGS}"
fi fi
dnl ========================================================
dnl = Use Address Sanitizer
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(address-sanitizer,
[ --enable-address-sanitizer Enable Address Sanitizer (default=no)],
MOZ_ASAN=1,
MOZ_ASAN= )
if test -n "$MOZ_ASAN"; then
MOZ_LLVM_HACKS=1
AC_DEFINE(MOZ_ASAN)
fi
AC_SUBST(MOZ_ASAN)
dnl ========================================================
dnl = Enable hacks required for LLVM instrumentations
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(llvm-hacks,
[ --enable-llvm-hacks Enable workarounds required for several LLVM instrumentations (default=no)],
MOZ_LLVM_HACKS=1,
MOZ_LLVM_HACKS= )
if test -n "$MOZ_LLVM_HACKS"; then
MOZ_NO_WLZDEFS=1
MOZ_CFLAGS_NSS=1
fi
AC_SUBST(MOZ_NO_WLZDEFS)
AC_SUBST(MOZ_CFLAGS_NSS)
dnl ======================================================== dnl ========================================================
dnl GNU specific defaults dnl GNU specific defaults
dnl ======================================================== dnl ========================================================
@ -1846,8 +1874,13 @@ if test "$GNU_CC"; then
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@' MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
DSO_LDOPTS='-shared' DSO_LDOPTS='-shared'
if test "$GCC_USE_GNU_LD"; then if test "$GCC_USE_GNU_LD"; then
# Don't allow undefined symbols in libraries # Some tools like ASan use a runtime library that is only
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs" # linked against executables, so we must allow undefined
# symbols for shared objects in some cases.
if test -z "$MOZ_NO_WLZDEFS"; then
# Don't allow undefined symbols in libraries
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
fi
fi fi
WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized' WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized'
DSO_CFLAGS='' DSO_CFLAGS=''
@ -9212,7 +9245,7 @@ if test -z "$MOZ_NATIVE_NSPR"; then
fi fi
if test "$MOZ_OPTIMIZE" = "1"; then if test "$MOZ_OPTIMIZE" = "1"; then
ac_configure_args="$ac_configure_args --enable-optimize" ac_configure_args="$ac_configure_args --enable-optimize"
else elif test -z "$MOZ_OPTIMIZE"; then
ac_configure_args="$ac_configure_args --disable-optimize" ac_configure_args="$ac_configure_args --disable-optimize"
fi fi
if test -n "$HAVE_64BIT_OS"; then if test -n "$HAVE_64BIT_OS"; then

View File

@ -41,6 +41,7 @@
#include "nsEventStates.h" #include "nsEventStates.h"
#include "nsIURL.h" #include "nsIURL.h"
#include "nsISizeOf.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsEscape.h" #include "nsEscape.h"
@ -531,5 +532,24 @@ Link::SetHrefAttribute(nsIURI *aURI)
NS_ConvertUTF8toUTF16(href), true); NS_ConvertUTF8toUTF16(href), true);
} }
size_t
Link::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
size_t n = 0;
if (mCachedURI) {
nsCOMPtr<nsISizeOf> iface = do_QueryInterface(mCachedURI);
if (iface) {
n += iface->SizeOfIncludingThis(aMallocSizeOf);
}
}
// The following members don't need to be measured:
// - mElement, because it is a pointer-to-self used to avoid QIs
// - mHistory, because it is non-owning
return n;
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -131,6 +131,9 @@ public:
*/ */
virtual bool HasDeferredDNSPrefetchRequest() { return true; } virtual bool HasDeferredDNSPrefetchRequest() { return true; }
virtual size_t
SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
protected: protected:
virtual ~Link(); virtual ~Link();

View File

@ -44,7 +44,6 @@
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsIParser.h" #include "nsIParser.h"
#include "nsParserCIID.h" #include "nsParserCIID.h"
#include "nsICharsetAlias.h"
#include "nsMimeTypes.h" #include "nsMimeTypes.h"
#include "nsIStreamConverterService.h" #include "nsIStreamConverterService.h"
#include "nsStringStream.h" #include "nsStringStream.h"

View File

@ -43,7 +43,6 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsDOMClassInfoID.h" #include "nsDOMClassInfoID.h"
#include "nsDOMError.h" #include "nsDOMError.h"
#include "nsICharsetAlias.h"
#include "nsICharsetDetector.h" #include "nsICharsetDetector.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsIConverterInputStream.h" #include "nsIConverterInputStream.h"

View File

@ -42,7 +42,7 @@
#include "nsDOMClassInfoID.h" #include "nsDOMClassInfoID.h"
#include "nsDOMFile.h" #include "nsDOMFile.h"
#include "nsDOMError.h" #include "nsDOMError.h"
#include "nsICharsetAlias.h" #include "nsCharsetAlias.h"
#include "nsICharsetDetector.h" #include "nsICharsetDetector.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsIConverterInputStream.h" #include "nsIConverterInputStream.h"
@ -495,10 +495,7 @@ nsDOMFileReader::GetAsText(const nsACString &aCharset,
} }
nsCAutoString charset; nsCAutoString charset;
nsCOMPtr<nsICharsetAlias> alias = do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv); rv = nsCharsetAlias::GetPreferred(charsetGuess, charset);
NS_ENSURE_SUCCESS(rv, rv);
rv = alias->GetPreferred(charsetGuess, charset);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = ConvertStream(aFileData, aDataLen, charset.get(), aResult); rv = ConvertStream(aFileData, aDataLen, charset.get(), aResult);

View File

@ -147,7 +147,7 @@
#include "nsILink.h" #include "nsILink.h"
#include "nsBlobProtocolHandler.h" #include "nsBlobProtocolHandler.h"
#include "nsICharsetAlias.h" #include "nsCharsetAlias.h"
#include "nsIParser.h" #include "nsIParser.h"
#include "nsIContentSink.h" #include "nsIContentSink.h"
@ -3012,13 +3012,10 @@ nsDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
mCharacterSet = aCharSetID; mCharacterSet = aCharSetID;
#ifdef DEBUG #ifdef DEBUG
nsCOMPtr<nsICharsetAlias> calias(do_GetService(NS_CHARSETALIAS_CONTRACTID)); nsCAutoString canonicalName;
if (calias) { nsCharsetAlias::GetPreferred(aCharSetID, canonicalName);
nsCAutoString canonicalName; NS_ASSERTION(canonicalName.Equals(aCharSetID),
calias->GetPreferred(aCharSetID, canonicalName); "charset name must be canonical");
NS_ASSERTION(canonicalName.Equals(aCharSetID),
"charset name must be canonical");
}
#endif #endif
PRInt32 n = mCharSetObservers.Length(); PRInt32 n = mCharSetObservers.Length();
@ -3172,16 +3169,10 @@ nsDocument::TryChannelCharset(nsIChannel *aChannel,
nsCAutoString charsetVal; nsCAutoString charsetVal;
nsresult rv = aChannel->GetContentCharset(charsetVal); nsresult rv = aChannel->GetContentCharset(charsetVal);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsICharsetAlias> calias(do_GetService(NS_CHARSETALIAS_CONTRACTID)); rv = nsCharsetAlias::GetPreferred(charsetVal, aCharset);
if (calias) { if(NS_SUCCEEDED(rv)) {
nsCAutoString preferred; aCharsetSource = kCharsetFromChannel;
rv = calias->GetPreferred(charsetVal, return true;
preferred);
if(NS_SUCCEEDED(rv)) {
aCharset = preferred;
aCharsetSource = kCharsetFromChannel;
return true;
}
} }
} }
} }

View File

@ -882,9 +882,7 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope)
JS_SetContextPrivate(cx, aScope); JS_SetContextPrivate(cx, aScope);
nsresult rv = nsresult rv =
xpc->InitClassesWithNewWrappedGlobal(cx, aScope, xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal,
NS_GET_IID(nsISupports),
mPrincipal, nsnull,
flags, getter_AddRefs(mGlobal)); flags, getter_AddRefs(mGlobal));
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, false);

View File

@ -597,29 +597,10 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
if (aCx && wrapper) { if (aCx && wrapper) {
nsIXPConnect *xpc = nsContentUtils::XPConnect(); nsIXPConnect *xpc = nsContentUtils::XPConnect();
if (xpc) { if (xpc) {
JSObject *preservedWrapper = nsnull;
// If reparenting moves us to a new compartment, preserving causes
// problems. In that case, we release ourselves and re-preserve after
// reparenting so we're sure to have the right JS object preserved.
// We use a JSObject stack copy of the wrapper to protect it from GC
// under ReparentWrappedNativeIfFound.
if (aNode->PreservingWrapper()) {
preservedWrapper = wrapper;
nsContentUtils::ReleaseWrapper(aNode, aNode);
NS_ASSERTION(aNode->GetWrapper(),
"ReleaseWrapper cleared our wrapper, this code needs to "
"be changed to deal with that!");
}
nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper; nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper;
rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode, rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode,
getter_AddRefs(oldWrapper)); getter_AddRefs(oldWrapper));
if (preservedWrapper) {
nsContentUtils::PreserveWrapper(aNode, aNode);
}
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
aNode->mNodeInfo.swap(nodeInfo); aNode->mNodeInfo.swap(nodeInfo);

View File

@ -602,7 +602,7 @@ nsWebSocket::Initialize(nsISupports* aOwner,
if (JSVAL_IS_OBJECT(aArgv[1]) && if (JSVAL_IS_OBJECT(aArgv[1]) &&
(jsobj = JSVAL_TO_OBJECT(aArgv[1])) && (jsobj = JSVAL_TO_OBJECT(aArgv[1])) &&
JS_IsArrayObject(aContext, jsobj)) { JS_IsArrayObject(aContext, jsobj)) {
jsuint len; uint32_t len;
JS_GetArrayLength(aContext, jsobj, &len); JS_GetArrayLength(aContext, jsobj, &len);
for (PRUint32 index = 0; index < len; ++index) { for (PRUint32 index = 0; index < len; ++index) {

View File

@ -61,7 +61,7 @@
#include "nsIJSContextStack.h" #include "nsIJSContextStack.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsWeakPtr.h" #include "nsWeakPtr.h"
#include "nsICharsetAlias.h" #include "nsCharsetAlias.h"
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
#include "nsDOMClassInfoID.h" #include "nsDOMClassInfoID.h"
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
@ -812,11 +812,7 @@ nsXMLHttpRequest::DetectCharset()
nsresult rv = channel ? channel->GetContentCharset(charsetVal) : nsresult rv = channel ? channel->GetContentCharset(charsetVal) :
NS_ERROR_FAILURE; NS_ERROR_FAILURE;
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsICharsetAlias> calias = rv = nsCharsetAlias::GetPreferred(charsetVal, mResponseCharset);
do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && calias) {
rv = calias->GetPreferred(charsetVal, mResponseCharset);
}
} }
if (NS_FAILED(rv) || mResponseCharset.IsEmpty()) { if (NS_FAILED(rv) || mResponseCharset.IsEmpty()) {

View File

@ -122,7 +122,7 @@ JSValToMatrixElts(JSContext* cx, const jsval& val,
double* (&elts)[N], nsresult* rv) double* (&elts)[N], nsresult* rv)
{ {
JSObject* obj; JSObject* obj;
jsuint length; uint32_t length;
if (JSVAL_IS_PRIMITIVE(val) || if (JSVAL_IS_PRIMITIVE(val) ||
!(obj = JSVAL_TO_OBJECT(val)) || !(obj = JSVAL_TO_OBJECT(val)) ||

View File

@ -146,11 +146,11 @@ JSValToDashArray(JSContext* cx, const jsval& patternArray,
{ {
// The cap is pretty arbitrary. 16k should be enough for // The cap is pretty arbitrary. 16k should be enough for
// anybody... // anybody...
static const jsuint MAX_NUM_DASHES = 1 << 14; static const uint32_t MAX_NUM_DASHES = 1 << 14;
if (!JSVAL_IS_PRIMITIVE(patternArray)) { if (!JSVAL_IS_PRIMITIVE(patternArray)) {
JSObject* obj = JSVAL_TO_OBJECT(patternArray); JSObject* obj = JSVAL_TO_OBJECT(patternArray);
jsuint length; uint32_t length;
if (!JS_GetArrayLength(cx, obj, &length)) { if (!JS_GetArrayLength(cx, obj, &length)) {
// Not an array-like thing // Not an array-like thing
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;

View File

@ -754,7 +754,7 @@ protected:
WebGL_MOZ_WEBGL_lose_context, WebGL_MOZ_WEBGL_lose_context,
WebGLExtensionID_Max WebGLExtensionID_Max
}; };
nsCOMPtr<WebGLExtension> mEnabledExtensions[WebGLExtensionID_Max]; nsRefPtr<WebGLExtension> mEnabledExtensions[WebGLExtensionID_Max];
bool IsExtensionEnabled(WebGLExtensionID ext) const { bool IsExtensionEnabled(WebGLExtensionID ext) const {
NS_ABORT_IF_FALSE(ext >= 0 && ext < WebGLExtensionID_Max, "bogus index!"); NS_ABORT_IF_FALSE(ext >= 0 && ext < WebGLExtensionID_Max, "bogus index!");
return mEnabledExtensions[ext] != nsnull; return mEnabledExtensions[ext] != nsnull;

View File

@ -377,7 +377,7 @@ function start() {
default: default:
throw 'unhandled'; throw 'unhandled';
break; break;
}; }
}; };
var getURLOptions = function(obj) { var getURLOptions = function(obj) {
@ -404,27 +404,12 @@ function start() {
// try to create a dummy WebGL context, just to catch context creation failures once here, // try to create a dummy WebGL context, just to catch context creation failures once here,
// rather than having them result in 100's of failures (one in each test page) // rather than having them result in 100's of failures (one in each test page)
var canvas = document.getElementById("webglcheck-default");
var ctx; var ctx;
try { try {
ctx = canvas.getContext("experimental-webgl"); ctx = document.getElementById("webglcheck-default")
} catch(e) { .getContext("experimental-webgl");
ok(false, "canvas.getContext() failed", e); } catch(e) {}
} if (!ctx) {
if (ctx) {
statusTextNode.textContent = 'Loading test lists...';
var iframe = document.getElementById("testframe");
var testHarness = new WebGLTestHarnessModule.TestHarness(
iframe,
'00_test_list.txt',
function(type, msg, success) {
return reporter.reportFunc(type, msg, success);
},
OPTIONS);
testHarness.setTimeoutDelay(20000); // and make it much higher when running under valgrind.
window.webglTestHarness = testHarness;
} else {
var errmsg = "Can't create a WebGL context"; var errmsg = "Can't create a WebGL context";
reporter.fullResultsNode.textContent = errmsg; reporter.fullResultsNode.textContent = errmsg;
// Workaround for SeaMonkey tinderboxes which don't support WebGL. // Workaround for SeaMonkey tinderboxes which don't support WebGL.
@ -434,8 +419,22 @@ function start() {
ok(false, errmsg); ok(false, errmsg);
dump("WebGL mochitest failed: " + errmsg + "\n"); dump("WebGL mochitest failed: " + errmsg + "\n");
reporter.finishedTestSuite(); reporter.finishedTestSuite();
return;
} }
};
statusTextNode.textContent = 'Loading test lists...';
var iframe = document.getElementById("testframe");
var testHarness = new WebGLTestHarnessModule.TestHarness(
iframe,
'00_test_list.txt',
function(type, msg, success) {
return reporter.reportFunc(type, msg, success);
},
OPTIONS);
// Make timeout delay much higher when running under valgrind.
testHarness.setTimeoutDelay(20000);
window.webglTestHarness = testHarness;
}
SimpleTest.requestLongerTimeout(3); SimpleTest.requestLongerTimeout(3);

View File

@ -60,7 +60,7 @@
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsLinebreakConverter.h" #include "nsLinebreakConverter.h"
#include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager.h"
#include "nsICharsetAlias.h" #include "nsCharsetAlias.h"
#include "nsEscape.h" #include "nsEscape.h"
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"
#include "nsIMultiplexInputStream.h" #include "nsIMultiplexInputStream.h"
@ -782,7 +782,6 @@ GetSubmitCharset(nsGenericHTMLElement* aForm,
{ {
oCharset.AssignLiteral("UTF-8"); // default to utf-8 oCharset.AssignLiteral("UTF-8"); // default to utf-8
nsresult rv = NS_OK;
nsAutoString acceptCharsetValue; nsAutoString acceptCharsetValue;
aForm->GetAttr(kNameSpaceID_None, nsGkAtoms::acceptcharset, aForm->GetAttr(kNameSpaceID_None, nsGkAtoms::acceptcharset,
acceptCharsetValue); acceptCharsetValue);
@ -792,26 +791,19 @@ GetSubmitCharset(nsGenericHTMLElement* aForm,
PRInt32 offset=0; PRInt32 offset=0;
PRInt32 spPos=0; PRInt32 spPos=0;
// get charset from charsets one by one // get charset from charsets one by one
nsCOMPtr<nsICharsetAlias> calias(do_GetService(NS_CHARSETALIAS_CONTRACTID, &rv)); do {
if (NS_FAILED(rv)) { spPos = acceptCharsetValue.FindChar(PRUnichar(' '), offset);
return; PRInt32 cnt = ((-1==spPos)?(charsetLen-offset):(spPos-offset));
} if (cnt > 0) {
if (calias) { nsAutoString uCharset;
do { acceptCharsetValue.Mid(uCharset, offset, cnt);
spPos = acceptCharsetValue.FindChar(PRUnichar(' '), offset);
PRInt32 cnt = ((-1==spPos)?(charsetLen-offset):(spPos-offset));
if (cnt > 0) {
nsAutoString uCharset;
acceptCharsetValue.Mid(uCharset, offset, cnt);
if (NS_SUCCEEDED(calias-> if (NS_SUCCEEDED(nsCharsetAlias::GetPreferred(NS_LossyConvertUTF16toASCII(uCharset),
GetPreferred(NS_LossyConvertUTF16toASCII(uCharset), oCharset)))
oCharset))) return;
return; }
} offset = spPos + 1;
offset = spPos + 1; } while (spPos != -1);
} while (spPos != -1);
}
} }
// if there are no accept-charset or all the charset are not supported // if there are no accept-charset or all the charset are not supported
// Get the charset from document // Get the charset from document

View File

@ -96,8 +96,8 @@ public:
// nsIDOMHTMLAnchorElement // nsIDOMHTMLAnchorElement
NS_DECL_NSIDOMHTMLANCHORELEMENT NS_DECL_NSIDOMHTMLANCHORELEMENT
// TODO: nsHTMLAnchorElement::SizeOfAnchorElement should call // DOM memory reporter participant
// Link::SizeOfExcludingThis(). See bug 682431. NS_DECL_SIZEOF_EXCLUDING_THIS
// nsILink // nsILink
NS_IMETHOD LinkAdded() { return NS_OK; } NS_IMETHOD LinkAdded() { return NS_OK; }
@ -520,3 +520,10 @@ nsHTMLAnchorElement::IntrinsicState() const
return Link::LinkState() | nsGenericHTMLElement::IntrinsicState(); return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
} }
size_t
nsHTMLAnchorElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
Link::SizeOfExcludingThis(aMallocSizeOf);
}

View File

@ -61,8 +61,8 @@ public:
// nsISupports // nsISupports
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
// TODO: nsHTMLAreaElement::SizeOfAnchorElement should call // DOM memory reporter participant
// Link::SizeOfExcludingThis(). See bug 682431. NS_DECL_SIZEOF_EXCLUDING_THIS
// nsIDOMNode // nsIDOMNode
NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::) NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
@ -335,3 +335,11 @@ nsHTMLAreaElement::IntrinsicState() const
{ {
return Link::LinkState() | nsGenericHTMLElement::IntrinsicState(); return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
} }
size_t
nsHTMLAreaElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
Link::SizeOfExcludingThis(aMallocSizeOf);
}

View File

@ -84,8 +84,8 @@ public:
// nsIDOMHTMLLinkElement // nsIDOMHTMLLinkElement
NS_DECL_NSIDOMHTMLLINKELEMENT NS_DECL_NSIDOMHTMLLINKELEMENT
// TODO: nsHTMLLinkElement::SizeOfAnchorElement should call // DOM memory reporter participant
// Link::SizeOfExcludingThis(). See bug 682431. NS_DECL_SIZEOF_EXCLUDING_THIS
// nsILink // nsILink
NS_IMETHOD LinkAdded(); NS_IMETHOD LinkAdded();
@ -458,3 +458,11 @@ nsHTMLLinkElement::IntrinsicState() const
{ {
return Link::LinkState() | nsGenericHTMLElement::IntrinsicState(); return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
} }
size_t
nsHTMLLinkElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
Link::SizeOfExcludingThis(aMallocSizeOf);
}

View File

@ -40,8 +40,6 @@
#include "mozilla/Util.h" #include "mozilla/Util.h"
#include "nsICharsetAlias.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsXPIDLString.h" #include "nsXPIDLString.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
@ -102,7 +100,6 @@
#include "nsFrameSelection.h" #include "nsFrameSelection.h"
#include "nsISelectionPrivate.h"//for toStringwithformat code #include "nsISelectionPrivate.h"//for toStringwithformat code
#include "nsICharsetAlias.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsJSUtils.h" #include "nsJSUtils.h"
#include "nsIDocumentEncoder.h" //for outputting selection #include "nsIDocumentEncoder.h" //for outputting selection

View File

@ -2019,6 +2019,13 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
// duration. // duration.
RenderVideoFrame(currentFrame, presTime); RenderVideoFrame(currentFrame, presTime);
} }
// If we're no longer playing after dropping and reacquiring the lock,
// playback must've been stopped on the decode thread (by a seek, for
// example). In that case, the current frame is probably out of date.
if (!IsPlaying()) {
ScheduleStateMachine();
return;
}
mDecoder->GetFrameStatistics().NotifyPresentedFrame(); mDecoder->GetFrameStatistics().NotifyPresentedFrame();
PRInt64 now = DurationToUsecs(TimeStamp::Now() - mPlayStartTime) + mPlayDuration; PRInt64 now = DurationToUsecs(TimeStamp::Now() - mPlayStartTime) + mPlayDuration;
remainingTime = currentFrame->mEndTime - mStartTime - now; remainingTime = currentFrame->mEndTime - mStartTime - now;

View File

@ -42,6 +42,7 @@
#include "nsMediaCache.h" #include "nsMediaCache.h"
#include "nsDirectoryServiceUtils.h" #include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h" #include "nsDirectoryServiceDefs.h"
#include "nsXULAppAPI.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "prio.h" #include "prio.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
@ -545,8 +546,15 @@ nsMediaCache::Init()
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ASSERTION(!mFD, "Cache file already open?"); NS_ASSERTION(!mFD, "Cache file already open?");
// In single process Gecko, store the media cache in the profile directory
// so that multiple users can use separate media caches concurrently.
// In multi-process Gecko, there is no profile dir, so just store it in the
// system temp directory instead.
nsresult rv;
nsCOMPtr<nsIFile> tmp; nsCOMPtr<nsIFile> tmp;
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmp)); const char* dir = (XRE_GetProcessType() == GeckoProcessType_Content) ?
NS_OS_TEMP_DIR : NS_APP_USER_PROFILE_LOCAL_50_DIR;
rv = NS_GetSpecialDirectory(dir, getter_AddRefs(tmp));
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr<nsILocalFile> tmpFile = do_QueryInterface(tmp); nsCOMPtr<nsILocalFile> tmpFile = do_QueryInterface(tmp);

View File

@ -428,9 +428,7 @@ nsSVGUseElement::SyncWidthOrHeight(nsIAtom* aName)
// Our width/height attribute is now no longer explicitly set, so we // Our width/height attribute is now no longer explicitly set, so we
// need to revert the clone's width/height to the width/height of the // need to revert the clone's width/height to the width/height of the
// content that's being cloned. // content that's being cloned.
nsSVGSVGElement* svgElement = TriggerReclone();
static_cast<nsSVGSVGElement*>(mSource.get());
svgElement->SyncWidthOrHeight(aName, target);
return; return;
} }
// Our width/height attribute is now no longer explicitly set, so we // Our width/height attribute is now no longer explicitly set, so we

View File

@ -41,7 +41,6 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIXBLService.h" #include "nsIXBLService.h"
#include "nsIInputStream.h" #include "nsIInputStream.h"
#include "nsDoubleHashtable.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsIURL.h" #include "nsIURL.h"
#include "nsIChannel.h" #include "nsIChannel.h"

View File

@ -59,8 +59,6 @@
#include "nsIHttpChannel.h" #include "nsIHttpChannel.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsICharsetAlias.h"
#include "nsICharsetAlias.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsDOMError.h" #include "nsDOMError.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"

View File

@ -55,7 +55,8 @@
#include "txList.h" #include "txList.h"
#include "nsIAtom.h" #include "nsIAtom.h"
#include "nsDoubleHashtable.h" #include "nsTHashtable.h"
#include "nsBaseHashtable.h"
#include "nsString.h" #include "nsString.h"
#include "txCore.h" #include "txCore.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
@ -229,24 +230,7 @@ class NodeDefinition : public Node
//Definition and Implementation of a Document. //Definition and Implementation of a Document.
// //
/** typedef nsTHashtable<nsBaseHashtableET<nsStringHashKey, Element*> > txIDMap;
* nsDoubleHashtable definitions for IDs
*
* It may be possible to share the key value with the element,
* but that may leave entries without keys, as the entries
* are constructed from the key value and the setting of mElement
* happens late. As pldhash.h ain't clear on this, we store the
* key by inheriting from PLDHashStringEntry.
*/
class txIDEntry : public PLDHashStringEntry
{
public:
txIDEntry(const void* aKey) : PLDHashStringEntry(aKey), mElement(nsnull)
{
}
Element* mElement;
};
DECL_DHASH_WRAPPER(txIDMap, txIDEntry, nsAString&)
class Document : public NodeDefinition class Document : public NodeDefinition
{ {

View File

@ -39,7 +39,7 @@
#ifndef txKey_h__ #ifndef txKey_h__
#define txKey_h__ #define txKey_h__
#include "nsDoubleHashtable.h" #include "nsTHashtable.h"
#include "txNodeSet.h" #include "txNodeSet.h"
#include "txList.h" #include "txList.h"
#include "txXSLTPatterns.h" #include "txXSLTPatterns.h"
@ -68,21 +68,31 @@ public:
struct txKeyValueHashEntry : public PLDHashEntryHdr struct txKeyValueHashEntry : public PLDHashEntryHdr
{ {
txKeyValueHashEntry(const void* aKey) public:
: mKey(*static_cast<const txKeyValueHashKey*>(aKey)), typedef const txKeyValueHashKey& KeyType;
mNodeSet(new txNodeSet(nsnull)) typedef const txKeyValueHashKey* KeyTypePointer;
{
}
// @see nsDoubleHashtable.h txKeyValueHashEntry(KeyTypePointer aKey)
bool MatchEntry(const void* aKey) const; : mKey(*aKey),
static PLDHashNumber HashKey(const void* aKey); mNodeSet(new txNodeSet(nsnull)) { }
txKeyValueHashEntry(const txKeyValueHashEntry& entry)
: mKey(entry.mKey),
mNodeSet(entry.mNodeSet) { }
bool KeyEquals(KeyTypePointer aKey) const;
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey);
enum { ALLOW_MEMMOVE = true };
txKeyValueHashKey mKey; txKeyValueHashKey mKey;
nsRefPtr<txNodeSet> mNodeSet; nsRefPtr<txNodeSet> mNodeSet;
}; };
DECL_DHASH_WRAPPER(txKeyValueHash, txKeyValueHashEntry, txKeyValueHashKey&) typedef nsTHashtable<txKeyValueHashEntry> txKeyValueHash;
class txIndexedKeyHashKey class txIndexedKeyHashKey
{ {
@ -100,22 +110,31 @@ public:
struct txIndexedKeyHashEntry : public PLDHashEntryHdr struct txIndexedKeyHashEntry : public PLDHashEntryHdr
{ {
txIndexedKeyHashEntry(const void* aKey) public:
: mKey(*static_cast<const txIndexedKeyHashKey*>(aKey)), typedef const txIndexedKeyHashKey& KeyType;
mIndexed(false) typedef const txIndexedKeyHashKey* KeyTypePointer;
{
}
// @see nsDoubleHashtable.h txIndexedKeyHashEntry(KeyTypePointer aKey)
bool MatchEntry(const void* aKey) const; : mKey(*aKey),
static PLDHashNumber HashKey(const void* aKey); mIndexed(false) { }
txIndexedKeyHashEntry(const txIndexedKeyHashEntry& entry)
: mKey(entry.mKey),
mIndexed(entry.mIndexed) { }
bool KeyEquals(KeyTypePointer aKey) const;
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey);
enum { ALLOW_MEMMOVE = true };
txIndexedKeyHashKey mKey; txIndexedKeyHashKey mKey;
bool mIndexed; bool mIndexed;
}; };
DECL_DHASH_WRAPPER(txIndexedKeyHash, txIndexedKeyHashEntry, typedef nsTHashtable<txIndexedKeyHashEntry> txIndexedKeyHash;
txIndexedKeyHashKey&)
/** /**
* Class holding all <xsl:key>s of a particular expanded name in the * Class holding all <xsl:key>s of a particular expanded name in the

View File

@ -152,51 +152,36 @@ txKeyFunctionCall::getNameAtom(nsIAtom** aAtom)
* Hash functions * Hash functions
*/ */
DHASH_WRAPPER(txKeyValueHash, txKeyValueHashEntry, txKeyValueHashKey&)
DHASH_WRAPPER(txIndexedKeyHash, txIndexedKeyHashEntry, txIndexedKeyHashKey&)
bool bool
txKeyValueHashEntry::MatchEntry(const void* aKey) const txKeyValueHashEntry::KeyEquals(KeyTypePointer aKey) const
{ {
const txKeyValueHashKey* key = return mKey.mKeyName == aKey->mKeyName &&
static_cast<const txKeyValueHashKey*>(aKey); mKey.mRootIdentifier == aKey->mRootIdentifier &&
mKey.mKeyValue.Equals(aKey->mKeyValue);
return mKey.mKeyName == key->mKeyName &&
mKey.mRootIdentifier == key->mRootIdentifier &&
mKey.mKeyValue.Equals(key->mKeyValue);
} }
PLDHashNumber PLDHashNumber
txKeyValueHashEntry::HashKey(const void* aKey) txKeyValueHashEntry::HashKey(KeyTypePointer aKey)
{ {
const txKeyValueHashKey* key = return aKey->mKeyName.mNamespaceID ^
static_cast<const txKeyValueHashKey*>(aKey); NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
aKey->mRootIdentifier ^
return key->mKeyName.mNamespaceID ^ HashString(aKey->mKeyValue);
NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^
key->mRootIdentifier ^
HashString(key->mKeyValue);
} }
bool bool
txIndexedKeyHashEntry::MatchEntry(const void* aKey) const txIndexedKeyHashEntry::KeyEquals(KeyTypePointer aKey) const
{ {
const txIndexedKeyHashKey* key = return mKey.mKeyName == aKey->mKeyName &&
static_cast<const txIndexedKeyHashKey*>(aKey); mKey.mRootIdentifier == aKey->mRootIdentifier;
return mKey.mKeyName == key->mKeyName &&
mKey.mRootIdentifier == key->mRootIdentifier;
} }
PLDHashNumber PLDHashNumber
txIndexedKeyHashEntry::HashKey(const void* aKey) txIndexedKeyHashEntry::HashKey(KeyTypePointer aKey)
{ {
const txIndexedKeyHashKey* key = return aKey->mKeyName.mNamespaceID ^
static_cast<const txIndexedKeyHashKey*>(aKey); NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
aKey->mRootIdentifier;
return key->mKeyName.mNamespaceID ^
NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^
key->mRootIdentifier;
} }
/* /*
@ -211,9 +196,6 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
txExecutionState& aEs, txExecutionState& aEs,
txNodeSet** aResult) txNodeSet** aResult)
{ {
NS_ENSURE_TRUE(mKeyValues.mHashTable.ops && mIndexedKeys.mHashTable.ops,
NS_ERROR_OUT_OF_MEMORY);
*aResult = nsnull; *aResult = nsnull;
PRInt32 identifier = txXPathNodeUtils::getUniqueIdentifier(aRoot); PRInt32 identifier = txXPathNodeUtils::getUniqueIdentifier(aRoot);
@ -241,7 +223,7 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
} }
txIndexedKeyHashKey indexKey(aKeyName, identifier); txIndexedKeyHashKey indexKey(aKeyName, identifier);
txIndexedKeyHashEntry* indexEntry = mIndexedKeys.AddEntry(indexKey); txIndexedKeyHashEntry* indexEntry = mIndexedKeys.PutEntry(indexKey);
NS_ENSURE_TRUE(indexEntry, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(indexEntry, NS_ERROR_OUT_OF_MEMORY);
if (indexEntry->mIndexed) { if (indexEntry->mIndexed) {
@ -412,7 +394,7 @@ nsresult txXSLKey::testNode(const txXPathNode& aNode,
txXPathNodeUtils::appendNodeValue(res->get(i), val); txXPathNodeUtils::appendNodeValue(res->get(i), val);
aKey.mKeyValue.Assign(val); aKey.mKeyValue.Assign(val);
txKeyValueHashEntry* entry = aKeyValueHash.AddEntry(aKey); txKeyValueHashEntry* entry = aKeyValueHash.PutEntry(aKey);
NS_ENSURE_TRUE(entry && entry->mNodeSet, NS_ENSURE_TRUE(entry && entry->mNodeSet,
NS_ERROR_OUT_OF_MEMORY); NS_ERROR_OUT_OF_MEMORY);
@ -427,7 +409,7 @@ nsresult txXSLKey::testNode(const txXPathNode& aNode,
exprResult->stringValue(val); exprResult->stringValue(val);
aKey.mKeyValue.Assign(val); aKey.mKeyValue.Assign(val);
txKeyValueHashEntry* entry = aKeyValueHash.AddEntry(aKey); txKeyValueHashEntry* entry = aKeyValueHash.PutEntry(aKey);
NS_ENSURE_TRUE(entry && entry->mNodeSet, NS_ENSURE_TRUE(entry && entry->mNodeSet,
NS_ERROR_OUT_OF_MEMORY); NS_ERROR_OUT_OF_MEMORY);

View File

@ -39,7 +39,7 @@
#include "nsCOMArray.h" #include "nsCOMArray.h"
#include "nsIAuthPrompt.h" #include "nsIAuthPrompt.h"
#include "nsICharsetAlias.h" #include "nsCharsetAlias.h"
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
#include "nsIDocument.h" #include "nsIDocument.h"
@ -282,29 +282,23 @@ txStylesheetSink::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
NS_IMETHODIMP NS_IMETHODIMP
txStylesheetSink::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) txStylesheetSink::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
{ {
nsCAutoString charset(NS_LITERAL_CSTRING("UTF-8"));
PRInt32 charsetSource = kCharsetFromDocTypeDefault; PRInt32 charsetSource = kCharsetFromDocTypeDefault;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
// check channel's charset... // check channel's charset...
nsCAutoString charsetVal; nsCAutoString charsetVal;
nsresult rv = channel->GetContentCharset(charsetVal); nsCAutoString charset;
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(channel->GetContentCharset(charsetVal))) {
nsCOMPtr<nsICharsetAlias> calias = if (NS_SUCCEEDED(nsCharsetAlias::GetPreferred(charsetVal, charset))) {
do_GetService(NS_CHARSETALIAS_CONTRACTID); charsetSource = kCharsetFromChannel;
if (calias) {
nsCAutoString preferred;
rv = calias->GetPreferred(charsetVal,
preferred);
if (NS_SUCCEEDED(rv)) {
charset = preferred;
charsetSource = kCharsetFromChannel;
}
} }
} }
if (charset.IsEmpty()) {
charset.AssignLiteral("UTF-8");
}
nsCOMPtr<nsIParser> parser = do_QueryInterface(aContext); nsCOMPtr<nsIParser> parser = do_QueryInterface(aContext);
parser->SetDocumentCharset(charset, charsetSource); parser->SetDocumentCharset(charset, charsetSource);
@ -318,6 +312,7 @@ txStylesheetSink::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
bool sniff; bool sniff;
if (NS_SUCCEEDED(uri->SchemeIs("file", &sniff)) && sniff && if (NS_SUCCEEDED(uri->SchemeIs("file", &sniff)) && sniff &&
contentType.Equals(UNKNOWN_CONTENT_TYPE)) { contentType.Equals(UNKNOWN_CONTENT_TYPE)) {
nsresult rv;
nsCOMPtr<nsIStreamConverterService> serv = nsCOMPtr<nsIStreamConverterService> serv =
do_GetService("@mozilla.org/streamConverters;1", &rv); do_GetService("@mozilla.org/streamConverters;1", &rv);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {

View File

@ -45,7 +45,7 @@
#include "nsIDocumentTransformer.h" #include "nsIDocumentTransformer.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsIParser.h" #include "nsIParser.h"
#include "nsICharsetAlias.h" #include "nsCharsetAlias.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "txURIUtils.h" #include "txURIUtils.h"
#include "nsContentCreatorFunctions.h" #include "nsContentCreatorFunctions.h"
@ -184,11 +184,9 @@ txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument)
if (!mOutputFormat.mEncoding.IsEmpty()) { if (!mOutputFormat.mEncoding.IsEmpty()) {
NS_LossyConvertUTF16toASCII charset(mOutputFormat.mEncoding); NS_LossyConvertUTF16toASCII charset(mOutputFormat.mEncoding);
nsCAutoString canonicalCharset; nsCAutoString canonicalCharset;
nsCOMPtr<nsICharsetAlias> calias =
do_GetService("@mozilla.org/intl/charsetalias;1");
if (calias && if (NS_SUCCEEDED(nsCharsetAlias::GetPreferred(charset,
NS_SUCCEEDED(calias->GetPreferred(charset, canonicalCharset))) { canonicalCharset))) {
mDocument->SetDocumentCharacterSetSource(kCharsetFromOtherComponent); mDocument->SetDocumentCharacterSetSource(kCharsetFromOtherComponent);
mDocument->SetDocumentCharacterSet(canonicalCharset); mDocument->SetDocumentCharacterSet(canonicalCharset);
} }

View File

@ -64,7 +64,7 @@
#include "nsIDocumentTransformer.h" #include "nsIDocumentTransformer.h"
#include "mozilla/css/Loader.h" #include "mozilla/css/Loader.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
#include "nsICharsetAlias.h" #include "nsCharsetAlias.h"
#include "nsIHTMLContentSink.h" #include "nsIHTMLContentSink.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "txXMLUtils.h" #include "txXMLUtils.h"
@ -857,11 +857,7 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, PRInt32 aNsID
if (!mOutputFormat.mEncoding.IsEmpty()) { if (!mOutputFormat.mEncoding.IsEmpty()) {
NS_LossyConvertUTF16toASCII charset(mOutputFormat.mEncoding); NS_LossyConvertUTF16toASCII charset(mOutputFormat.mEncoding);
nsCAutoString canonicalCharset; nsCAutoString canonicalCharset;
nsCOMPtr<nsICharsetAlias> calias = if (NS_SUCCEEDED(nsCharsetAlias::GetPreferred(charset, canonicalCharset))) {
do_GetService("@mozilla.org/intl/charsetalias;1");
if (calias &&
NS_SUCCEEDED(calias->GetPreferred(charset, canonicalCharset))) {
mDocument->SetDocumentCharacterSetSource(kCharsetFromOtherComponent); mDocument->SetDocumentCharacterSetSource(kCharsetFromOtherComponent);
mDocument->SetDocumentCharacterSet(canonicalCharset); mDocument->SetDocumentCharacterSet(canonicalCharset);
} }

View File

@ -0,0 +1,80 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* helper object for APIs that deal with DOMRequest and need to release them properly
* when the window goes out of scope
*/
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
let EXPORTED_SYMBOLS = ["DOMRequestIpcHelper"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(Services, "rs", function() {
return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
});
XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
});
function DOMRequestIpcHelper() {
}
DOMRequestIpcHelper.prototype = {
getRequestId: function(aRequest) {
let id = "id" + this._getRandomId();
this._requests[id] = aRequest;
return id;
},
getRequest: function(aId) {
if (this._requests[aId])
return this._requests[aId];
},
removeRequest: function(aId) {
if (this._requests[aId])
delete this._requests[aId];
},
_getRandomId: function() {
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
},
observe: function(aSubject, aTopic, aData) {
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
if (wId == this.innerWindowID) {
Services.obs.removeObserver(this, "inner-window-destroyed");
this._requests = [];
this._window = null;
this._messages.forEach((function(msgName) {
cpmm.removeMessageListener(msgName, this);
}).bind(this));
if(this.uninit)
this.uninit();
}
},
initHelper: function(aWindow, aMessages) {
this._messages = aMessages;
this._requests = [];
this._window = aWindow;
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
this.innerWindowID = util.currentInnerWindowID;
this._id = this._getRandomId();
Services.obs.addObserver(this, "inner-window-destroyed", false);
this._messages.forEach((function(msgName) {
cpmm.addMessageListener(msgName, this);
}).bind(this));
},
createRequest: function() {
return Services.rs.createRequest(this._window);
}
}

View File

@ -69,6 +69,9 @@ EXTRA_JS_MODULES += Webapps.jsm \
$(NULL) $(NULL)
endif endif
EXTRA_JS_MODULES += DOMRequestHelper.jsm \
$(NULL)
XPIDLSRCS = \ XPIDLSRCS = \
nsIDOMDOMError.idl \ nsIDOMDOMError.idl \
nsIDOMDOMRequest.idl \ nsIDOMDOMRequest.idl \

View File

@ -70,6 +70,8 @@
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "BatteryManager.h" #include "BatteryManager.h"
#include "PowerManager.h" #include "PowerManager.h"
#include "nsIDOMWakeLock.h"
#include "nsIPowerManagerService.h"
#include "SmsManager.h" #include "SmsManager.h"
#include "nsISmsService.h" #include "nsISmsService.h"
#include "mozilla/Hal.h" #include "mozilla/Hal.h"
@ -172,7 +174,10 @@ Navigator::Invalidate()
mBatteryManager = nsnull; mBatteryManager = nsnull;
} }
mPowerManager = nsnull; if (mPowerManager) {
mPowerManager->Shutdown();
mPowerManager = nsnull;
}
if (mSmsManager) { if (mSmsManager) {
mSmsManager->Shutdown(); mSmsManager->Shutdown();
@ -958,15 +963,38 @@ Navigator::GetMozBattery(nsIDOMMozBatteryManager** aBattery)
NS_IMETHODIMP NS_IMETHODIMP
Navigator::GetMozPower(nsIDOMMozPowerManager** aPower) Navigator::GetMozPower(nsIDOMMozPowerManager** aPower)
{ {
*aPower = nsnull;
if (!mPowerManager) { if (!mPowerManager) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(win, NS_OK);
mPowerManager = new power::PowerManager(); mPowerManager = new power::PowerManager();
mPowerManager->Init(win);
} }
NS_ADDREF(*aPower = mPowerManager); nsCOMPtr<nsIDOMMozPowerManager> power =
do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMMozPowerManager*, mPowerManager));
power.forget(aPower);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
Navigator::RequestWakeLock(const nsAString &aTopic, nsIDOMMozWakeLock **aWakeLock)
{
*aWakeLock = nsnull;
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(win, NS_OK);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_TRUE(pmService, NS_OK);
return pmService->NewWakeLock(aTopic, win, aWakeLock);
}
//***************************************************************************** //*****************************************************************************
// Navigator::nsIDOMNavigatorSms // Navigator::nsIDOMNavigatorSms
//***************************************************************************** //*****************************************************************************

View File

@ -1,38 +1,6 @@
/* ***** BEGIN LICENSE BLOCK ***** /* This Source Code Form is subject to the terms of the Mozilla Public
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* * You can obtain one at http://mozilla.org/MPL/2.0/. */
* 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 Open Web Apps.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Fabrice Desré <fabrice@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
@ -41,27 +9,31 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
XPCOMUtils.defineLazyGetter(Services, "rs", function() {
return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
});
XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
});
function convertAppsArray(aApps, aWindow) {
let apps = new Array();
for (let i = 0; i < aApps.length; i++) {
let app = aApps[i];
apps.push(new WebappsApplication(aWindow, app.origin, app.manifest, app.manifestURL,
app.receipts, app.installOrigin, app.installTime));
}
return apps;
}
function WebappsRegistry() { function WebappsRegistry() {
this.messages = ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
"Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO",
"Webapps:Enumerate:Return:OK", "Webapps:Enumerate:Return:KO"];
this.mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
this.messages.forEach((function(msgName) {
this.mm.addMessageListener(msgName, this);
}).bind(this));
this._window = null;
this._id = this._getRandomId();
this._callbacks = [];
} }
WebappsRegistry.prototype = { WebappsRegistry.prototype = {
_onerror: null, __proto__: DOMRequestIpcHelper.prototype,
_oninstall: null,
_onuninstall: null,
/** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest /** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest
* only the name property is mandatory * only the name property is mandatory
@ -70,7 +42,7 @@ WebappsRegistry.prototype = {
// TODO : check for install_allowed_from // TODO : check for install_allowed_from
if (aManifest.name == undefined) if (aManifest.name == undefined)
return false; return false;
if (aManifest.installs_allowed_from) { if (aManifest.installs_allowed_from) {
ok = false; ok = false;
aManifest.installs_allowed_from.forEach(function(aOrigin) { aManifest.installs_allowed_from.forEach(function(aOrigin) {
@ -81,97 +53,41 @@ WebappsRegistry.prototype = {
} }
return true; return true;
}, },
getCallbackId: function(aCallback) {
let id = "id" + this._getRandomId();
this._callbacks[id] = aCallback;
return id;
},
getCallback: function(aId) {
return this._callbacks[aId];
},
removeCallback: function(aId) {
if (this._callbacks[aId])
delete this._callbacks[aId];
},
_getRandomId: function() {
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
},
_convertAppsArray: function(aApps) {
let apps = new Array();
for (let i = 0; i < aApps.length; i++) {
let app = aApps[i];
apps.push(new WebappsApplication(app.origin, app.manifest, app.receipt, app.installOrigin, app.installTime));
}
return apps;
},
set oninstall(aCallback) {
if (this.hasPrivileges)
this._oninstall = aCallback;
else
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
set onuninstall(aCallback) {
if (this.hasPrivileges)
this._onuninstall = aCallback;
else
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
set onerror(aCallback) {
this._onerror = aCallback;
},
receiveMessage: function(aMessage) { receiveMessage: function(aMessage) {
let msg = aMessage.json; let msg = aMessage.json;
if (!(msg.oid == this._id || aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Return:OK")) if (msg.oid != this._id)
return return
let req = this.getRequest(msg.requestID);
if (!req)
return;
let app = msg.app; let app = msg.app;
let cb;
switch (aMessage.name) { switch (aMessage.name) {
case "Webapps:Install:Return:OK": case "Webapps:Install:Return:OK":
if (this._oninstall) Services.rs.fireSuccess(req, new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
this._oninstall.handleEvent(new WebappsApplication(app.origin, app.manifest, app.receipt,
app.installOrigin, app.installTime)); app.installOrigin, app.installTime));
break; break;
case "Webapps:Install:Return:KO": case "Webapps:Install:Return:KO":
if (this._onerror) Services.rs.fireError(req, "DENIED");
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.DENIED));
break; break;
case "Webapps:Uninstall:Return:OK": case "Webapps:GetSelf:Return:OK":
if (this._onuninstall) if (msg.apps.length) {
this._onuninstall.handleEvent(new WebappsApplication(msg.origin, null, null, null, 0)); app = msg.apps[0];
break; Services.rs.fireSuccess(req, new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
case "Webapps:Uninstall:Return:KO": app.installOrigin, app.installTime));
if (this._onerror) } else {
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED)); Services.rs.fireSuccess(req, null);
break;
case "Webapps:Enumerate:Return:OK":
cb = this.getCallback(msg.callbackID);
if (cb.success) {
let apps = this._convertAppsArray(msg.apps);
cb.success.handleEvent(apps, apps.length);
} }
break; break;
case "Webapps:Enumerate:Return:KO": case "Webapps:GetInstalled:Return:OK":
cb = this.getCallback(msg.callbackID); Services.rs.fireSuccess(req, convertAppsArray(msg.apps, this._window));
if (cb.error) break;
cb.error.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED)); case "Webapps:GetSelf:Return:KO":
case "Webapps:GetInstalled:Return:KO":
Services.rs.fireError(req, "ERROR");
break; break;
} }
this.removeCallback(msg.callbackID); this.removeRequest(msg.requestID);
},
_fireError: function(aCode) {
if (!this._onerror)
return;
this._onerror.handleEvent(new RegistryError(aCode));
}, },
_getOrigin: function(aURL) { _getOrigin: function(aURL) {
@ -181,7 +97,9 @@ WebappsRegistry.prototype = {
// mozIDOMApplicationRegistry implementation // mozIDOMApplicationRegistry implementation
install: function(aURL, aReceipt) { install: function(aURL, aParams) {
let request = this.createRequest();
let requestID = this.getRequestId(request);
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest); let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
xhr.open("GET", aURL, true); xhr.open("GET", aURL, true);
@ -191,90 +109,70 @@ WebappsRegistry.prototype = {
let installOrigin = this._getOrigin(this._window.location.href); let installOrigin = this._getOrigin(this._window.location.href);
let manifest = JSON.parse(xhr.responseText, installOrigin); let manifest = JSON.parse(xhr.responseText, installOrigin);
if (!this.checkManifest(manifest, installOrigin)) { if (!this.checkManifest(manifest, installOrigin)) {
this._fireError(Ci.mozIDOMApplicationRegistryError.INVALID_MANIFEST); Services.rs.fireError(request, "INVALID_MANIFEST");
} else { } else {
this.mm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin, let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : [];
origin: this._getOrigin(aURL), cpmm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
manifest: manifest, origin: this._getOrigin(aURL),
receipt: aReceipt }, manifestURL: aURL,
from: this._window.location.href, manifest: manifest,
oid: this._id }); receipts: receipts },
from: this._window.location.href,
oid: this._id,
requestID: requestID });
} }
} catch(e) { } catch(e) {
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_PARSE_ERROR); Services.rs.fireError(request, "MANIFEST_PARSE_ERROR");
} }
} }
else { else {
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_URL_ERROR); Services.rs.fireError(request, "MANIFEST_URL_ERROR");
} }
}).bind(this), false); }).bind(this), false);
xhr.addEventListener("error", (function() { xhr.addEventListener("error", (function() {
this._fireError(Ci.mozIDOMApplicationRegistryError.NETWORK_ERROR); Services.rs.fireError(request, "NETWORK_ERROR");
}).bind(this), false); }).bind(this), false);
xhr.send(null); xhr.send(null);
return request;
}, },
uninstall: function(aOrigin) { getSelf: function() {
if (this.hasPrivileges) let request = this.createRequest();
this.mm.sendAsyncMessage("Webapps:Uninstall", { from: this._window.location.href, cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
origin: aOrigin, oid: this._id,
oid: this._id }); requestID: this.getRequestId(request) });
else return request;
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
}, },
launch: function(aOrigin) { getInstalled: function() {
this.mm.sendAsyncMessage("Webapps:Launch", { origin: aOrigin, let request = this.createRequest();
from: this._window.location.href}); cpmm.sendAsyncMessage("Webapps:GetInstalled", { origin: this._getOrigin(this._window.location.href),
},
enumerate: function(aSuccess, aError) {
this.mm.sendAsyncMessage("Webapps:Enumerate", { from: this._window.location.href,
origin: this._getOrigin(this._window.location.href),
oid: this._id, oid: this._id,
callbackID: this.getCallbackId({ success: aSuccess, error: aError }) }); requestID: this.getRequestId(request) });
return request;
}, },
enumerateAll: function(aSuccess, aError) { get mgmt() {
if (this.hasPrivileges) { if (!this._mgmt)
this.mm.sendAsyncMessage("Webapps:EnumerateAll", { from: this._window.location.href, this._mgmt = new WebappsApplicationMgmt(this._window);
origin: this._getOrigin(this._window.location.href), return this._mgmt;
oid: this._id,
callbackID: this.getCallbackId({ success: aSuccess, error: aError }) });
} else {
if (aError)
aError.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
}
}, },
observe: function(aSubject, aTopic, aData) { uninit: function() {
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; this._mgmt = null;
if (wId == this.innerWindowID) {
Services.obs.removeObserver(this, "inner-window-destroyed");
this._oninstall = null;
this._onuninstall = null;
this._onerror = null;
this._callbacks = [];
this._window = null;
}
}, },
// nsIDOMGlobalPropertyInitializer implementation // nsIDOMGlobalPropertyInitializer implementation
init: function(aWindow) { init: function(aWindow) {
dump("DOMApplicationRegistry::init() " + aWindow + "\n"); this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
this._window = aWindow; "Webapps:GetInstalled:Return:OK", "Webapps:GetInstalled:Return:KO",
this._window.appId = this._id; "Webapps:GetSelf:Return:OK", "Webapps:GetSelf:Return:KO"]);
let from = Services.io.newURI(this._window.location.href, null, null);
let perm = Services.perms.testExactPermission(from, "webapps-manage");
//only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
Services.obs.addObserver(this, "inner-window-destroyed", false); Services.obs.addObserver(this, "inner-window-destroyed", false);
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
this.innerWindowID = util.currentInnerWindowID; this._id = util.outerWindowID;
}, },
classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"), classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
@ -288,18 +186,26 @@ WebappsRegistry.prototype = {
classDescription: "Webapps Registry"}) classDescription: "Webapps Registry"})
} }
function WebappsApplication(aOrigin, aManifest, aReceipt, aInstallOrigin, aInstallTime) { /**
* mozIDOMApplication object
*/
function WebappsApplication(aWindow, aOrigin, aManifest, aManifestURL, aReceipts, aInstallOrigin, aInstallTime) {
this._origin = aOrigin; this._origin = aOrigin;
this._manifest = aManifest; this._manifest = aManifest;
this._receipt = aReceipt; this._manifestURL = aManifestURL;
this._receipts = aReceipts;
this._installOrigin = aInstallOrigin; this._installOrigin = aInstallOrigin;
this._installTime = aInstallTime; this._installTime = aInstallTime;
this.initHelper(aWindow, ["Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO"]);
} }
WebappsApplication.prototype = { WebappsApplication.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
_origin: null, _origin: null,
_manifest: null, _manifest: null,
_receipt: null, _manifestURL: null,
_receipts: [],
_installOrigin: null, _installOrigin: null,
_installTime: 0, _installTime: 0,
@ -311,8 +217,12 @@ WebappsApplication.prototype = {
return this._manifest; return this._manifest;
}, },
get receipt() { get manifestURL() {
return this._receipt; return this._manifestURL;
},
get receipts() {
return this._receipts;
}, },
get installOrigin() { get installOrigin() {
@ -323,6 +233,39 @@ WebappsApplication.prototype = {
return this._installTime; return this._installTime;
}, },
launch: function(aStartPoint) {
let request = this.createRequest();
cpmm.sendAsyncMessage("Webapps:Launch", { origin: this._origin,
startPoint: aStartPoint,
oid: this._id,
requestID: this.getRequestId(request) });
return request;
},
uninstall: function() {
let request = this.createRequest();
cpmm.sendAsyncMessage("Webapps:Uninstall", { origin: this._origin,
oid: this._id,
requestID: this.getRequestId(request) });
return request;
},
receiveMessage: function(aMessage) {
var msg = aMessage.json;
let req = this.getRequest(msg.requestID);
if (msg.oid != this._id || !req)
return;
switch (aMessage.name) {
case "Webapps:Uninstall:Return:OK":
Services.rs.fireSuccess(req, msg.origin);
break;
case "Webapps:Uninstall:Return:KO":
Services.rs.fireError(req, msg.origin);
break;
}
this.removeRequest(msg.requestID);
},
classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"), classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication]), QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication]),
@ -334,26 +277,131 @@ WebappsApplication.prototype = {
classDescription: "Webapps Application"}) classDescription: "Webapps Application"})
} }
function RegistryError(aCode) { /**
this._code = aCode; * mozIDOMApplicationMgmt object
*/
function WebappsApplicationMgmt(aWindow) {
let principal = aWindow.document.nodePrincipal;
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
let perm = principal == secMan.getSystemPrincipal() ?
Ci.nsIPermissionManager.ALLOW_ACTION :
Services.perms.testExactPermission(principal.URI, "webapps-manage");
//only pages with perm set can use some functions
this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
this.initHelper(aWindow, ["Webapps:GetAll:Return:OK", "Webapps:GetAll:Return:KO",
"Webapps:Install:Return:OK", "Webapps:Uninstall:Return:OK"]);
this._oninstall = null;
this._onuninstall = null;
} }
RegistryError.prototype = { WebappsApplicationMgmt.prototype = {
_code: null, __proto__: DOMRequestIpcHelper.prototype,
get code() { uninit: function() {
return this._code; this._oninstall = null;
this._onuninstall = null;
}, },
classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistryError]), getAll: function() {
let request = this.createRequest();
cpmm.sendAsyncMessage("Webapps:GetAll", { oid: this._id,
requestID: this.getRequestId(request),
hasPrivileges: this.hasPrivileges });
return request;
},
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"), get oninstall() {
contractID: "@mozilla.org/webapps/error;1", return this._oninstall;
interfaces: [Ci.mozIDOMApplicationRegistryError], },
get onuninstall() {
this._onuninstall;
},
set oninstall(aCallback) {
if (this.hasPrivileges)
this._oninstall = aCallback;
else
throw new Components.exception("Denied", Cr.NS_ERROR_FAILURE);
},
set onuninstall(aCallback) {
if (this.hasPrivileges)
this._onuninstall = aCallback;
else
throw new Components.exception("Denied", Cr.NS_ERROR_FAILURE);
},
receiveMessage: function(aMessage) {
var msg = aMessage.json;
let req = this.getRequest(msg.requestID);
// We want Webapps:Install:Return:OK and Webapps:Uninstall:Return:OK to be boradcasted
// to all instances of mozApps.mgmt
if (!((msg.oid == this._id && req)
|| aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Return:OK"))
return;
switch (aMessage.name) {
case "Webapps:GetAll:Return:OK":
Services.rs.fireSuccess(req, convertAppsArray(msg.apps, this._window));
break;
case "Webapps:GetAll:Return:KO":
Services.rs.fireError(req, "DENIED");
break;
case "Webapps:Install:Return:OK":
if (this._oninstall) {
let app = msg.app;
let event = new WebappsApplicationEvent(new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
app.installOrigin, app.installTime));
this._oninstall.handleEvent(event);
}
break;
case "Webapps:Uninstall:Return:OK":
if (this._onuninstall) {
let event = new WebappsApplicationEvent(new WebappsApplication(this._window, msg.origin, null, null, null, null, 0));
this._onuninstall.handleEvent(event);
}
break;
}
this.removeRequest(msg.requestID);
},
classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationMgmt]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
contractID: "@mozilla.org/webapps/application-mgmt;1",
interfaces: [Ci.mozIDOMApplicationMgmt],
flags: Ci.nsIClassInfo.DOM_OBJECT, flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Webapps Registry Error"}) classDescription: "Webapps Application Mgmt"})
} }
const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry, WebappsApplication, RegistryError]); /**
* mozIDOMApplicationEvent object
*/
function WebappsApplicationEvent(aApp) {
this._app = aApp;
}
WebappsApplicationEvent.prototype = {
get application() {
return this._app;
},
classID: Components.ID("{5bc42b2a-9acc-49d5-a336-c353c8125e48}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationEvent]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
contractID: "@mozilla.org/webapps/application-event;1",
interfaces: [Ci.mozIDOMApplicationEvent],
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Webapps Application Event"})
}
const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry, WebappsApplication]);

View File

@ -1,39 +1,6 @@
/* ***** BEGIN LICENSE BLOCK ***** /* This Source Code Form is subject to the terms of the Mozilla Public
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
* * You can obtain one at http://mozilla.org/MPL/2.0/. */
* 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 Mobile Browser.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Fabrice Desré <fabrice@mozilla.com>
* Mark Finkle <mfinkle@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const Cu = Components.utils; const Cu = Components.utils;
const Cc = Components.classes; const Cc = Components.classes;
@ -50,17 +17,21 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
return NetUtil; return NetUtil;
}); });
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
});
let DOMApplicationRegistry = { let DOMApplicationRegistry = {
appsFile: null, appsFile: null,
webapps: { }, webapps: { },
init: function() { init: function() {
this.mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
let messages = ["Webapps:Install", "Webapps:Uninstall", let messages = ["Webapps:Install", "Webapps:Uninstall",
"Webapps:Enumerate", "Webapps:EnumerateAll", "Webapps:Launch"]; "Webapps:GetSelf", "Webapps:GetInstalled",
"Webapps:Launch", "Webapps:GetAll"];
messages.forEach((function(msgName) { messages.forEach((function(msgName) {
this.mm.addMessageListener(msgName, this); ppmm.addMessageListener(msgName, this);
}).bind(this)); }).bind(this));
let appsDir = FileUtils.getDir("ProfD", ["webapps"], true, true); let appsDir = FileUtils.getDir("ProfD", ["webapps"], true, true);
@ -114,29 +85,29 @@ let DOMApplicationRegistry = {
receiveMessage: function(aMessage) { receiveMessage: function(aMessage) {
let msg = aMessage.json; let msg = aMessage.json;
let from = Services.io.newURI(msg.from, null, null);
let perm = Services.perms.testExactPermission(from, "webapps-manage");
//only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
let hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
switch (aMessage.name) { switch (aMessage.name) {
case "Webapps:Install": case "Webapps:Install":
// always ask for UI to install // always ask for UI to install
Services.obs.notifyObservers(this, "webapps-ask-install", JSON.stringify(msg)); Services.obs.notifyObservers(this, "webapps-ask-install", JSON.stringify(msg));
break; break;
case "Webapps:GetSelf":
this.getSelf(msg);
break;
case "Webapps:Uninstall": case "Webapps:Uninstall":
if (hasPrivileges) this.uninstall(msg);
this.uninstall(msg);
break; break;
case "Webapps:Launch": case "Webapps:Launch":
Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg)); Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg));
break; break;
case "Webapps:Enumerate": case "Webapps:GetInstalled":
this.enumerate(msg); this.getInstalled(msg);
break; break;
case "Webapps:EnumerateAll": case "Webapps:GetAll":
this.enumerateAll(msg); if (msg.hasPrivileges)
this.getAll(msg);
else
ppmm.sendAsyncMessage("Webapps:GetAll:Return:KO", msg);
break; break;
} }
}, },
@ -162,14 +133,15 @@ let DOMApplicationRegistry = {
let clone = { let clone = {
installOrigin: aApp.installOrigin, installOrigin: aApp.installOrigin,
origin: aApp.origin, origin: aApp.origin,
receipt: aApp.receipt, receipts: aApp.receipts,
installTime: aApp.installTime installTime: aApp.installTime,
manifestURL: aApp.manifestURL
}; };
return clone; return clone;
}, },
denyInstall: function(aData) { denyInstall: function(aData) {
this.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData); ppmm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
}, },
confirmInstall: function(aData, aFromSync) { confirmInstall: function(aData, aFromSync) {
@ -202,7 +174,7 @@ let DOMApplicationRegistry = {
if (!aFromSync) if (!aFromSync)
this._saveApps((function() { this._saveApps((function() {
this.mm.sendAsyncMessage("Webapps:Install:Return:OK", aData); ppmm.sendAsyncMessage("Webapps:Install:Return:OK", aData);
Services.obs.notifyObservers(this, "webapps-sync-install", id); Services.obs.notifyObservers(this, "webapps-sync-install", id);
}).bind(this)); }).bind(this));
}, },
@ -244,9 +216,11 @@ let DOMApplicationRegistry = {
}, },
uninstall: function(aData) { uninstall: function(aData) {
let found = false;
for (let id in this.webapps) { for (let id in this.webapps) {
let app = this.webapps[id]; let app = this.webapps[id];
if (app.origin == aData.origin) { if (app.origin == aData.origin) {
found = true;
delete this.webapps[id]; delete this.webapps[id];
let dir = FileUtils.getDir("ProfD", ["webapps", id], true, true); let dir = FileUtils.getDir("ProfD", ["webapps", id], true, true);
try { try {
@ -254,62 +228,53 @@ let DOMApplicationRegistry = {
} catch (e) { } catch (e) {
} }
this._saveApps((function() { this._saveApps((function() {
this.mm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData); ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
Services.obs.notifyObservers(this, "webapps-sync-uninstall", id); Services.obs.notifyObservers(this, "webapps-sync-uninstall", id);
}).bind(this)); }).bind(this));
} }
} }
if (!found)
ppmm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
}, },
enumerate: function(aData) { getSelf: function(aData) {
aData.apps = []; aData.apps = [];
let tmp = []; let tmp = [];
let selfId;
let id = this._appId(aData.origin); let id = this._appId(aData.origin);
// if it's an app, add itself to the result
if (id) { if (id) {
let app = this._cloneAppObject(this.webapps[id]); let app = this._cloneAppObject(this.webapps[id]);
aData.apps.push(app); aData.apps.push(app);
tmp.push({ id: id }); tmp.push({ id: id });
selfId = id;
} }
// check if it's a store. this._readManifests(tmp, (function(aResult) {
let isStore = false; for (let i = 0; i < aResult.length; i++)
aData.apps[i].manifest = aResult[i].manifest;
ppmm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
}).bind(this));
},
getInstalled: function(aData) {
aData.apps = [];
let tmp = [];
let id = this._appId(aData.origin);
for (id in this.webapps) { for (id in this.webapps) {
let app = this.webapps[id]; if (this.webapps[id].installOrigin == aData.origin) {
if (app.installOrigin == aData.origin) { aData.apps.push(this._cloneAppObject(this.webapps[id]));
isStore = true; tmp.push({ id: id });
break;
}
}
// add all the apps from this store
if (isStore) {
for (id in this.webapps) {
if (id == selfId)
continue;
let app = this._cloneAppObject(this.webapps[id]);
if (app.installOrigin == aData.origin) {
aData.apps.push(app);
tmp.push({ id: id });
}
} }
} }
this._readManifests(tmp, (function(aResult) { this._readManifests(tmp, (function(aResult) {
for (let i = 0; i < aResult.length; i++) for (let i = 0; i < aResult.length; i++)
aData.apps[i].manifest = aResult[i].manifest; aData.apps[i].manifest = aResult[i].manifest;
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData); ppmm.sendAsyncMessage("Webapps:GetInstalled:Return:OK", aData);
}).bind(this)); }).bind(this));
}, },
denyEnumerate: function(aData) { getAll: function(aData) {
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:KO", aData);
},
enumerateAll: function(aData) {
aData.apps = []; aData.apps = [];
let tmp = []; let tmp = [];
@ -322,7 +287,7 @@ let DOMApplicationRegistry = {
this._readManifests(tmp, (function(aResult) { this._readManifests(tmp, (function(aResult) {
for (let i = 0; i < aResult.length; i++) for (let i = 0; i < aResult.length; i++)
aData.apps[i].manifest = aResult[i].manifest; aData.apps[i].manifest = aResult[i].manifest;
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData); ppmm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
}).bind(this)); }).bind(this));
}, },
@ -368,7 +333,7 @@ let DOMApplicationRegistry = {
dir.remove(true); dir.remove(true);
} catch (e) { } catch (e) {
} }
this.mm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin }); ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
} else { } else {
if (!!this.webapps[record.id]) { if (!!this.webapps[record.id]) {
this.webapps[record.id] = record.value; this.webapps[record.id] = record.value;
@ -377,7 +342,7 @@ let DOMApplicationRegistry = {
else { else {
let data = { app: record.value }; let data = { app: record.value };
this.confirmInstall(data, true); this.confirmInstall(data, true);
this.mm.sendAsyncMessage("Webapps:Install:Return:OK", data); ppmm.sendAsyncMessage("Webapps:Install:Return:OK", data);
} }
} }
} }

View File

@ -2,9 +2,3 @@
component {fff440b3-fae2-45c1-bf03-3b5a2e432270} Webapps.js component {fff440b3-fae2-45c1-bf03-3b5a2e432270} Webapps.js
contract @mozilla.org/webapps;1 {fff440b3-fae2-45c1-bf03-3b5a2e432270} contract @mozilla.org/webapps;1 {fff440b3-fae2-45c1-bf03-3b5a2e432270}
category JavaScript-navigator-property mozApps @mozilla.org/webapps;1 category JavaScript-navigator-property mozApps @mozilla.org/webapps;1
component {723ed303-7757-4fb0-b261-4f78b1f6bd22} Webapps.js
contract @mozilla.org/webapps/application;1 {723ed303-7757-4fb0-b261-4f78b1f6bd22}
component {b4937718-11a3-400b-a69f-ab442a418569} Webapps.js
contract @mozilla.org/webapps/error;1 {b4937718-11a3-400b-a69f-ab442a418569}

View File

@ -507,6 +507,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#include "nsIDOMBatteryManager.h" #include "nsIDOMBatteryManager.h"
#include "BatteryManager.h" #include "BatteryManager.h"
#include "nsIDOMPowerManager.h" #include "nsIDOMPowerManager.h"
#include "nsIDOMWakeLock.h"
#include "nsIDOMSmsManager.h" #include "nsIDOMSmsManager.h"
#include "nsIDOMSmsMessage.h" #include "nsIDOMSmsMessage.h"
#include "nsIDOMSmsEvent.h" #include "nsIDOMSmsEvent.h"
@ -548,6 +549,7 @@ static const char kDOMStringBundleURL[] =
nsIXPCScriptable::WANT_ENUMERATE | \ nsIXPCScriptable::WANT_ENUMERATE | \
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \ nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
nsIXPCScriptable::USE_STUB_EQUALITY_HOOK | \ nsIXPCScriptable::USE_STUB_EQUALITY_HOOK | \
nsIXPCScriptable::IS_GLOBAL_OBJECT | \
nsIXPCScriptable::WANT_OUTER_OBJECT) nsIXPCScriptable::WANT_OUTER_OBJECT)
#define NODE_SCRIPTABLE_FLAGS \ #define NODE_SCRIPTABLE_FLAGS \
@ -1435,6 +1437,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozWakeLock, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozSmsManager, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(MozSmsManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1549,7 +1554,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(AnimationEvent, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(AnimationEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH, NS_DEFINE_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS | nsIXPCScriptable::IS_GLOBAL_OBJECT)
NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1617,8 +1622,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
#endif #endif
#ifdef MOZ_B2G_BT #ifdef MOZ_B2G_BT
NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsEventTargetSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS) EVENTTARGET_SCRIPTABLE_FLAGS)
#endif #endif
NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH, NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
@ -4030,6 +4035,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager) DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozWakeLock, nsIDOMMozWakeLock)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozWakeLock)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozSmsManager, nsIDOMMozSmsManager) DOM_CLASSINFO_MAP_BEGIN(MozSmsManager, nsIDOMMozSmsManager)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsManager) DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsManager)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END

View File

@ -429,6 +429,7 @@ DOMCI_CLASS(GeoPositionError)
DOMCI_CLASS(MozBatteryManager) DOMCI_CLASS(MozBatteryManager)
DOMCI_CLASS(MozPowerManager) DOMCI_CLASS(MozPowerManager)
DOMCI_CLASS(MozWakeLock)
DOMCI_CLASS(MozSmsManager) DOMCI_CLASS(MozSmsManager)
DOMCI_CLASS(MozSmsMessage) DOMCI_CLASS(MozSmsMessage)

View File

@ -144,7 +144,11 @@ static PRLogModuleInfo* gJSDiagnostics;
#define NS_CC_SKIPPABLE_DELAY 400 // ms #define NS_CC_SKIPPABLE_DELAY 400 // ms
#define NS_CC_FORCED (5 * 60 * PR_USEC_PER_SEC) // 5 min // Force a CC after this long if there's anything in the purple buffer.
#define NS_CC_FORCED (2 * 60 * PR_USEC_PER_SEC) // 2 min
// Trigger a CC if the purple buffer exceeds this size when we check it.
#define NS_CC_PURPLE_LIMIT 250
#define JAVASCRIPT nsIProgrammingLanguage::JAVASCRIPT #define JAVASCRIPT nsIProgrammingLanguage::JAVASCRIPT
@ -2227,11 +2231,9 @@ nsJSContext::CreateNativeGlobalForInner(
nsRefPtr<nsIXPConnectJSObjectHolder> jsholder; nsRefPtr<nsIXPConnectJSObjectHolder> jsholder;
nsresult rv = xpc-> nsresult rv = xpc->
InitClassesWithNewWrappedGlobal(mContext, InitClassesWithNewWrappedGlobal(mContext, aNewInner,
aNewInner, NS_GET_IID(nsISupports),
aIsChrome ? systemPrincipal.get() : aPrincipal, aIsChrome ? systemPrincipal.get() : aPrincipal,
nsnull, flags, flags, getter_AddRefs(jsholder));
getter_AddRefs(jsholder));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }
@ -2324,7 +2326,7 @@ nsJSContext::SetOuterObject(JSObject* aOuterObject)
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(wrapper, "bad wrapper"); NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
wrapper->RefreshPrototype(); wrapper->FinishInitForWrappedGlobal();
JS_SetPrototype(mContext, aOuterObject, JS_GetPrototype(inner)); JS_SetPrototype(mContext, aOuterObject, JS_GetPrototype(inner));
return NS_OK; return NS_OK;
@ -3286,46 +3288,70 @@ ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
nsJSContext::ShrinkGCBuffersNow(); nsJSContext::ShrinkGCBuffersNow();
} }
// static static bool
void ShouldTriggerCC(PRUint32 aSuspected)
{
return sNeedsFullCC ||
aSuspected > NS_CC_PURPLE_LIMIT ||
sLastCCEndTime + NS_CC_FORCED < PR_Now();
}
static void
TimerFireForgetSkippable(PRUint32 aSuspected, bool aRemoveChildless)
{
PRTime startTime = PR_Now();
nsCycleCollector_forgetSkippable(aRemoveChildless);
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
sCleanupSinceLastGC = true;
PRTime delta = PR_Now() - startTime;
if (sMinForgetSkippableTime > delta) {
sMinForgetSkippableTime = delta;
}
if (sMaxForgetSkippableTime < delta) {
sMaxForgetSkippableTime = delta;
}
sTotalForgetSkippableTime += delta;
sRemovedPurples += (aSuspected - sPreviousSuspectedCount);
++sForgetSkippableBeforeCC;
}
static void
CCTimerFired(nsITimer *aTimer, void *aClosure) CCTimerFired(nsITimer *aTimer, void *aClosure)
{ {
if (sDidShutdown) { if (sDidShutdown || sCCLockedOut) {
return;
}
if (sCCLockedOut) {
return; return;
} }
++sCCTimerFireCount; ++sCCTimerFireCount;
if (sCCTimerFireCount < (NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY)) {
PRUint32 suspected = nsCycleCollector_suspectedCount(); // During early timer fires, we only run forgetSkippable. During the first
if ((sPreviousSuspectedCount + 100) > suspected) { // late timer fire, we decide if we are going to have a second and final
// Just few new suspected objects, return early. // late timer fire, where we may run the CC.
return; const PRUint32 numEarlyTimerFires = NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY - 2;
} bool isLateTimerFire = sCCTimerFireCount > numEarlyTimerFires;
PRUint32 suspected = nsCycleCollector_suspectedCount();
PRTime startTime = PR_Now(); if (isLateTimerFire && ShouldTriggerCC(suspected)) {
nsCycleCollector_forgetSkippable(); if (sCCTimerFireCount == numEarlyTimerFires + 1) {
sPreviousSuspectedCount = nsCycleCollector_suspectedCount(); TimerFireForgetSkippable(suspected, true);
sCleanupSinceLastGC = true; if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
PRTime delta = PR_Now() - startTime; // Our efforts to avoid a CC have failed, so we return to let the
if (sMinForgetSkippableTime > delta) { // timer fire once more to trigger a CC.
sMinForgetSkippableTime = delta; return;
} }
if (sMaxForgetSkippableTime < delta) { } else {
sMaxForgetSkippableTime = delta; // We are in the final timer fire and still meet the conditions for
} // triggering a CC.
sTotalForgetSkippableTime += delta;
sRemovedPurples += (suspected - sPreviousSuspectedCount);
++sForgetSkippableBeforeCC;
} else {
sPreviousSuspectedCount = 0;
nsJSContext::KillCCTimer();
if (sNeedsFullCC ||
nsCycleCollector_suspectedCount() > 500 ||
sLastCCEndTime + NS_CC_FORCED < PR_Now()) {
nsJSContext::CycleCollectNow(); nsJSContext::CycleCollectNow();
} }
} else if ((sPreviousSuspectedCount + 100) <= suspected) {
// Only do a forget skippable if there are more than a few new objects.
TimerFireForgetSkippable(suspected, false);
}
if (isLateTimerFire) {
// We have either just run the CC or decided we don't want to run the CC
// next time, so kill the timer.
sPreviousSuspectedCount = 0;
nsJSContext::KillCCTimer();
} }
} }

View File

@ -16,47 +16,56 @@
#include <bluedroid/bluetooth.h> #include <bluedroid/bluetooth.h>
#endif #endif
#define POWERED_EVENT_NAME NS_LITERAL_STRING("powered") USING_BLUETOOTH_NAMESPACE
BEGIN_BLUETOOTH_NAMESPACE
class ToggleBtResultTask : public nsRunnable class ToggleBtResultTask : public nsRunnable
{ {
public: public:
ToggleBtResultTask(bool result, nsRefPtr<BluetoothAdapter>& adapterPtr) ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, bool result)
: mResult(result) : mResult(result)
{ {
MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread MOZ_ASSERT(!NS_IsMainThread());
mAdapterPtr.swap(adapterPtr); mAdapterPtr.swap(adapterPtr);
} }
NS_IMETHOD Run() { NS_IMETHOD Run()
MOZ_ASSERT(NS_IsMainThread()); // This method is supposed to run on the main thread! {
MOZ_ASSERT(NS_IsMainThread());
if (!mResult) {
//TODO:Bug-731361
NS_WARNING("BT firmware loading fails.\n");
}
//mAdapterPtr must be null before returning to prevent the background
//thread from racing to release it during the destruction of this runnable.
mAdapterPtr->FirePowered(); mAdapterPtr->FirePowered();
mAdapterPtr = nsnull;
return NS_OK; return NS_OK;
} }
private: private:
bool mResult;
nsRefPtr<BluetoothAdapter> mAdapterPtr; nsRefPtr<BluetoothAdapter> mAdapterPtr;
bool mResult;
}; };
class ToggleBtTask : public nsRunnable class ToggleBtTask : public nsRunnable
{ {
public: public:
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr) ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
: mOnOff(onOff), : mOnOff(onOff),
mAdapterPtr(adapterPtr) mAdapterPtr(adapterPtr)
{ {
MOZ_ASSERT(NS_IsMainThread()); // The constructor should be running on the main thread. MOZ_ASSERT(NS_IsMainThread());
} }
NS_IMETHOD Run() { NS_IMETHOD Run()
bool result; {
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread. bool result;
//Toggle BT here //Toggle BT here
#if defined(MOZ_WIDGET_GONK) #if defined(MOZ_WIDGET_GONK)
@ -65,13 +74,16 @@ class ToggleBtTask : public nsRunnable
} else { } else {
result = bt_disable(); result = bt_disable();
} }
#else #else
result = true; result = true;
#endif #endif
// Create a result thread and pass it to Main Thread, // Create a result thread and pass it to Main Thread,
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(result, mAdapterPtr); nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, result);
NS_DispatchToMainThread(resultRunnable);
if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
NS_WARNING("Failed to dispatch to main thread!");
}
return NS_OK; return NS_OK;
} }
@ -81,25 +93,21 @@ class ToggleBtTask : public nsRunnable
bool mOnOff; bool mOnOff;
}; };
END_BLUETOOTH_NAMESPACE DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
DOMCI_DATA(BluetoothAdapter, mozilla::dom::bluetooth::BluetoothAdapter)
USING_BLUETOOTH_NAMESPACE
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter) NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper) nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered) NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter, NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper) nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered) NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter) NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
@ -107,18 +115,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
BluetoothAdapter::BluetoothAdapter() : mPower(false) BluetoothAdapter::BluetoothAdapter()
: mPower(false)
{ {
} }
NS_IMETHODIMP NS_IMETHODIMP
BluetoothAdapter::GetPower(bool* aPower) BluetoothAdapter::GetPower(bool* aPower)
{ {
#if defined(MOZ_WIDGET_GONK)
*aPower = bt_is_enabled();
#else
*aPower = mPower; *aPower = mPower;
#endif
return NS_OK; return NS_OK;
} }
@ -128,13 +134,13 @@ BluetoothAdapter::SetPower(bool aPower)
if (mPower != aPower) { if (mPower != aPower) {
mPower = aPower; mPower = aPower;
ToggleBluetoothAsync(); return ToggleBluetoothAsync();
} }
return NS_OK; return NS_OK;
} }
void nsresult
BluetoothAdapter::ToggleBluetoothAsync() BluetoothAdapter::ToggleBluetoothAsync()
{ {
if (!mToggleBtThread) { if (!mToggleBtThread) {
@ -143,14 +149,17 @@ BluetoothAdapter::ToggleBluetoothAsync()
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this); nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
mToggleBtThread->Dispatch(r, 0); return mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
} }
nsresult nsresult
BluetoothAdapter::FirePowered() BluetoothAdapter::FirePowered()
{ {
nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull); nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
nsresult rv = event->InitEvent(POWERED_EVENT_NAME, false, false); nsresult rv = event->InitEvent(NS_LITERAL_STRING("powered"), false, false);
NS_ENSURE_SUCCESS(rv, rv);
rv = event->SetTrusted(true);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
bool dummy; bool dummy;

View File

@ -11,10 +11,12 @@
#include "nsDOMEventTargetHelper.h" #include "nsDOMEventTargetHelper.h"
#include "nsIDOMBluetoothAdapter.h" #include "nsIDOMBluetoothAdapter.h"
class nsIEventTarget;
BEGIN_BLUETOOTH_NAMESPACE BEGIN_BLUETOOTH_NAMESPACE
class BluetoothAdapter : public nsIDOMBluetoothAdapter class BluetoothAdapter : public nsIDOMBluetoothAdapter
,public nsDOMEventTargetHelper , public nsDOMEventTargetHelper
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -36,7 +38,7 @@ protected:
private: private:
nsCOMPtr<nsIEventTarget> mToggleBtThread; nsCOMPtr<nsIEventTarget> mToggleBtThread;
void ToggleBluetoothAsync(); nsresult ToggleBluetoothAsync();
}; };
END_BLUETOOTH_NAMESPACE END_BLUETOOTH_NAMESPACE

View File

@ -17,6 +17,15 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
XPCOMUtils.defineLazyGetter(Services, "rs", function() {
return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
});
XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
});
const nsIClassInfo = Ci.nsIClassInfo; const nsIClassInfo = Ci.nsIClassInfo;
const CONTACTPROPERTIES_CID = Components.ID("{53ed7c20-ceda-11e0-9572-0800200c9a66}"); const CONTACTPROPERTIES_CID = Components.ID("{53ed7c20-ceda-11e0-9572-0800200c9a66}");
@ -184,6 +193,7 @@ function ContactManager()
} }
ContactManager.prototype = { ContactManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
save: function save(aContact) { save: function save(aContact) {
let request; let request;
@ -222,9 +232,9 @@ ContactManager.prototype = {
this._setMetaData(newContact, aContact); this._setMetaData(newContact, aContact);
debug("send: " + JSON.stringify(newContact)); debug("send: " + JSON.stringify(newContact));
request = this._rs.createRequest(this._window); request = this.createRequest();
this._mm.sendAsyncMessage("Contact:Save", {contact: newContact, cpmm.sendAsyncMessage("Contact:Save", {contact: newContact,
requestID: this.getRequestId({ request: request })}); requestID: this.getRequestId(request)});
return request; return request;
} else { } else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED; throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -234,9 +244,9 @@ ContactManager.prototype = {
remove: function removeContact(aRecord) { remove: function removeContact(aRecord) {
let request; let request;
if (this.hasPrivileges) { if (this.hasPrivileges) {
request = this._rs.createRequest(this._window); request = this.createRequest();
this._mm.sendAsyncMessage("Contact:Remove", {id: aRecord.id, cpmm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
requestID: this.getRequestId({ request: request })}); requestID: this.getRequestId(request)});
return request; return request;
} else { } else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED; throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -260,26 +270,6 @@ ContactManager.prototype = {
return contacts; return contacts;
}, },
getRequestId: function(aRequest) {
let id = "id" + this._getRandomId();
this._requests[id] = aRequest;
return id;
},
getRequest: function(aId) {
if (this._requests[aId])
return this._requests[aId].request;
},
removeRequest: function(aId) {
if (this._requests[aId])
delete this._requests[aId];
},
_getRandomId: function() {
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
},
receiveMessage: function(aMessage) { receiveMessage: function(aMessage) {
debug("Contactmanager::receiveMessage: " + aMessage.name); debug("Contactmanager::receiveMessage: " + aMessage.name);
let msg = aMessage.json; let msg = aMessage.json;
@ -291,7 +281,7 @@ ContactManager.prototype = {
if (req) { if (req) {
let result = this._convertContactsArray(contacts); let result = this._convertContactsArray(contacts);
debug("result: " + JSON.stringify(result)); debug("result: " + JSON.stringify(result));
this._rs.fireSuccess(req, result); Services.rs.fireSuccess(req, result);
} else { } else {
debug("no request stored!" + msg.requestID); debug("no request stored!" + msg.requestID);
} }
@ -301,7 +291,7 @@ ContactManager.prototype = {
case "Contact:Remove:Return:OK": case "Contact:Remove:Return:OK":
req = this.getRequest(msg.requestID); req = this.getRequest(msg.requestID);
if (req) if (req)
this._rs.fireSuccess(req, 0); Services.rs.fireSuccess(req, null);
break; break;
case "Contacts:Find:Return:KO": case "Contacts:Find:Return:KO":
case "Contact:Save:Return:KO": case "Contact:Save:Return:KO":
@ -309,7 +299,7 @@ ContactManager.prototype = {
case "Contacts:Clear:Return:KO": case "Contacts:Clear:Return:KO":
req = this.getRequest(msg.requestID); req = this.getRequest(msg.requestID);
if (req) if (req)
this._rs.fireError(req, msg.errorMsg); Services.rs.fireError(req, msg.errorMsg);
break; break;
default: default:
debug("Wrong message: " + aMessage.name); debug("Wrong message: " + aMessage.name);
@ -320,9 +310,9 @@ ContactManager.prototype = {
find: function(aOptions) { find: function(aOptions) {
let request; let request;
if (this.hasPrivileges) { if (this.hasPrivileges) {
request = this._rs.createRequest(this._window); request = this.createRequest();
this._mm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions, cpmm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions,
requestID: this.getRequestId({ request: request })}); requestID: this.getRequestId(request)});
return request; return request;
} else { } else {
debug("find not allowed"); debug("find not allowed");
@ -333,8 +323,8 @@ ContactManager.prototype = {
clear: function() { clear: function() {
let request; let request;
if (this.hasPrivileges) { if (this.hasPrivileges) {
request = this._rs.createRequest(this._window); request = this.createRequest();
this._mm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId({ request: request })}); cpmm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId(request)});
return request; return request;
} else { } else {
debug("clear not allowed"); debug("clear not allowed");
@ -347,22 +337,12 @@ ContactManager.prototype = {
if (!Services.prefs.getBoolPref("dom.mozContacts.enabled")) if (!Services.prefs.getBoolPref("dom.mozContacts.enabled"))
return null; return null;
this._window = aWindow; this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
this._messages = ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
"Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO", "Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
"Contact:Save:Return:OK", "Contact:Save:Return:KO", "Contact:Save:Return:OK", "Contact:Save:Return:KO",
"Contact:Remove:Return:OK", "Contact:Remove:Return:KO"]; "Contact:Remove:Return:OK", "Contact:Remove:Return:KO"]);
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
this._messages.forEach((function(msgName) {
this._mm.addMessageListener(msgName, this);
}).bind(this));
this._rs = Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
this._requests = [];
Services.obs.addObserver(this, "inner-window-destroyed", false); Services.obs.addObserver(this, "inner-window-destroyed", false);
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
this._innerWindowID = util.currentInnerWindowID;
let principal = aWindow.document.nodePrincipal; let principal = aWindow.document.nodePrincipal;
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
@ -376,21 +356,6 @@ ContactManager.prototype = {
debug("has privileges :" + this.hasPrivileges); debug("has privileges :" + this.hasPrivileges);
}, },
observe: function(aSubject, aTopic, aData) {
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
if (wId == this.innerWindowID) {
Services.obs.removeObserver(this, "inner-window-destroyed");
this._messages.forEach((function(msgName) {
this._mm.removeMessageListener(msgName, this);
}).bind(this));
this._mm = null;
this._messages = null;
this._requests = null;
this._window = null;
this._innerWindowID = null;
}
},
classID : CONTACTMANAGER_CID, classID : CONTACTMANAGER_CID,
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager, Ci.nsIDOMGlobalPropertyInitializer]), QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager, Ci.nsIDOMGlobalPropertyInitializer]),

View File

@ -20,16 +20,18 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/ContactDB.jsm"); Cu.import("resource://gre/modules/ContactDB.jsm");
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
});
let myGlobal = this; let myGlobal = this;
let DOMContactManager = { let DOMContactManager = {
init: function() { init: function() {
debug("Init"); debug("Init");
this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
this._messages = ["Contacts:Find", "Contacts:Clear", "Contact:Save", "Contact:Remove"]; this._messages = ["Contacts:Find", "Contacts:Clear", "Contact:Save", "Contact:Remove"];
this._messages.forEach((function(msgName) { this._messages.forEach((function(msgName) {
this._mm.addMessageListener(msgName, this); ppmm.addMessageListener(msgName, this);
}).bind(this)); }).bind(this));
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager); var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
@ -52,10 +54,10 @@ let DOMContactManager = {
observe: function(aSubject, aTopic, aData) { observe: function(aSubject, aTopic, aData) {
myGlobal = null; myGlobal = null;
this._messages.forEach((function(msgName) { this._messages.forEach((function(msgName) {
this._mm.removeMessageListener(msgName, this); ppmm.removeMessageListener(msgName, this);
}).bind(this)); }).bind(this));
Services.obs.removeObserver(this, "profile-before-change"); Services.obs.removeObserver(this, "profile-before-change");
this._mm = null; ppmm = null;
this._messages = null; this._messages = null;
if (this._db) if (this._db)
this._db.close(); this._db.close();
@ -72,23 +74,23 @@ let DOMContactManager = {
for (let i in contacts) for (let i in contacts)
result.push(contacts[i]); result.push(contacts[i]);
debug("result:" + JSON.stringify(result)); debug("result:" + JSON.stringify(result));
this._mm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result}); ppmm.sendAsyncMessage("Contacts:Find:Return:OK", {requestID: msg.requestID, contacts: result});
}.bind(this), }.bind(this),
function(aErrorMsg) { this._mm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this), function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Find:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }) }.bind(this),
msg.findOptions); msg.findOptions);
break; break;
case "Contact:Save": case "Contact:Save":
this._db.saveContact(msg.contact, function() {this._mm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this), this._db.saveContact(msg.contact, function() { ppmm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { this._mm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)); function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
break; break;
case "Contact:Remove": case "Contact:Remove":
this._db.removeContact(msg.id, this._db.removeContact(msg.id,
function() {this._mm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this), function() { ppmm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) {this._mm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)); function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
break; break;
case "Contacts:Clear": case "Contacts:Clear":
this._db.clear(function() { this._mm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this), this._db.clear(function() { ppmm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { this._mm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)); function(aErrorMsg) { ppmm.sendAsyncMessage("Contacts:Clear:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
} }
} }
} }

View File

@ -90,7 +90,7 @@ ConvertCloneReadInfosToArrayInternal(
} }
if (!aReadInfos.IsEmpty()) { if (!aReadInfos.IsEmpty()) {
if (!JS_SetArrayLength(aCx, array, jsuint(aReadInfos.Length()))) { if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
NS_WARNING("Failed to set array length!"); NS_WARNING("Failed to set array length!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }

View File

@ -410,7 +410,7 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
JSObject* obj = JSVAL_TO_OBJECT(val); JSObject* obj = JSVAL_TO_OBJECT(val);
jsuint length; uint32_t length;
if (!JS_GetArrayLength(aCx, obj, &length)) { if (!JS_GetArrayLength(aCx, obj, &length)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
@ -421,7 +421,7 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
keyPathArray.SetCapacity(length); keyPathArray.SetCapacity(length);
for (jsuint index = 0; index < length; index++) { for (uint32_t index = 0; index < length; index++) {
jsval val; jsval val;
JSString* jsstr; JSString* jsstr;
nsDependentJSString str; nsDependentJSString str;
@ -566,7 +566,7 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
// See if this is a JS array. // See if this is a JS array.
if (JS_IsArrayObject(aCx, obj)) { if (JS_IsArrayObject(aCx, obj)) {
jsuint length; uint32_t length;
if (!JS_GetArrayLength(aCx, obj, &length)) { if (!JS_GetArrayLength(aCx, obj, &length)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
@ -577,7 +577,7 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
storesToOpen.SetCapacity(length); storesToOpen.SetCapacity(length);
for (jsuint index = 0; index < length; index++) { for (uint32_t index = 0; index < length; index++) {
jsval val; jsval val;
JSString* jsstr; JSString* jsstr;
nsDependentJSString str; nsDependentJSString str;

View File

@ -904,7 +904,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
} }
if (!keys.IsEmpty()) { if (!keys.IsEmpty()) {
if (!JS_SetArrayLength(aCx, array, jsuint(keys.Length()))) { if (!JS_SetArrayLength(aCx, array, uint32_t(keys.Length()))) {
NS_WARNING("Failed to set array length!"); NS_WARNING("Failed to set array length!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }

View File

@ -618,12 +618,12 @@ IDBObjectStore::AppendIndexUpdateInfo(PRInt64 aIndexID,
if (aMultiEntry && !JSVAL_IS_PRIMITIVE(key) && if (aMultiEntry && !JSVAL_IS_PRIMITIVE(key) &&
JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(key))) { JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(key))) {
JSObject* array = JSVAL_TO_OBJECT(key); JSObject* array = JSVAL_TO_OBJECT(key);
jsuint arrayLength; uint32_t arrayLength;
if (!JS_GetArrayLength(aCx, array, &arrayLength)) { if (!JS_GetArrayLength(aCx, array, &arrayLength)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
for (jsuint arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) { for (uint32_t arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
jsval arrayItem; jsval arrayItem;
if (!JS_GetElement(aCx, array, arrayIndex, &arrayItem)) { if (!JS_GetElement(aCx, array, arrayIndex, &arrayItem)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@ -1700,7 +1700,7 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
JSObject* obj = JSVAL_TO_OBJECT(aKeyPath); JSObject* obj = JSVAL_TO_OBJECT(aKeyPath);
jsuint length; uint32_t length;
if (!JS_GetArrayLength(aCx, obj, &length)) { if (!JS_GetArrayLength(aCx, obj, &length)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
@ -1711,7 +1711,7 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
keyPathArray.SetCapacity(length); keyPathArray.SetCapacity(length);
for (jsuint index = 0; index < length; index++) { for (uint32_t index = 0; index < length; index++) {
jsval val; jsval val;
JSString* jsstr; JSString* jsstr;
nsDependentJSString str; nsDependentJSString str;

View File

@ -170,12 +170,12 @@ Key::EncodeJSVal(JSContext* aCx, const jsval aVal, PRUint8 aTypeOffset)
aTypeOffset < (eMaxType * MaxArrayCollapse), aTypeOffset < (eMaxType * MaxArrayCollapse),
"Wrong typeoffset"); "Wrong typeoffset");
jsuint length; uint32_t length;
if (!JS_GetArrayLength(aCx, obj, &length)) { if (!JS_GetArrayLength(aCx, obj, &length)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
for (jsuint index = 0; index < length; index++) { for (uint32_t index = 0; index < length; index++) {
jsval val; jsval val;
if (!JS_GetElement(aCx, obj, index, &val)) { if (!JS_GetElement(aCx, obj, index, &val)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@ -220,7 +220,7 @@ Key::DecodeJSVal(const unsigned char*& aPos, const unsigned char* aEnd,
aTypeOffset = 0; aTypeOffset = 0;
} }
jsuint index = 0; uint32_t index = 0;
while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) { while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) {
jsval val; jsval val;
nsresult rv = DecodeJSVal(aPos, aEnd, aCx, aTypeOffset, &val); nsresult rv = DecodeJSVal(aPos, aEnd, aCx, aTypeOffset, &val);

View File

@ -36,104 +36,79 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "domstubs.idl" #include "domstubs.idl"
#include "nsIArray.idl"
#include "nsIDOMEvent.idl"
#include "nsIDOMEventTarget.idl"
[scriptable, uuid(e0c271cb-266b-48c9-a7e4-96590b445c26)] interface nsIDOMDOMRequest;
interface mozIDOMApplicationRegistryError : nsISupports
{
const unsigned short DENIED = 1;
const unsigned short PERMISSION_DENIED = 2;
const unsigned short MANIFEST_URL_ERROR = 3;
const unsigned short NETWORK_ERROR = 4;
const unsigned short MANIFEST_PARSE_ERROR = 5;
const unsigned short INVALID_MANIFEST = 6;
readonly attribute short code; [scriptable, uuid(b70b84f1-7ac9-4a92-bc32-8b6a7eb7879e)]
}; interface mozIDOMApplication : nsISupports
[scriptable, uuid(a6856a3d-dece-43ce-89b9-72dba07f4246)]
interface mozIDOMApplication : nsISupports
{ {
readonly attribute jsval manifest; readonly attribute jsval manifest;
readonly attribute DOMString receipt; readonly attribute DOMString manifestURL;
readonly attribute nsIArray receipts; /* an array of strings */
readonly attribute DOMString origin; readonly attribute DOMString origin;
readonly attribute DOMString installOrigin; readonly attribute DOMString installOrigin;
readonly attribute unsigned long installTime; readonly attribute unsigned long installTime;
/* startPoint will be used when several launch_path exists for an app */
nsIDOMDOMRequest launch([optional] in DOMString startPoint);
nsIDOMDOMRequest uninstall();
}; };
[scriptable, function, uuid(be170df5-9154-463b-9197-10a6195eba52)] [scriptable, uuid(870bfbdc-3e13-4042-99dd-18e25720782d)]
interface mozIDOMApplicationRegistryEnumerateCallback : nsISupports interface mozIDOMApplicationEvent : nsIDOMEvent
{ {
void handleEvent([array, size_is(count)] in mozIDOMApplication apps, readonly attribute mozIDOMApplication application;
in unsigned long count);
}; };
[scriptable, function, uuid(ae0ed33d-35cf-443a-837b-a6cebf16bd49)] [scriptable, uuid(a82771f6-ba46-4073-9e6e-f1ad3f42b1f6)]
interface mozIDOMApplicationRegistryErrorCallback : nsISupports interface mozIDOMApplicationMgmt : nsIDOMEventTarget
{ {
void handleEvent(in mozIDOMApplicationRegistryError error); /**
* the request will return the all the applications installed. Only accessible
* to privileged callers.
*/
nsIDOMDOMRequest getAll();
/**
* event listener to get notified of application installs. Only settable by
* privileged callers.
* the event will be a mozIDOMApplicationEvent
*/
attribute nsIDOMEventListener oninstall;
/**
* event listener to get notified of application uninstalls. Only settable by
* privileged callers.
* the event will be a mozIDOMApplicationEvent
*/
attribute nsIDOMEventListener onuninstall;
}; };
[scriptable, uuid(ac63c0ba-1f33-4e3e-b9aa-6a3243a9adba)] [scriptable, uuid(f6929871-288b-4613-9a37-9a150760ac50)]
interface mozIDOMApplicationRegistry : nsISupports interface mozIDOMApplicationRegistry : nsISupports
{ {
/** /**
* Install a web app. onerror can be used to report errors, * Install a web app. onerror can be used to report errors,
* and oninstall if the caller is privileged. * and oninstall if the caller is privileged.
* *
* @param manifestUrl : the URL of the webapps manifest * @param manifestUrl : the URL of the webapps manifest.
* @param receipt : An opaque string used to track payment status * @param parameters : A structure with optional information.
* { receipts: ... } will be used to specify the payment receipts for this installation.
*/ */
void install(in DOMString manifestUrl, nsIDOMDOMRequest install(in DOMString manifestUrl, [optional] in jsval parameters);
[optional] in DOMString receipt);
/** /**
* This call is only accessible to privileged callers. * the request will return the application currently installed, or null.
*
* @param origin : the origin of the application to uninstall.
*/ */
void uninstall(in DOMString origin); nsIDOMDOMRequest getSelf();
/** /**
* Enumerate apps : either return itself if caller is an app, or * the request will return the applications installed from this origin, or null.
* apps installed from a store if caller is a store
*
* @param success: the callback that will get the array of applications
* @param error: optional error callback
*/ */
void enumerate(in mozIDOMApplicationRegistryEnumerateCallback success, nsIDOMDOMRequest getInstalled();
[optional] in mozIDOMApplicationRegistryErrorCallback error);
/** readonly attribute mozIDOMApplicationMgmt mgmt;
* Enumerate all apps installed from all stores.
* Only usable by privileged callers.
*
* @param success: the callback that will get the array of applications
* @param error: optional error callback
*/
void enumerateAll(in mozIDOMApplicationRegistryEnumerateCallback success,
[optional] in mozIDOMApplicationRegistryErrorCallback error);
/**
* launch a webapp. Behavior is application dependant.
*
* @param origin : the origin of the application to launch
*/
void launch(in DOMString origin);
/**
* event listener to get notified of application installs. Only settable by
* privileged callers
*/
attribute nsIDOMEventListener oninstall;
/**
* event listener to get notified of application uninstalls. Only settable by
* privileged callers
*/
attribute nsIDOMEventListener onuninstall;
/**
* event listener to get notified of errors.
*/
attribute nsIDOMEventListener onerror;
}; };

View File

@ -131,3 +131,4 @@ interface nsIDOMFontFaceList;
// Power // Power
interface nsIDOMMozPowerManager; interface nsIDOMMozPowerManager;
interface nsIDOMMozWakeLock;

View File

@ -39,7 +39,7 @@
#include "domstubs.idl" #include "domstubs.idl"
[scriptable, uuid(b1f4b1fa-49c2-4375-9ce8-bf97ecf6b428)] [scriptable, uuid(e610c037-db58-4cd7-8ed3-0d7f1422b4d3)]
interface nsIDOMNavigator : nsISupports interface nsIDOMNavigator : nsISupports
{ {
readonly attribute DOMString appCodeName; readonly attribute DOMString appCodeName;
@ -110,4 +110,34 @@ interface nsIDOMNavigator : nsISupports
*/ */
[implicit_jscontext] [implicit_jscontext]
void mozVibrate(in jsval aPattern); void mozVibrate(in jsval aPattern);
/**
* Request a wake lock for a resource.
*
* A page holds a wake lock to request that a resource not be turned
* off (or otherwise made unavailable).
*
* The topic is the name of a resource that might be made unavailable for
* various reasons. For example, on a mobile device the power manager might
* decide to turn off the screen after a period of idle time to save power.
*
* The resource manager checks the lock state of a topic before turning off
* the associated resource. For example, a page could hold a lock on the
* "screen" topic to prevent the screensaver from appearing or the screen
* from turning off.
*
* The resource manager defines what each topic means and sets policy. For
* example, the resource manager might decide to ignore 'screen' wake locks
* held by pages which are not visible.
*
* One topic can be locked multiple times; it is considered released only when
* all locks on the topic have been released.
*
* The returned nsIDOMMozWakeLock object is a token of the lock. You can
* unlock the lock via the object's |unlock| method. The lock is released
* automatically when its associated window is unloaded.
*
* @param aTopic resource name
*/
nsIDOMMozWakeLock requestWakeLock(in DOMString aTopic);
}; };

View File

@ -52,15 +52,19 @@ EXPORTS_NAMESPACES = mozilla/dom/power
EXPORTS_mozilla/dom/power = \ EXPORTS_mozilla/dom/power = \
PowerManagerService.h \ PowerManagerService.h \
Types.h \
$(NULL) $(NULL)
CPPSRCS = \ CPPSRCS = \
PowerManager.cpp \ PowerManager.cpp \
PowerManagerService.cpp \ PowerManagerService.cpp \
WakeLock.cpp \
$(NULL) $(NULL)
XPIDLSRCS = \ XPIDLSRCS = \
nsIDOMPowerManager.idl \ nsIDOMPowerManager.idl \
nsIDOMWakeLock.idl \
nsIDOMWakeLockListener.idl \
nsIPowerManagerService.idl \ nsIPowerManagerService.idl \
$(NULL) $(NULL)

View File

@ -36,9 +36,13 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "PowerManager.h" #include "PowerManager.h"
#include "WakeLock.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsDOMClassInfoID.h" #include "nsDOMClassInfoID.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIPowerManagerService.h" #include "nsIPowerManagerService.h"
#include "nsIPrincipal.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
DOMCI_DATA(MozPowerManager, mozilla::dom::power::PowerManager) DOMCI_DATA(MozPowerManager, mozilla::dom::power::PowerManager)
@ -50,20 +54,66 @@ namespace power {
NS_INTERFACE_MAP_BEGIN(PowerManager) NS_INTERFACE_MAP_BEGIN(PowerManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozPowerManager) NS_INTERFACE_MAP_ENTRY(nsIDOMMozPowerManager)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozPowerManager) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozPowerManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWakeLockListener)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozPowerManager) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozPowerManager)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(PowerManager) NS_IMPL_ADDREF(PowerManager)
NS_IMPL_RELEASE(PowerManager) NS_IMPL_RELEASE(PowerManager)
NS_IMETHODIMP nsresult
PowerManager::Reboot() PowerManager::Init(nsIDOMWindow *aWindow)
{ {
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR); mWindow = do_GetWeakReference(aWindow);
nsCOMPtr<nsIPowerManagerService> pmService = nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID); do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_TRUE(pmService, NS_OK); NS_ENSURE_STATE(pmService);
// Add ourself to the global notification list.
pmService->AddWakeLockListener(this);
return NS_OK;
}
nsresult
PowerManager::Shutdown()
{
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_STATE(pmService);
// Remove ourself from the global notification list.
pmService->RemoveWakeLockListener(this);
return NS_OK;
}
nsresult
PowerManager::CheckPermission()
{
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_STATE(win);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
NS_ENSURE_STATE(doc);
nsCOMPtr<nsIURI> uri;
doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.power.whitelist")) {
return NS_ERROR_DOM_SECURITY_ERR;
}
return NS_OK;
}
NS_IMETHODIMP
PowerManager::Reboot()
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_STATE(pmService);
pmService->Reboot(); pmService->Reboot();
@ -73,17 +123,74 @@ PowerManager::Reboot()
NS_IMETHODIMP NS_IMETHODIMP
PowerManager::PowerOff() PowerManager::PowerOff()
{ {
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR); nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPowerManagerService> pmService = nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID); do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_TRUE(pmService, NS_OK); NS_ENSURE_STATE(pmService);
pmService->PowerOff(); pmService->PowerOff();
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
PowerManager::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
// already added? bail out.
if (mListeners.Contains(aListener))
return NS_OK;
mListeners.AppendElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManager::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
mListeners.RemoveElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManager::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
{
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_STATE(pmService);
return pmService->GetWakeLockState(aTopic, aState);
}
NS_IMETHODIMP
PowerManager::Callback(const nsAString &aTopic, const nsAString &aState)
{
/**
* We maintain a local listener list instead of using the global
* list so that when the window is destroyed we don't have to
* cleanup the mess.
* Copy the listeners list before we walk through the callbacks
* because the callbacks may install new listeners. We expect no
* more than one listener per window, so it shouldn't be too long.
*/
nsAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mListeners);
for (PRUint32 i = 0; i < listeners.Length(); ++i) {
listeners[i]->Callback(aTopic, aState);
}
return NS_OK;
}
} // power } // power
} // dom } // dom
} // mozilla } // mozilla

View File

@ -37,7 +37,12 @@
#ifndef mozilla_dom_power_PowerManager_h #ifndef mozilla_dom_power_PowerManager_h
#define mozilla_dom_power_PowerManager_h #define mozilla_dom_power_PowerManager_h
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsIDOMPowerManager.h" #include "nsIDOMPowerManager.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIDOMWindow.h"
#include "nsWeakReference.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -45,13 +50,24 @@ namespace power {
class PowerManager class PowerManager
: public nsIDOMMozPowerManager : public nsIDOMMozPowerManager
, public nsIDOMMozWakeLockListener
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIDOMMOZPOWERMANAGER NS_DECL_NSIDOMMOZPOWERMANAGER
NS_DECL_NSIDOMMOZWAKELOCKLISTENER
PowerManager() {}; PowerManager() {};
virtual ~PowerManager() {}; virtual ~PowerManager() {};
nsresult Init(nsIDOMWindow *aWindow);
nsresult Shutdown();
private:
nsresult CheckPermission();
nsWeakPtr mWindow;
nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mListeners;
}; };
} // namespace power } // namespace power

View File

@ -36,7 +36,12 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "mozilla/Hal.h" #include "mozilla/Hal.h"
#include "mozilla/HalWakeLock.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIDOMWindow.h"
#include "PowerManagerService.h" #include "PowerManagerService.h"
#include "WakeLock.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -44,14 +49,67 @@ namespace power {
NS_IMPL_ISUPPORTS1(PowerManagerService, nsIPowerManagerService) NS_IMPL_ISUPPORTS1(PowerManagerService, nsIPowerManagerService)
/* static */ nsRefPtr<PowerManagerService> PowerManagerService::sSingleton;
/* static */ already_AddRefed<nsIPowerManagerService> /* static */ already_AddRefed<nsIPowerManagerService>
PowerManagerService::GetInstance() PowerManagerService::GetInstance()
{ {
nsCOMPtr<nsIPowerManagerService> pmService; if (!sSingleton) {
sSingleton = new PowerManagerService();
sSingleton->Init();
ClearOnShutdown(&sSingleton);
}
pmService = new PowerManagerService(); nsCOMPtr<nsIPowerManagerService> service(do_QueryInterface(sSingleton));
return service.forget();
}
return pmService.forget(); void
PowerManagerService::Init()
{
hal::RegisterWakeLockObserver(this);
}
PowerManagerService::~PowerManagerService()
{
hal::UnregisterWakeLockObserver(this);
}
void
PowerManagerService::ComputeWakeLockState(const hal::WakeLockInformation& aWakeLockInfo,
nsAString &aState)
{
hal::WakeLockState state = hal::ComputeWakeLockState(aWakeLockInfo.numLocks(),
aWakeLockInfo.numHidden());
switch (state) {
case hal::WAKE_LOCK_STATE_UNLOCKED:
aState.AssignLiteral("unlocked");
break;
case hal::WAKE_LOCK_STATE_HIDDEN:
aState.AssignLiteral("locked-background");
break;
case hal::WAKE_LOCK_STATE_VISIBLE:
aState.AssignLiteral("locked-foreground");
break;
}
}
void
PowerManagerService::Notify(const hal::WakeLockInformation& aWakeLockInfo)
{
nsAutoString state;
ComputeWakeLockState(aWakeLockInfo, state);
/**
* Copy the listeners list before we walk through the callbacks
* because the callbacks may install new listeners. We expect no
* more than one listener per window, so it shouldn't be too long.
*/
nsAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mWakeLockListeners);
for (PRUint32 i = 0; i < listeners.Length(); ++i) {
listeners[i]->Callback(aWakeLockInfo.topic(), state);
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -68,6 +126,50 @@ PowerManagerService::PowerOff()
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
PowerManagerService::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
if (mWakeLockListeners.Contains(aListener))
return NS_OK;
mWakeLockListeners.AppendElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManagerService::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
{
mWakeLockListeners.RemoveElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PowerManagerService::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
{
hal::WakeLockInformation info;
hal::GetWakeLockInfo(aTopic, &info);
ComputeWakeLockState(info, aState);
return NS_OK;
}
NS_IMETHODIMP
PowerManagerService::NewWakeLock(const nsAString &aTopic,
nsIDOMWindow *aWindow,
nsIDOMMozWakeLock **aWakeLock)
{
nsRefPtr<WakeLock> wakelock = new WakeLock();
nsresult rv = wakelock->Init(aTopic, aWindow);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMMozWakeLock> wl =
do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMMozWakeLock*, wakelock));
wl.forget(aWakeLock);
return NS_OK;
}
} // power } // power
} // dom } // dom
} // mozilla } // mozilla

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