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;
[scriptable, uuid(52837507-202d-4e72-a482-5f068a1fd720)]
[scriptable, uuid(e242d495-5cde-4b1c-8c84-2525b14939f5)]
interface nsIAccessibleEditableText : nsISupports
{
/**
@ -103,19 +103,4 @@ interface nsIAccessibleEditableText : nsISupports
* clipboard into the text represented by this object.
*/
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
nsApplicationAccessibleWrap::GetNativeInterface(void **aOutAccessible)
{

View File

@ -57,6 +57,8 @@ public:
virtual bool Init();
// nsAccessible
NS_IMETHOD GetName(nsAString &aName);
virtual bool AppendChild(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.
if (aEvent->mAccessible->Role() == roles::WHITESPACE) {
nsCOMPtr<nsIEditor> editor;
textAccessible->GetAssociatedEditor(getter_AddRefs(editor));
nsCOMPtr<nsIEditor> editor = textAccessible->GetEditor();
if (editor) {
bool isEmpty = false;
editor->GetDocumentIsEmpty(&isEmpty);

View File

@ -969,10 +969,8 @@ void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame
*aBoundingFrame = ancestorFrame;
// 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
if (!nsCoreUtils::IsCorrectFrameType(ancestorFrame,
nsGkAtoms::inlineFrame) &&
!nsCoreUtils::IsCorrectFrameType(ancestorFrame,
nsGkAtoms::textFrame))
if (ancestorFrame->GetType() != nsGkAtoms::inlineFrame &&
ancestorFrame->GetType() != nsGkAtoms::textFrame)
break;
ancestorFrame = ancestorFrame->GetParent();
}
@ -996,8 +994,7 @@ void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame
nsIFrame *iterNextFrame = nsnull;
if (nsCoreUtils::IsCorrectFrameType(iterFrame,
nsGkAtoms::inlineFrame)) {
if (iterFrame->GetType() == nsGkAtoms::inlineFrame) {
// Only do deeper bounds search if we're on an inline frame
// Inline frames can contain larger frames inside of them
iterNextFrame = iterFrame->GetFirstPrincipalChild();

View File

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

View File

@ -503,17 +503,6 @@ nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
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>
nsCoreUtils::GetDOMNodeForContainer(nsIDocShellTreeItem *aContainer)
{

View File

@ -241,14 +241,6 @@ public:
*/
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.
*/

View File

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

View File

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

View File

@ -544,11 +544,12 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible::DoAction(PRUint8 index)
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));
NS_ENSURE_TRUE(editableElt, NS_ERROR_FAILURE);
if (!editableElt)
return nsnull;
// nsGenericHTMLElement::GetEditor has a security check.
// 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));
nsCOMPtr<nsIEditor> editor;
nsresult rv = editableElt->GetEditor(aEditor);
editableElt->GetEditor(getter_AddRefs(editor));
if (pushed) {
JSContext* cx;
@ -566,7 +567,7 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible::GetAssociatedEditor(nsIEditor **aEditor
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 DoAction(PRUint8 index);
// nsIAccessibleEditableText
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
// nsHyperTextAccessible
virtual already_AddRefed<nsIEditor> GetEditor() const;
// nsAccessible
virtual void ApplyARIAState(PRUint64* aState);

View File

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

View File

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

View File

@ -273,8 +273,7 @@ nsXFormsEditableAccessible::NativeState()
}
}
nsCOMPtr<nsIEditor> editor;
GetAssociatedEditor(getter_AddRefs(editor));
nsCOMPtr<nsIEditor> editor = GetEditor();
NS_ENSURE_TRUE(editor, state);
PRUint32 flags;
editor->GetFlags(&flags);
@ -286,11 +285,14 @@ nsXFormsEditableAccessible::NativeState()
return state;
}
NS_IMETHODIMP
nsXFormsEditableAccessible::GetAssociatedEditor(nsIEditor **aEditor)
already_AddRefed<nsIEditor>
nsXFormsEditableAccessible::GetEditor() const
{
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:
nsXFormsEditableAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
// nsIAccessibleEditableText
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
// nsHyperTextAccessible
virtual already_AddRefed<nsIEditor> GetEditor() const;
// nsAccessible
virtual PRUint64 NativeState();

View File

@ -850,14 +850,17 @@ nsXULTextFieldAccessible::CanHaveAnonChildren()
return false;
}
NS_IMETHODIMP nsXULTextFieldAccessible::GetAssociatedEditor(nsIEditor **aEditor)
already_AddRefed<nsIEditor>
nsXULTextFieldAccessible::GetEditor() const
{
*aEditor = nsnull;
nsCOMPtr<nsIContent> inputField = GetInputField();
nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(inputField));
NS_ENSURE_TRUE(editableElt, NS_ERROR_FAILURE);
return editableElt->GetEditor(aEditor);
if (!editableElt)
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 DoAction(PRUint8 index);
// nsIAccessibleEditableText
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
// nsHyperTextAccessible
virtual already_AddRefed<nsIEditor> GetEditor() const;
// nsAccessible
virtual void ApplyARIAState(PRUint64* aState);

View File

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

View File

@ -15,41 +15,46 @@
<script type="application/javascript">
function doTest()
{
var accessible = getApplicationAccessible();
if (!accessible) {
SimpleTest.finish();
return;
}
var accessible = getApplicationAccessible();
if (!accessible) {
SimpleTest.finish();
return;
}
// nsIAccessible::name
var bundleServ = Components.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService);
var bundle = bundleServ.createBundle("chrome://branding/locale/brand.properties");
var bundleServ =
Components.classes["@mozilla.org/intl/stringbundle;1"].
getService(Components.interfaces.nsIStringBundleService);
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 {
applicationName = bundle.GetStringFromName("brandShortName");
} catch(e) {
applicationName = brandBundle.GetStringFromName("brandShortName");
} catch(e) {
}
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
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.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>

View File

@ -304,12 +304,20 @@ function eventQueue(aEventType)
// Start processing of next invoker.
invoker = this.getNextInvoker();
this.setEventHandler(invoker);
if (gLogger.isEnabled()) {
gLogger.logToConsole("Event queue: \n invoke: " + invoker.getID());
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) {
// Invoker failed to prepare action, fail and finish tests.

View File

@ -384,14 +384,11 @@
{
if (SEAMONKEY) {
todo(false, "Skipping this test on SeaMonkey ftb. (Bug 718237)");
shutdownAutoComplete();
SimpleTest.finish();
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.push(new loadFormAutoComplete("iframe"));
gInitQueue.push(new initFormAutoCompleteBy("iframe", "hello"));
@ -461,6 +458,12 @@
}
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);
]]>
</script>

View File

@ -35,10 +35,6 @@
var gQueue = null;
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.push(new openCombobox("menulist"));
@ -73,6 +69,12 @@
}
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);
]]>
</script>

View File

@ -181,7 +181,11 @@ const ContentPanning = {
case 'click':
evt.stopPropagation();
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;
}
},
@ -190,16 +194,24 @@ const ContentPanning = {
onTouchStart: function cp_onTouchStart(evt) {
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
// 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) {
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);
KineticPanning.record(new Point(0, 0), evt.timeStamp);
},
@ -211,14 +223,15 @@ const ContentPanning = {
this.onTouchMove(evt);
let pan = KineticPanning.isPan();
let click = evt.detail;
if (click && (pan || this.preventNextClick))
evt.target.addEventListener('click', this, true);
if (this.target && click && (this.panning || this.preventNextClick)) {
let target = this.target;
let view = target.ownerDocument ? target.ownerDocument.defaultView
: target;
view.addEventListener('click', this, true, true);
}
this.preventNextClick = false;
if (pan)
if (this.panning)
KineticPanning.start(this);
},
@ -232,6 +245,13 @@ const ContentPanning = {
KineticPanning.record(delta, evt.timeStamp);
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) {
if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML')
return null;
return [null, null];
let content = node.ownerDocument.defaultView;
while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
@ -266,12 +286,12 @@ const ContentPanning = {
let isScroll = (overflow.indexOf('scroll') != -1);
if (isScroll || isAuto)
return this._generateCallback(node);
return [node, this._generateCallback(node)];
node = node.parentNode;
}
return this._generateCallback(content);
return [content, this._generateCallback(content)];
},
_generateCallback: function cp_generateCallback(content) {
@ -290,6 +310,19 @@ const ContentPanning = {
}
}
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;
this.momentums = [];
this.distance.set(0, 0);
this.target.onKineticEnd();
this.target = null;
@ -378,23 +412,24 @@ const KineticPanning = {
momentums: [],
record: function kp_record(delta, timestamp) {
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)
.getInterface(Ci.nsIDOMWindowUtils)
.displayDPI;
let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
let deltaX = 0;
let deltaY = 0;
let start = this.momentums[0].time;
return this.momentums.slice(1).some(function(momentum) {
deltaX += momentum.dx;
deltaY += momentum.dy;
return (Math.abs(deltaX) > threshold) || (Math.abs(deltaY) > threshold);
});
delete this.threshold;
return this.threshold = threshold;
},
distance: new Point(0, 0),
isPan: function cp_isPan() {
return (Math.abs(this.distance.x) > this.threshold ||
Math.abs(this.distance.y) > this.threshold);
},
_startAnimation: function kp_startAnimation() {

View File

@ -1563,49 +1563,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
gHomeButton.updateTooltip(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
gBidiUI = isBidiEnabled();
if (gBidiUI) {
@ -3989,10 +3946,22 @@ var FullScreen = {
}
},
exitDomFullScreen : function(e) {
exitDomFullScreen : function() {
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) {
if (!document.mozFullScreen) {
return;
@ -4039,7 +4008,7 @@ var FullScreen = {
// Exit DOM full-screen mode when the browser window loses focus (ALT+TAB, etc).
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
@ -4074,7 +4043,7 @@ var FullScreen = {
gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
gBrowser.tabContainer.removeEventListener("TabClose", 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 = {
init: function TabsOnTop_init() {
this._initialized = true;
this.syncUI();
Services.prefs.addObserver(this._prefName, this, false);
},
@ -5375,6 +5345,9 @@ var TabsOnTop = {
},
syncUI: function () {
if (!this._initialized)
return;
let userEnabled = Services.prefs.getBoolPref(this._prefName);
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 noStyle = menuPopup.firstChild;
var persistentOnly = noStyle.nextSibling;
var sep = persistentOnly.nextSibling;
while (sep.nextSibling)
menuPopup.removeChild(sep.nextSibling);
var gPageStyleMenu = {
var styleSheets = getAllStyleSheets(window.content);
var currentStyleSheets = {};
var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled;
var haveAltSheets = false;
var altStyleSelected = false;
getAllStyleSheets: function (frameset) {
var styleSheetsArray = Array.slice(frameset.document.styleSheets);
for (let i = 0; i < frameset.frames.length; i++) {
let frameSheets = this.getAllStyleSheets(frameset.frames[i]);
styleSheetsArray = styleSheetsArray.concat(frameSheets);
}
return styleSheetsArray;
},
for (let i = 0; i < styleSheets.length; ++i) {
let currentStyleSheet = styleSheets[i];
stylesheetFillPopup: function (menuPopup) {
var noStyle = menuPopup.firstChild;
var persistentOnly = noStyle.nextSibling;
var sep = persistentOnly.nextSibling;
while (sep.nextSibling)
menuPopup.removeChild(sep.nextSibling);
if (!currentStyleSheet.title)
continue;
var styleSheets = this.getAllStyleSheets(window.content);
var currentStyleSheets = {};
var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled;
var haveAltSheets = false;
var altStyleSelected = false;
// 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)
for (let i = 0; i < styleSheets.length; ++i) {
let currentStyleSheet = styleSheets[i];
if (!currentStyleSheet.title)
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)
altStyleSelected = true;
noStyle.setAttribute("checked", styleDisabled);
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;
if (currentStyleSheet.title in currentStyleSheets)
lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
stylesheetSwitchFrame: function (frame, title) {
var docStyleSheets = frame.document.styleSheets;
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");
for (let i = 0; i < docStyleSheets.length; ++i) {
let docStyleSheet = docStyleSheets[i];
if (title == "_nostyle")
docStyleSheet.disabled = true;
else if (docStyleSheet.title)
docStyleSheet.disabled = (docStyleSheet.title != title);
else if (docStyleSheet.disabled)
docStyleSheet.disabled = false;
}
}
},
noStyle.setAttribute("checked", styleDisabled);
persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled);
persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false;
sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
return true;
}
stylesheetSwitchAll: function (frameset, title) {
if (!title || title == "_nostyle" || this.stylesheetInFrame(frameset, title))
this.stylesheetSwitchFrame(frameset, title);
function stylesheetInFrame(frame, title) {
return Array.some(frame.document.styleSheets,
function (stylesheet) stylesheet.title == title);
}
for (let i = 0; i < frameset.frames.length; i++)
this.stylesheetSwitchAll(frameset.frames[i], title);
},
function stylesheetSwitchFrame(frame, title) {
var docStyleSheets = frame.document.styleSheets;
setStyleDisabled: function (disabled) {
getMarkupDocumentViewer().authorStyleDisabled = disabled;
},
};
for (let i = 0; i < docStyleSheets.length; ++i) {
let docStyleSheet = docStyleSheets[i];
/* Legacy global page-style functions */
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 = {
_inited: false,

View File

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

View File

@ -428,6 +428,49 @@ BrowserGlue.prototype = {
let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL");
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) {

View File

@ -167,73 +167,33 @@ PlacesViewBase.prototype = {
},
_cleanPopup: function PVB_cleanPopup(aPopup) {
// Remove places popup children and update markers to keep track of
// their indices.
let start = aPopup._startMarker != -1 ? aPopup._startMarker + 1 : 0;
let end = aPopup._endMarker != -1 ? aPopup._endMarker :
aPopup.childNodes.length;
let items = [];
// 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--;
// Remove Places nodes from the popup.
let child = aPopup._startMarker;
while (child.nextSibling != aPopup._endMarker) {
if (child.nextSibling._placesNode)
aPopup.removeChild(child.nextSibling);
else
child = child.nextSibling;
}
},
_rebuildPopup: function PVB__rebuildPopup(aPopup) {
this._cleanPopup(aPopup);
let resultNode = aPopup._placesNode;
if (!resultNode.containerOpen)
return;
if (resultNode._feedURI) {
aPopup.removeAttribute("emptyplacesresult");
if (aPopup._emptyMenuItem) {
aPopup._emptyMenuItem.hidden = true;
}
this._setEmptyPopupStatus(aPopup, false);
aPopup._built = true;
this._populateLivemarkPopup(aPopup);
return;
}
this._cleanPopup(aPopup);
let cc = resultNode.childCount;
if (cc > 0) {
aPopup.removeAttribute("emptyplacesresult");
if (aPopup._emptyMenuItem)
aPopup._emptyMenuItem.hidden = true;
this._setEmptyPopupStatus(aPopup, false);
for (let i = 0; i < cc; ++i) {
let child = resultNode.getChild(i);
@ -241,11 +201,7 @@ PlacesViewBase.prototype = {
}
}
else {
aPopup.setAttribute("emptyplacesresult", "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);
this._setEmptyPopupStatus(aPopup, true);
}
aPopup._built = true;
},
@ -260,17 +216,28 @@ PlacesViewBase.prototype = {
aChild.parentNode.removeChild(aChild);
},
_showEmptyMenuItem: function PVB__showEmptyMenuItem(aPopup) {
if (aPopup._emptyMenuItem) {
aPopup._emptyMenuItem.hidden = false;
return;
_setEmptyPopupStatus:
function PVB__setEmptyPopupStatus(aPopup, aEmpty) {
if (!aPopup._emptyMenuitem) {
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");
aPopup._emptyMenuItem = document.createElement("menuitem");
aPopup._emptyMenuItem.setAttribute("label", label);
aPopup._emptyMenuItem.setAttribute("disabled", true);
aPopup.appendChild(aPopup._emptyMenuItem);
if (aEmpty) {
aPopup.setAttribute("emptyplacesresult", "true");
// Don't add the menuitem if there is static content.
if (!aPopup._startMarker.previousSibling &&
!aPopup._endMarker.nextSibling)
aPopup.insertBefore(aPopup._emptyMenuitem, aPopup._endMarker);
}
else {
aPopup.removeAttribute("emptyplacesresult");
try {
aPopup.removeChild(aPopup._emptyMenuitem);
} catch (ex) {}
}
},
_createMenuItemForPlacesNode:
@ -308,6 +275,12 @@ PlacesViewBase.prototype = {
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
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
// its metadata.
aPlacesNode._feedURI = aLivemark.feedURI;
@ -319,12 +292,11 @@ PlacesViewBase.prototype = {
let popup = document.createElement("menupopup");
popup._placesNode = PlacesUtils.asContainer(aPlacesNode);
if (this._nativeView) {
popup._startMarker = -1;
popup._endMarker = -1;
}
else
if (!this._nativeView) {
popup.setAttribute("placespopup", "true");
}
#ifdef XP_MACOSX
// No context menu on mac.
popup.setAttribute("context", "placesContext");
@ -354,26 +326,8 @@ PlacesViewBase.prototype = {
_insertNewItemToPopup:
function PVB__insertNewItemToPopup(aNewChild, aPopup, aBefore) {
let element = this._createMenuItemForPlacesNode(aNewChild);
if (aBefore) {
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++;
let before = aBefore || aPopup._endMarker;
aPopup.insertBefore(element, before);
return element;
},
@ -384,10 +338,8 @@ PlacesViewBase.prototype = {
if (!siteUrl && aPopup._siteURIMenuitem) {
aPopup.removeChild(aPopup._siteURIMenuitem);
aPopup._siteURIMenuitem = null;
aPopup._startMarker--;
aPopup.removeChild(aPopup._siteURIMenuseparator);
aPopup._siteURIMenuseparator = null;
aPopup._startMarker--;
}
else if (siteUrl && !aPopup._siteURIMenuitem) {
// Add "Open (Feed Name)" menuitem.
@ -407,14 +359,10 @@ PlacesViewBase.prototype = {
PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
[aPopup.parentNode.getAttribute("label")])
aPopup._siteURIMenuitem.setAttribute("label", label);
aPopup.insertBefore(aPopup._siteURIMenuitem,
aPopup.childNodes.item(aPopup._startMarker + 1));
aPopup._startMarker++;
aPopup.insertBefore(aPopup._siteURIMenuitem, aPopup._startMarker);
aPopup._siteURIMenuseparator = document.createElement("menuseparator");
aPopup.insertBefore(aPopup._siteURIMenuseparator,
aPopup.childNodes.item(aPopup._startMarker + 1));
aPopup._startMarker++;
aPopup.insertBefore(aPopup._siteURIMenuseparator, aPopup._startMarker);
}
},
@ -427,7 +375,6 @@ PlacesViewBase.prototype = {
*/
_setLivemarkStatusMenuItem:
function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
let itemId = aPopup._placesNode.itemId;
let statusMenuitem = aPopup._statusMenuitem;
let stringId = "";
if (aStatus == Ci.mozILivemark.STATUS_LOADING)
@ -439,12 +386,11 @@ PlacesViewBase.prototype = {
// Create the status menuitem and cache it in the popup object.
statusMenuitem = document.createElement("menuitem");
statusMenuitem.setAttribute("livemarkStatus", stringId);
statusMenuitem.className = "livemarkstatus-menuitem";
statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
statusMenuitem.setAttribute("disabled", true);
aPopup.insertBefore(statusMenuitem,
aPopup.childNodes.item(aPopup._startMarker + 1));
aPopup.insertBefore(statusMenuitem, aPopup._startMarker.nextSibling);
aPopup._statusMenuitem = statusMenuitem;
aPopup._startMarker++;
}
else if (stringId &&
statusMenuitem.getAttribute("livemarkStatus") != stringId) {
@ -455,7 +401,6 @@ PlacesViewBase.prototype = {
// The livemark has finished loading.
aPopup.removeChild(aPopup._statusMenuitem);
aPopup._statusMenuitem = null;
aPopup._startMarker--;
}
},
@ -517,6 +462,12 @@ PlacesViewBase.prototype = {
let menu = elt.parentNode;
if (!menu.hasAttribute("livemark")) {
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(
@ -580,13 +531,8 @@ PlacesViewBase.prototype = {
// 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
// root.
if (!parentElt.hasChildNodes() ||
(parentElt.childNodes.length == 1 &&
parentElt.firstChild == parentElt._emptyMenuItem))
this._showEmptyMenuItem(parentElt);
if (parentElt._endMarker != -1)
parentElt._endMarker--;
if (parentElt._startMarker.nextSibling == parentElt._endMarker)
this._setEmptyPopupStatus(parentElt, true);
}
},
@ -620,8 +566,9 @@ PlacesViewBase.prototype = {
if (aPlacesNode.parent && aPlacesNode.parent._feedURI) {
// Find the node in the parent.
let popup = aPlacesNode.parent._DOMElement;
for (let i = popup._startMarker; i < popup.childNodes.length; i++) {
let child = popup.childNodes[i];
for (let child = popup._startMarker.nextSibling;
child != popup._endMarker;
child = child.nextSibling) {
if (child._placesNode && child._placesNode.uri == aPlacesNode.uri) {
if (aCount)
child.setAttribute("visited", "true");
@ -649,11 +596,11 @@ PlacesViewBase.prototype = {
if (!parentElt._built)
return;
let index = parentElt._startMarker + 1 + aIndex;
let index = Array.indexOf(parentElt.childNodes, parentElt._startMarker) +
aIndex + 1;
this._insertNewItemToPopup(aPlacesNode, parentElt,
parentElt.childNodes[index]);
if (parentElt._emptyMenuItem)
parentElt._emptyMenuItem.hidden = true;
this._setEmptyPopupStatus(parentElt, false);
},
nodeMoved:
@ -684,7 +631,8 @@ PlacesViewBase.prototype = {
if (parentElt._built) {
// Move the node.
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]);
}
},
@ -821,11 +769,9 @@ PlacesViewBase.prototype = {
if (aPopup._endOptOpenAllInTabs) {
aPopup.removeChild(aPopup._endOptOpenAllInTabs);
aPopup._endOptOpenAllInTabs = null;
aPopup._endMarker--;
aPopup.removeChild(aPopup._endOptSeparator);
aPopup._endOptSeparator = null;
aPopup._endMarker--;
}
}
else if (!aPopup._endOptOpenAllInTabs) {
@ -833,7 +779,6 @@ PlacesViewBase.prototype = {
aPopup._endOptSeparator = document.createElement("menuseparator");
aPopup._endOptSeparator.className = "bookmarks-actions-menuseparator";
aPopup.appendChild(aPopup._endOptSeparator);
aPopup._endMarker++;
// Add the "Open All in Tabs" menuitem.
aPopup._endOptOpenAllInTabs = document.createElement("menuitem");
@ -846,13 +791,51 @@ PlacesViewBase.prototype = {
aPopup._endOptOpenAllInTabs.setAttribute("label",
gNavigatorBundle.getString("menuOpenAllInTabs.label"));
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) {
// Avoid handling popupshowing of inner views.
let popup = aEvent.originalTarget;
this._ensureMarkers(popup);
if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
if (!popup._placesNode.containerOpen)
popup._placesNode.containerOpen = true;
@ -1808,8 +1791,6 @@ function PlacesMenu(aPopupShowingEvent, aPlace) {
#ifdef XP_MACOSX
if (this._viewElt.parentNode.localName == "menubar") {
this._nativeView = true;
this._rootElt._startMarker = -1;
this._rootElt._endMarker = -1;
}
#endif
@ -1829,8 +1810,6 @@ PlacesMenu.prototype = {
_removeChild: function PM_removeChild(aChild) {
PlacesViewBase.prototype._removeChild.apply(this, arguments);
if (this._endMarker != -1)
this._endMarker--;
},
uninit: function PM_uninit() {

View File

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

View File

@ -42,7 +42,7 @@ let test_bookmarks = {
menu: [
{ title: "Mozilla Firefox",
children: [
{ title: "Help and Tutorials",
{ title: "Help and Tutorials",
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=="
},
@ -57,8 +57,8 @@ let test_bookmarks = {
{ title: "About Us",
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=="
},
],
}
]
},
{ title: "test",
description: "folder test comment",
@ -72,10 +72,10 @@ let test_bookmarks = {
keyword: "test",
sidebar: true,
postData: "hidden1%3Dbar&text1%3D%25s",
charset: "ISO-8859-1",
},
charset: "ISO-8859-1"
}
]
},
}
],
toolbar: [
{ title: "Getting Started",
@ -84,14 +84,14 @@ let test_bookmarks = {
},
{ title: "Latest Headlines",
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: [
{ title: "Example.tld",
url: "http://example.tld/",
},
],
url: "http://example.tld/"
}
]
};
// Pre-Places bookmarks.html file pointer.
@ -303,6 +303,8 @@ add_test(function test_import_ontop()
function testImportedBookmarks()
{
for (let group in test_bookmarks) {
do_print("[testImportedBookmarks()] Checking group '" + group + "'");
let root;
switch (group) {
case "menu":
@ -335,6 +337,7 @@ function testImportedBookmarksToFolder(aFolder)
for (let i = 0; i < root.childCount; i++) {
let child = root.getChild(i);
// This check depends on all "menu" bookmarks being listed first in the imported file :-|
if (i < rootFolderCount) {
checkItem(test_bookmarks.menu[i], child);
}
@ -343,9 +346,8 @@ function testImportedBookmarksToFolder(aFolder)
let group = /Toolbar/.test(container.title) ? test_bookmarks.toolbar
: test_bookmarks.unfiled;
container.containerOpen = true;
print(container.title);
do_print("[testImportedBookmarksToFolder()] Checking container '" + container.title + "'");
for (let t = 0; t < container.childCount; t++) {
print(group[t].title + " " + container.getChild(t).title);
checkItem(group[t], container.getChild(t));
}
container.containerOpen = false;

View File

@ -199,7 +199,7 @@ menuitem.bookmark-item {
}
/* Bookmark items */
.bookmark-item:not([container]) {
.bookmark-item {
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");
}
.query-item[container] {
list-style-image: url("chrome://browser/skin/places/history.png");
}
.bookmark-item[livemark] {
.bookmark-item[container][livemark] {
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");
}
@ -257,20 +262,23 @@ toolbarbutton.bookmark-item > menupopup {
list-style-image: url("chrome://global/skin/tree/folder.png");
}
.bookmark-item[livemark] .menuitem-iconic {
list-style-image: url("chrome://browser/skin/places/livemark-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
.bookmark-item[livemark] .menuitem-iconic[visited] {
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
.bookmark-item menuitem[openInTabs],
.bookmark-item menuitem[siteURI] {
/* Workaround for native menubar inheritance */
.openintabs-menuitem,
.openlivemarksite-menuitem,
.livemarkstatus-menuitem {
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 {
background: url("chrome://browser/skin/places/bookmarksToolbar.png") no-repeat center;
}
@ -287,16 +295,6 @@ toolbarbutton.bookmark-item > menupopup {
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,
#BMB_bookmarksToolbar {
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;
background-clip: padding-box;
border: 1px solid ThreeDShadow;
border-radius: 2.5px;
border-radius: 2px;
}
#urlbar {

View File

@ -74,6 +74,6 @@
-moz-padding-start: 4px;
background-clip: padding-box;
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):
"""Kill the process, preferrably in a way that gets us a stack trace."""
if not debuggerInfo and not self.haveDumpedScreen:
self.dumpScreen(utilityPath)
if not debuggerInfo:
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.UNIXISH:
@ -796,8 +799,11 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
if stackFixerFunction:
line = stackFixerFunction(line)
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:
self.dumpScreen(utilityPath)
if not debuggerInfo and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line:
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)
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
the GC) to the tests that created them and prints leak statistics.
"""
MAX_LEAK_COUNT = 130
MAX_LEAK_COUNT = 123
def __init__(self, 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
* 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.util.HashMap;
import java.util.List;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
@ -291,7 +293,7 @@ public class FennecNativeDriver implements Driver {
return null;
}
public int[][] getPaintedSurface() {
public PaintedSurface getPaintedSurface() {
GLSurfaceView view = getSurfaceView();
if (view == null) {
return null;
@ -309,14 +311,34 @@ public class FennecNativeDriver implements Driver {
int w = view.getWidth();
int h = view.getHeight();
pixelBuffer.position(0);
int[][] pixels = new int[h][w];
for (int y = h - 1; y >= 0; y--) {
for (int x = 0; x < w; x++) {
int agbr = pixelBuffer.get();
pixels[y][x] = (agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000);
String mapFile = "/mnt/sdcard/pixels.map";
FileOutputStream fos = null;
DataOutputStream dos = null;
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;

View File

@ -61,11 +61,15 @@ _JAVA_HARNESS = \
FennecNativeDriver.java \
FennecNativeElement.java \
RoboCopException.java \
PaintedSurface.java \
$(NULL)
_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 = \
$(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_INTERFACE_MAP_BEGIN(nsNullPrincipalURI)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURI)
if (aIID.Equals(kNullPrincipalURIImplementationCID))
foundInterface = static_cast<nsIURI *>(this);
else
NS_INTERFACE_MAP_ENTRY(nsIURI)
NS_INTERFACE_MAP_ENTRY(nsISizeOf)
NS_INTERFACE_MAP_END
////////////////////////////////////////////////////////////////////////////////
@ -299,3 +300,19 @@ nsNullPrincipalURI::SchemeIs(const char *aScheme, bool *_schemeIs)
*_schemeIs = (0 == nsCRT::strcasecmp(mScheme.get(), aScheme));
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__
#include "nsIURI.h"
#include "nsISizeOf.h"
#include "nsAutoPtr.h"
#include "nsString.h"
@ -54,11 +55,16 @@
{0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
class nsNullPrincipalURI : public nsIURI
, public nsISizeOf
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIURI
// nsISizeOf
virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
nsNullPrincipalURI(const nsCString &aSpec);
private:

View File

@ -301,6 +301,10 @@ MOZ_NATIVE_NSS = @MOZ_NATIVE_NSS@
MOZ_B2G_RIL = @MOZ_B2G_RIL@
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@
COMPILE_ENVIRONMENT = @COMPILE_ENVIRONMENT@

View File

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

View File

@ -628,9 +628,10 @@ if test "$GXX" = "yes"; then
GNU_CXX=1
CXX_VERSION=`$CXX -v 2>&1 | grep 'gcc version'`
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
fi
rm -f conftest.out
if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
GNU_LD=1
fi
@ -1836,6 +1837,33 @@ if test -n "$CLANG_CXX"; then
_WARNINGS_CXXFLAGS="-Qunused-arguments ${_WARNINGS_CXXFLAGS}"
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 GNU specific defaults
dnl ========================================================
@ -1846,8 +1874,13 @@ if test "$GNU_CC"; then
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
DSO_LDOPTS='-shared'
if test "$GCC_USE_GNU_LD"; then
# Don't allow undefined symbols in libraries
DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
# Some tools like ASan use a runtime library that is only
# 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
WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized'
DSO_CFLAGS=''
@ -9212,7 +9245,7 @@ if test -z "$MOZ_NATIVE_NSPR"; then
fi
if test "$MOZ_OPTIMIZE" = "1"; then
ac_configure_args="$ac_configure_args --enable-optimize"
else
elif test -z "$MOZ_OPTIMIZE"; then
ac_configure_args="$ac_configure_args --disable-optimize"
fi
if test -n "$HAVE_64BIT_OS"; then

View File

@ -41,6 +41,7 @@
#include "nsEventStates.h"
#include "nsIURL.h"
#include "nsISizeOf.h"
#include "nsContentUtils.h"
#include "nsEscape.h"
@ -531,5 +532,24 @@ Link::SetHrefAttribute(nsIURI *aURI)
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 mozilla

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -597,29 +597,10 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
if (aCx && wrapper) {
nsIXPConnect *xpc = nsContentUtils::XPConnect();
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;
rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode,
getter_AddRefs(oldWrapper));
if (preservedWrapper) {
nsContentUtils::PreserveWrapper(aNode, aNode);
}
if (NS_FAILED(rv)) {
aNode->mNodeInfo.swap(nodeInfo);

View File

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

View File

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

View File

@ -122,7 +122,7 @@ JSValToMatrixElts(JSContext* cx, const jsval& val,
double* (&elts)[N], nsresult* rv)
{
JSObject* obj;
jsuint length;
uint32_t length;
if (JSVAL_IS_PRIMITIVE(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
// anybody...
static const jsuint MAX_NUM_DASHES = 1 << 14;
static const uint32_t MAX_NUM_DASHES = 1 << 14;
if (!JSVAL_IS_PRIMITIVE(patternArray)) {
JSObject* obj = JSVAL_TO_OBJECT(patternArray);
jsuint length;
uint32_t length;
if (!JS_GetArrayLength(cx, obj, &length)) {
// Not an array-like thing
return NS_ERROR_INVALID_ARG;

View File

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

View File

@ -377,7 +377,7 @@ function start() {
default:
throw 'unhandled';
break;
};
}
};
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,
// rather than having them result in 100's of failures (one in each test page)
var canvas = document.getElementById("webglcheck-default");
var ctx;
try {
ctx = canvas.getContext("experimental-webgl");
} catch(e) {
ok(false, "canvas.getContext() failed", e);
}
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 {
ctx = document.getElementById("webglcheck-default")
.getContext("experimental-webgl");
} catch(e) {}
if (!ctx) {
var errmsg = "Can't create a WebGL context";
reporter.fullResultsNode.textContent = errmsg;
// Workaround for SeaMonkey tinderboxes which don't support WebGL.
@ -434,8 +419,22 @@ function start() {
ok(false, errmsg);
dump("WebGL mochitest failed: " + errmsg + "\n");
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);

View File

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

View File

@ -96,8 +96,8 @@ public:
// nsIDOMHTMLAnchorElement
NS_DECL_NSIDOMHTMLANCHORELEMENT
// TODO: nsHTMLAnchorElement::SizeOfAnchorElement should call
// Link::SizeOfExcludingThis(). See bug 682431.
// DOM memory reporter participant
NS_DECL_SIZEOF_EXCLUDING_THIS
// nsILink
NS_IMETHOD LinkAdded() { return NS_OK; }
@ -520,3 +520,10 @@ nsHTMLAnchorElement::IntrinsicState() const
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
NS_DECL_ISUPPORTS_INHERITED
// TODO: nsHTMLAreaElement::SizeOfAnchorElement should call
// Link::SizeOfExcludingThis(). See bug 682431.
// DOM memory reporter participant
NS_DECL_SIZEOF_EXCLUDING_THIS
// nsIDOMNode
NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
@ -335,3 +335,11 @@ nsHTMLAreaElement::IntrinsicState() const
{
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
NS_DECL_NSIDOMHTMLLINKELEMENT
// TODO: nsHTMLLinkElement::SizeOfAnchorElement should call
// Link::SizeOfExcludingThis(). See bug 682431.
// DOM memory reporter participant
NS_DECL_SIZEOF_EXCLUDING_THIS
// nsILink
NS_IMETHOD LinkAdded();
@ -458,3 +458,11 @@ nsHTMLLinkElement::IntrinsicState() const
{
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 "nsICharsetAlias.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsPrintfCString.h"
@ -102,7 +100,6 @@
#include "nsFrameSelection.h"
#include "nsISelectionPrivate.h"//for toStringwithformat code
#include "nsICharsetAlias.h"
#include "nsContentUtils.h"
#include "nsJSUtils.h"
#include "nsIDocumentEncoder.h" //for outputting selection

View File

@ -2019,6 +2019,13 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
// duration.
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();
PRInt64 now = DurationToUsecs(TimeStamp::Now() - mPlayStartTime) + mPlayDuration;
remainingTime = currentFrame->mEndTime - mStartTime - now;

View File

@ -42,6 +42,7 @@
#include "nsMediaCache.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsXULAppAPI.h"
#include "nsNetUtil.h"
#include "prio.h"
#include "nsThreadUtils.h"
@ -545,8 +546,15 @@ nsMediaCache::Init()
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
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;
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);
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
// need to revert the clone's width/height to the width/height of the
// content that's being cloned.
nsSVGSVGElement* svgElement =
static_cast<nsSVGSVGElement*>(mSource.get());
svgElement->SyncWidthOrHeight(aName, target);
TriggerReclone();
return;
}
// Our width/height attribute is now no longer explicitly set, so we

View File

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

View File

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

View File

@ -55,7 +55,8 @@
#include "txList.h"
#include "nsIAtom.h"
#include "nsDoubleHashtable.h"
#include "nsTHashtable.h"
#include "nsBaseHashtable.h"
#include "nsString.h"
#include "txCore.h"
#include "nsAutoPtr.h"
@ -229,24 +230,7 @@ class NodeDefinition : public Node
//Definition and Implementation of a Document.
//
/**
* 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&)
typedef nsTHashtable<nsBaseHashtableET<nsStringHashKey, Element*> > txIDMap;
class Document : public NodeDefinition
{

View File

@ -39,7 +39,7 @@
#ifndef txKey_h__
#define txKey_h__
#include "nsDoubleHashtable.h"
#include "nsTHashtable.h"
#include "txNodeSet.h"
#include "txList.h"
#include "txXSLTPatterns.h"
@ -68,21 +68,31 @@ public:
struct txKeyValueHashEntry : public PLDHashEntryHdr
{
txKeyValueHashEntry(const void* aKey)
: mKey(*static_cast<const txKeyValueHashKey*>(aKey)),
mNodeSet(new txNodeSet(nsnull))
{
}
public:
typedef const txKeyValueHashKey& KeyType;
typedef const txKeyValueHashKey* KeyTypePointer;
// @see nsDoubleHashtable.h
bool MatchEntry(const void* aKey) const;
static PLDHashNumber HashKey(const void* aKey);
txKeyValueHashEntry(KeyTypePointer aKey)
: mKey(*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;
nsRefPtr<txNodeSet> mNodeSet;
};
DECL_DHASH_WRAPPER(txKeyValueHash, txKeyValueHashEntry, txKeyValueHashKey&)
typedef nsTHashtable<txKeyValueHashEntry> txKeyValueHash;
class txIndexedKeyHashKey
{
@ -100,22 +110,31 @@ public:
struct txIndexedKeyHashEntry : public PLDHashEntryHdr
{
txIndexedKeyHashEntry(const void* aKey)
: mKey(*static_cast<const txIndexedKeyHashKey*>(aKey)),
mIndexed(false)
{
}
public:
typedef const txIndexedKeyHashKey& KeyType;
typedef const txIndexedKeyHashKey* KeyTypePointer;
// @see nsDoubleHashtable.h
bool MatchEntry(const void* aKey) const;
static PLDHashNumber HashKey(const void* aKey);
txIndexedKeyHashEntry(KeyTypePointer aKey)
: mKey(*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;
bool mIndexed;
};
DECL_DHASH_WRAPPER(txIndexedKeyHash, txIndexedKeyHashEntry,
txIndexedKeyHashKey&)
typedef nsTHashtable<txIndexedKeyHashEntry> txIndexedKeyHash;
/**
* 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
*/
DHASH_WRAPPER(txKeyValueHash, txKeyValueHashEntry, txKeyValueHashKey&)
DHASH_WRAPPER(txIndexedKeyHash, txIndexedKeyHashEntry, txIndexedKeyHashKey&)
bool
txKeyValueHashEntry::MatchEntry(const void* aKey) const
txKeyValueHashEntry::KeyEquals(KeyTypePointer aKey) const
{
const txKeyValueHashKey* key =
static_cast<const txKeyValueHashKey*>(aKey);
return mKey.mKeyName == key->mKeyName &&
mKey.mRootIdentifier == key->mRootIdentifier &&
mKey.mKeyValue.Equals(key->mKeyValue);
return mKey.mKeyName == aKey->mKeyName &&
mKey.mRootIdentifier == aKey->mRootIdentifier &&
mKey.mKeyValue.Equals(aKey->mKeyValue);
}
PLDHashNumber
txKeyValueHashEntry::HashKey(const void* aKey)
txKeyValueHashEntry::HashKey(KeyTypePointer aKey)
{
const txKeyValueHashKey* key =
static_cast<const txKeyValueHashKey*>(aKey);
return key->mKeyName.mNamespaceID ^
NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^
key->mRootIdentifier ^
HashString(key->mKeyValue);
return aKey->mKeyName.mNamespaceID ^
NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
aKey->mRootIdentifier ^
HashString(aKey->mKeyValue);
}
bool
txIndexedKeyHashEntry::MatchEntry(const void* aKey) const
txIndexedKeyHashEntry::KeyEquals(KeyTypePointer aKey) const
{
const txIndexedKeyHashKey* key =
static_cast<const txIndexedKeyHashKey*>(aKey);
return mKey.mKeyName == key->mKeyName &&
mKey.mRootIdentifier == key->mRootIdentifier;
return mKey.mKeyName == aKey->mKeyName &&
mKey.mRootIdentifier == aKey->mRootIdentifier;
}
PLDHashNumber
txIndexedKeyHashEntry::HashKey(const void* aKey)
txIndexedKeyHashEntry::HashKey(KeyTypePointer aKey)
{
const txIndexedKeyHashKey* key =
static_cast<const txIndexedKeyHashKey*>(aKey);
return key->mKeyName.mNamespaceID ^
NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^
key->mRootIdentifier;
return aKey->mKeyName.mNamespaceID ^
NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
aKey->mRootIdentifier;
}
/*
@ -211,9 +196,6 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
txExecutionState& aEs,
txNodeSet** aResult)
{
NS_ENSURE_TRUE(mKeyValues.mHashTable.ops && mIndexedKeys.mHashTable.ops,
NS_ERROR_OUT_OF_MEMORY);
*aResult = nsnull;
PRInt32 identifier = txXPathNodeUtils::getUniqueIdentifier(aRoot);
@ -241,7 +223,7 @@ txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
}
txIndexedKeyHashKey indexKey(aKeyName, identifier);
txIndexedKeyHashEntry* indexEntry = mIndexedKeys.AddEntry(indexKey);
txIndexedKeyHashEntry* indexEntry = mIndexedKeys.PutEntry(indexKey);
NS_ENSURE_TRUE(indexEntry, NS_ERROR_OUT_OF_MEMORY);
if (indexEntry->mIndexed) {
@ -412,7 +394,7 @@ nsresult txXSLKey::testNode(const txXPathNode& aNode,
txXPathNodeUtils::appendNodeValue(res->get(i), val);
aKey.mKeyValue.Assign(val);
txKeyValueHashEntry* entry = aKeyValueHash.AddEntry(aKey);
txKeyValueHashEntry* entry = aKeyValueHash.PutEntry(aKey);
NS_ENSURE_TRUE(entry && entry->mNodeSet,
NS_ERROR_OUT_OF_MEMORY);
@ -427,7 +409,7 @@ nsresult txXSLKey::testNode(const txXPathNode& aNode,
exprResult->stringValue(val);
aKey.mKeyValue.Assign(val);
txKeyValueHashEntry* entry = aKeyValueHash.AddEntry(aKey);
txKeyValueHashEntry* entry = aKeyValueHash.PutEntry(aKey);
NS_ENSURE_TRUE(entry && entry->mNodeSet,
NS_ERROR_OUT_OF_MEMORY);

View File

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

View File

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

View File

@ -64,7 +64,7 @@
#include "nsIDocumentTransformer.h"
#include "mozilla/css/Loader.h"
#include "mozilla/dom/Element.h"
#include "nsICharsetAlias.h"
#include "nsCharsetAlias.h"
#include "nsIHTMLContentSink.h"
#include "nsContentUtils.h"
#include "txXMLUtils.h"
@ -857,11 +857,7 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, PRInt32 aNsID
if (!mOutputFormat.mEncoding.IsEmpty()) {
NS_LossyConvertUTF16toASCII charset(mOutputFormat.mEncoding);
nsCAutoString canonicalCharset;
nsCOMPtr<nsICharsetAlias> calias =
do_GetService("@mozilla.org/intl/charsetalias;1");
if (calias &&
NS_SUCCEEDED(calias->GetPreferred(charset, canonicalCharset))) {
if (NS_SUCCEEDED(nsCharsetAlias::GetPreferred(charset, canonicalCharset))) {
mDocument->SetDocumentCharacterSetSource(kCharsetFromOtherComponent);
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)
endif
EXTRA_JS_MODULES += DOMRequestHelper.jsm \
$(NULL)
XPIDLSRCS = \
nsIDOMDOMError.idl \
nsIDOMDOMRequest.idl \

View File

@ -70,6 +70,8 @@
#include "mozilla/Telemetry.h"
#include "BatteryManager.h"
#include "PowerManager.h"
#include "nsIDOMWakeLock.h"
#include "nsIPowerManagerService.h"
#include "SmsManager.h"
#include "nsISmsService.h"
#include "mozilla/Hal.h"
@ -172,7 +174,10 @@ Navigator::Invalidate()
mBatteryManager = nsnull;
}
mPowerManager = nsnull;
if (mPowerManager) {
mPowerManager->Shutdown();
mPowerManager = nsnull;
}
if (mSmsManager) {
mSmsManager->Shutdown();
@ -958,15 +963,38 @@ Navigator::GetMozBattery(nsIDOMMozBatteryManager** aBattery)
NS_IMETHODIMP
Navigator::GetMozPower(nsIDOMMozPowerManager** aPower)
{
*aPower = nsnull;
if (!mPowerManager) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(win, NS_OK);
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;
}
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
//*****************************************************************************

View File

@ -1,38 +1,6 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is 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 ***** */
/* 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/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
@ -41,27 +9,31 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.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() {
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 = {
_onerror: null,
_oninstall: null,
_onuninstall: null,
__proto__: DOMRequestIpcHelper.prototype,
/** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest
* only the name property is mandatory
@ -70,7 +42,7 @@ WebappsRegistry.prototype = {
// TODO : check for install_allowed_from
if (aManifest.name == undefined)
return false;
if (aManifest.installs_allowed_from) {
ok = false;
aManifest.installs_allowed_from.forEach(function(aOrigin) {
@ -81,97 +53,41 @@ WebappsRegistry.prototype = {
}
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) {
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
let req = this.getRequest(msg.requestID);
if (!req)
return;
let app = msg.app;
let cb;
switch (aMessage.name) {
case "Webapps:Install:Return:OK":
if (this._oninstall)
this._oninstall.handleEvent(new WebappsApplication(app.origin, app.manifest, app.receipt,
Services.rs.fireSuccess(req, new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
app.installOrigin, app.installTime));
break;
case "Webapps:Install:Return:KO":
if (this._onerror)
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.DENIED));
Services.rs.fireError(req, "DENIED");
break;
case "Webapps:Uninstall:Return:OK":
if (this._onuninstall)
this._onuninstall.handleEvent(new WebappsApplication(msg.origin, null, null, null, 0));
break;
case "Webapps:Uninstall:Return:KO":
if (this._onerror)
this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
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);
case "Webapps:GetSelf:Return:OK":
if (msg.apps.length) {
app = msg.apps[0];
Services.rs.fireSuccess(req, new WebappsApplication(this._window, app.origin, app.manifest, app.manifestURL, app.receipts,
app.installOrigin, app.installTime));
} else {
Services.rs.fireSuccess(req, null);
}
break;
case "Webapps:Enumerate:Return:KO":
cb = this.getCallback(msg.callbackID);
if (cb.error)
cb.error.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
case "Webapps:GetInstalled:Return:OK":
Services.rs.fireSuccess(req, convertAppsArray(msg.apps, this._window));
break;
case "Webapps:GetSelf:Return:KO":
case "Webapps:GetInstalled:Return:KO":
Services.rs.fireError(req, "ERROR");
break;
}
this.removeCallback(msg.callbackID);
},
_fireError: function(aCode) {
if (!this._onerror)
return;
this._onerror.handleEvent(new RegistryError(aCode));
this.removeRequest(msg.requestID);
},
_getOrigin: function(aURL) {
@ -181,7 +97,9 @@ WebappsRegistry.prototype = {
// 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);
xhr.open("GET", aURL, true);
@ -191,90 +109,70 @@ WebappsRegistry.prototype = {
let installOrigin = this._getOrigin(this._window.location.href);
let manifest = JSON.parse(xhr.responseText, installOrigin);
if (!this.checkManifest(manifest, installOrigin)) {
this._fireError(Ci.mozIDOMApplicationRegistryError.INVALID_MANIFEST);
Services.rs.fireError(request, "INVALID_MANIFEST");
} else {
this.mm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
origin: this._getOrigin(aURL),
manifest: manifest,
receipt: aReceipt },
from: this._window.location.href,
oid: this._id });
let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : [];
cpmm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
origin: this._getOrigin(aURL),
manifestURL: aURL,
manifest: manifest,
receipts: receipts },
from: this._window.location.href,
oid: this._id,
requestID: requestID });
}
} catch(e) {
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_PARSE_ERROR);
Services.rs.fireError(request, "MANIFEST_PARSE_ERROR");
}
}
else {
this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_URL_ERROR);
Services.rs.fireError(request, "MANIFEST_URL_ERROR");
}
}).bind(this), false);
xhr.addEventListener("error", (function() {
this._fireError(Ci.mozIDOMApplicationRegistryError.NETWORK_ERROR);
Services.rs.fireError(request, "NETWORK_ERROR");
}).bind(this), false);
xhr.send(null);
return request;
},
uninstall: function(aOrigin) {
if (this.hasPrivileges)
this.mm.sendAsyncMessage("Webapps:Uninstall", { from: this._window.location.href,
origin: aOrigin,
oid: this._id });
else
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
getSelf: function() {
let request = this.createRequest();
cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
oid: this._id,
requestID: this.getRequestId(request) });
return request;
},
launch: function(aOrigin) {
this.mm.sendAsyncMessage("Webapps:Launch", { origin: aOrigin,
from: 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),
getInstalled: function() {
let request = this.createRequest();
cpmm.sendAsyncMessage("Webapps:GetInstalled", { origin: this._getOrigin(this._window.location.href),
oid: this._id,
callbackID: this.getCallbackId({ success: aSuccess, error: aError }) });
requestID: this.getRequestId(request) });
return request;
},
enumerateAll: function(aSuccess, aError) {
if (this.hasPrivileges) {
this.mm.sendAsyncMessage("Webapps:EnumerateAll", { from: this._window.location.href,
origin: this._getOrigin(this._window.location.href),
oid: this._id,
callbackID: this.getCallbackId({ success: aSuccess, error: aError }) });
} else {
if (aError)
aError.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
}
get mgmt() {
if (!this._mgmt)
this._mgmt = new WebappsApplicationMgmt(this._window);
return this._mgmt;
},
observe: function(aSubject, aTopic, aData) {
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
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;
}
uninit: function() {
this._mgmt = null;
},
// nsIDOMGlobalPropertyInitializer implementation
init: function(aWindow) {
dump("DOMApplicationRegistry::init() " + aWindow + "\n");
this._window = aWindow;
this._window.appId = this._id;
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");
this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
"Webapps:GetInstalled:Return:OK", "Webapps:GetInstalled:Return:KO",
"Webapps:GetSelf:Return:OK", "Webapps:GetSelf:Return:KO"]);
Services.obs.addObserver(this, "inner-window-destroyed", false);
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}"),
@ -288,18 +186,26 @@ WebappsRegistry.prototype = {
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._manifest = aManifest;
this._receipt = aReceipt;
this._manifestURL = aManifestURL;
this._receipts = aReceipts;
this._installOrigin = aInstallOrigin;
this._installTime = aInstallTime;
this.initHelper(aWindow, ["Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO"]);
}
WebappsApplication.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
_origin: null,
_manifest: null,
_receipt: null,
_manifestURL: null,
_receipts: [],
_installOrigin: null,
_installTime: 0,
@ -311,8 +217,12 @@ WebappsApplication.prototype = {
return this._manifest;
},
get receipt() {
return this._receipt;
get manifestURL() {
return this._manifestURL;
},
get receipts() {
return this._receipts;
},
get installOrigin() {
@ -323,6 +233,39 @@ WebappsApplication.prototype = {
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}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication]),
@ -334,26 +277,131 @@ WebappsApplication.prototype = {
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 = {
_code: null,
get code() {
return this._code;
WebappsApplicationMgmt.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
uninit: function() {
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}"),
contractID: "@mozilla.org/webapps/error;1",
interfaces: [Ci.mozIDOMApplicationRegistryError],
get oninstall() {
return this._oninstall;
},
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,
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 *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla 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 ***** */
/* 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/. */
const Cu = Components.utils;
const Cc = Components.classes;
@ -50,17 +17,21 @@ XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
return NetUtil;
});
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
});
let DOMApplicationRegistry = {
appsFile: null,
webapps: { },
init: function() {
this.mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
let messages = ["Webapps:Install", "Webapps:Uninstall",
"Webapps:Enumerate", "Webapps:EnumerateAll", "Webapps:Launch"];
"Webapps:GetSelf", "Webapps:GetInstalled",
"Webapps:Launch", "Webapps:GetAll"];
messages.forEach((function(msgName) {
this.mm.addMessageListener(msgName, this);
ppmm.addMessageListener(msgName, this);
}).bind(this));
let appsDir = FileUtils.getDir("ProfD", ["webapps"], true, true);
@ -114,29 +85,29 @@ let DOMApplicationRegistry = {
receiveMessage: function(aMessage) {
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) {
case "Webapps:Install":
// always ask for UI to install
Services.obs.notifyObservers(this, "webapps-ask-install", JSON.stringify(msg));
break;
case "Webapps:GetSelf":
this.getSelf(msg);
break;
case "Webapps:Uninstall":
if (hasPrivileges)
this.uninstall(msg);
this.uninstall(msg);
break;
case "Webapps:Launch":
Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg));
break;
case "Webapps:Enumerate":
this.enumerate(msg);
case "Webapps:GetInstalled":
this.getInstalled(msg);
break;
case "Webapps:EnumerateAll":
this.enumerateAll(msg);
case "Webapps:GetAll":
if (msg.hasPrivileges)
this.getAll(msg);
else
ppmm.sendAsyncMessage("Webapps:GetAll:Return:KO", msg);
break;
}
},
@ -162,14 +133,15 @@ let DOMApplicationRegistry = {
let clone = {
installOrigin: aApp.installOrigin,
origin: aApp.origin,
receipt: aApp.receipt,
installTime: aApp.installTime
receipts: aApp.receipts,
installTime: aApp.installTime,
manifestURL: aApp.manifestURL
};
return clone;
},
denyInstall: function(aData) {
this.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
ppmm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
},
confirmInstall: function(aData, aFromSync) {
@ -202,7 +174,7 @@ let DOMApplicationRegistry = {
if (!aFromSync)
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);
}).bind(this));
},
@ -244,9 +216,11 @@ let DOMApplicationRegistry = {
},
uninstall: function(aData) {
let found = false;
for (let id in this.webapps) {
let app = this.webapps[id];
if (app.origin == aData.origin) {
found = true;
delete this.webapps[id];
let dir = FileUtils.getDir("ProfD", ["webapps", id], true, true);
try {
@ -254,62 +228,53 @@ let DOMApplicationRegistry = {
} catch (e) {
}
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);
}).bind(this));
}
}
if (!found)
ppmm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
},
enumerate: function(aData) {
getSelf: function(aData) {
aData.apps = [];
let tmp = [];
let selfId;
let id = this._appId(aData.origin);
// if it's an app, add itself to the result
if (id) {
let app = this._cloneAppObject(this.webapps[id]);
aData.apps.push(app);
tmp.push({ id: id });
selfId = id;
}
// check if it's a store.
let isStore = false;
this._readManifests(tmp, (function(aResult) {
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) {
let app = this.webapps[id];
if (app.installOrigin == aData.origin) {
isStore = true;
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 });
}
if (this.webapps[id].installOrigin == aData.origin) {
aData.apps.push(this._cloneAppObject(this.webapps[id]));
tmp.push({ id: id });
}
}
this._readManifests(tmp, (function(aResult) {
for (let i = 0; i < aResult.length; i++)
aData.apps[i].manifest = aResult[i].manifest;
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
ppmm.sendAsyncMessage("Webapps:GetInstalled:Return:OK", aData);
}).bind(this));
},
denyEnumerate: function(aData) {
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:KO", aData);
},
enumerateAll: function(aData) {
getAll: function(aData) {
aData.apps = [];
let tmp = [];
@ -322,7 +287,7 @@ let DOMApplicationRegistry = {
this._readManifests(tmp, (function(aResult) {
for (let i = 0; i < aResult.length; i++)
aData.apps[i].manifest = aResult[i].manifest;
this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
ppmm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
}).bind(this));
},
@ -368,7 +333,7 @@ let DOMApplicationRegistry = {
dir.remove(true);
} catch (e) {
}
this.mm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
} else {
if (!!this.webapps[record.id]) {
this.webapps[record.id] = record.value;
@ -377,7 +342,7 @@ let DOMApplicationRegistry = {
else {
let data = { app: record.value };
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
contract @mozilla.org/webapps;1 {fff440b3-fae2-45c1-bf03-3b5a2e432270}
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 "BatteryManager.h"
#include "nsIDOMPowerManager.h"
#include "nsIDOMWakeLock.h"
#include "nsIDOMSmsManager.h"
#include "nsIDOMSmsMessage.h"
#include "nsIDOMSmsEvent.h"
@ -548,6 +549,7 @@ static const char kDOMStringBundleURL[] =
nsIXPCScriptable::WANT_ENUMERATE | \
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
nsIXPCScriptable::USE_STUB_EQUALITY_HOOK | \
nsIXPCScriptable::IS_GLOBAL_OBJECT | \
nsIXPCScriptable::WANT_OUTER_OBJECT)
#define NODE_SCRIPTABLE_FLAGS \
@ -1435,6 +1437,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozWakeLock, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozSmsManager, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1549,7 +1554,7 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(AnimationEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
DOM_DEFAULT_SCRIPTABLE_FLAGS | nsIXPCScriptable::IS_GLOBAL_OBJECT)
NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -1617,8 +1622,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
#endif
#ifdef MOZ_B2G_BT
NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
#endif
NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
@ -4030,6 +4035,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager)
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_ENTRY(nsIDOMMozSmsManager)
DOM_CLASSINFO_MAP_END

View File

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

View File

@ -144,7 +144,11 @@ static PRLogModuleInfo* gJSDiagnostics;
#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
@ -2227,11 +2231,9 @@ nsJSContext::CreateNativeGlobalForInner(
nsRefPtr<nsIXPConnectJSObjectHolder> jsholder;
nsresult rv = xpc->
InitClassesWithNewWrappedGlobal(mContext,
aNewInner, NS_GET_IID(nsISupports),
InitClassesWithNewWrappedGlobal(mContext, aNewInner,
aIsChrome ? systemPrincipal.get() : aPrincipal,
nsnull, flags,
getter_AddRefs(jsholder));
flags, getter_AddRefs(jsholder));
if (NS_FAILED(rv)) {
return rv;
}
@ -2324,7 +2326,7 @@ nsJSContext::SetOuterObject(JSObject* aOuterObject)
NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
wrapper->RefreshPrototype();
wrapper->FinishInitForWrappedGlobal();
JS_SetPrototype(mContext, aOuterObject, JS_GetPrototype(inner));
return NS_OK;
@ -3286,46 +3288,70 @@ ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
nsJSContext::ShrinkGCBuffersNow();
}
// static
void
static bool
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)
{
if (sDidShutdown) {
return;
}
if (sCCLockedOut) {
if (sDidShutdown || sCCLockedOut) {
return;
}
++sCCTimerFireCount;
if (sCCTimerFireCount < (NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY)) {
PRUint32 suspected = nsCycleCollector_suspectedCount();
if ((sPreviousSuspectedCount + 100) > suspected) {
// Just few new suspected objects, return early.
return;
}
PRTime startTime = PR_Now();
nsCycleCollector_forgetSkippable();
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
sCleanupSinceLastGC = true;
PRTime delta = PR_Now() - startTime;
if (sMinForgetSkippableTime > delta) {
sMinForgetSkippableTime = delta;
}
if (sMaxForgetSkippableTime < delta) {
sMaxForgetSkippableTime = delta;
}
sTotalForgetSkippableTime += delta;
sRemovedPurples += (suspected - sPreviousSuspectedCount);
++sForgetSkippableBeforeCC;
} else {
sPreviousSuspectedCount = 0;
nsJSContext::KillCCTimer();
if (sNeedsFullCC ||
nsCycleCollector_suspectedCount() > 500 ||
sLastCCEndTime + NS_CC_FORCED < PR_Now()) {
// During early timer fires, we only run forgetSkippable. During the first
// late timer fire, we decide if we are going to have a second and final
// late timer fire, where we may run the CC.
const PRUint32 numEarlyTimerFires = NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY - 2;
bool isLateTimerFire = sCCTimerFireCount > numEarlyTimerFires;
PRUint32 suspected = nsCycleCollector_suspectedCount();
if (isLateTimerFire && ShouldTriggerCC(suspected)) {
if (sCCTimerFireCount == numEarlyTimerFires + 1) {
TimerFireForgetSkippable(suspected, true);
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
// Our efforts to avoid a CC have failed, so we return to let the
// timer fire once more to trigger a CC.
return;
}
} else {
// We are in the final timer fire and still meet the conditions for
// triggering a CC.
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>
#endif
#define POWERED_EVENT_NAME NS_LITERAL_STRING("powered")
BEGIN_BLUETOOTH_NAMESPACE
USING_BLUETOOTH_NAMESPACE
class ToggleBtResultTask : public nsRunnable
{
public:
ToggleBtResultTask(bool result, nsRefPtr<BluetoothAdapter>& adapterPtr)
ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, bool result)
: mResult(result)
{
MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread
MOZ_ASSERT(!NS_IsMainThread());
mAdapterPtr.swap(adapterPtr);
}
NS_IMETHOD Run() {
MOZ_ASSERT(NS_IsMainThread()); // This method is supposed to run on the main thread!
NS_IMETHOD Run()
{
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 = nsnull;
return NS_OK;
}
private:
bool mResult;
nsRefPtr<BluetoothAdapter> mAdapterPtr;
bool mResult;
};
class ToggleBtTask : public nsRunnable
{
public:
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
: 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() {
bool result;
NS_IMETHOD Run()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread.
bool result;
//Toggle BT here
#if defined(MOZ_WIDGET_GONK)
@ -65,13 +74,16 @@ class ToggleBtTask : public nsRunnable
} else {
result = bt_disable();
}
#else
#else
result = true;
#endif
// Create a result thread and pass it to Main Thread,
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(result, mAdapterPtr);
NS_DispatchToMainThread(resultRunnable);
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, result);
if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
NS_WARNING("Failed to dispatch to main thread!");
}
return NS_OK;
}
@ -81,25 +93,21 @@ class ToggleBtTask : public nsRunnable
bool mOnOff;
};
END_BLUETOOTH_NAMESPACE
DOMCI_DATA(BluetoothAdapter, mozilla::dom::bluetooth::BluetoothAdapter)
USING_BLUETOOTH_NAMESPACE
DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
nsDOMEventTargetHelper)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
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_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
@ -107,18 +115,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
BluetoothAdapter::BluetoothAdapter() : mPower(false)
BluetoothAdapter::BluetoothAdapter()
: mPower(false)
{
}
NS_IMETHODIMP
BluetoothAdapter::GetPower(bool* aPower)
{
#if defined(MOZ_WIDGET_GONK)
*aPower = bt_is_enabled();
#else
*aPower = mPower;
#endif
return NS_OK;
}
@ -128,13 +134,13 @@ BluetoothAdapter::SetPower(bool aPower)
if (mPower != aPower) {
mPower = aPower;
ToggleBluetoothAsync();
return ToggleBluetoothAsync();
}
return NS_OK;
}
void
nsresult
BluetoothAdapter::ToggleBluetoothAsync()
{
if (!mToggleBtThread) {
@ -143,14 +149,17 @@ BluetoothAdapter::ToggleBluetoothAsync()
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
mToggleBtThread->Dispatch(r, 0);
return mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
}
nsresult
BluetoothAdapter::FirePowered()
{
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);
bool dummy;

View File

@ -11,10 +11,12 @@
#include "nsDOMEventTargetHelper.h"
#include "nsIDOMBluetoothAdapter.h"
class nsIEventTarget;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothAdapter : public nsIDOMBluetoothAdapter
,public nsDOMEventTargetHelper
, public nsDOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS
@ -36,7 +38,7 @@ protected:
private:
nsCOMPtr<nsIEventTarget> mToggleBtThread;
void ToggleBluetoothAsync();
nsresult ToggleBluetoothAsync();
};
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/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 CONTACTPROPERTIES_CID = Components.ID("{53ed7c20-ceda-11e0-9572-0800200c9a66}");
@ -184,6 +193,7 @@ function ContactManager()
}
ContactManager.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
save: function save(aContact) {
let request;
@ -222,9 +232,9 @@ ContactManager.prototype = {
this._setMetaData(newContact, aContact);
debug("send: " + JSON.stringify(newContact));
request = this._rs.createRequest(this._window);
this._mm.sendAsyncMessage("Contact:Save", {contact: newContact,
requestID: this.getRequestId({ request: request })});
request = this.createRequest();
cpmm.sendAsyncMessage("Contact:Save", {contact: newContact,
requestID: this.getRequestId(request)});
return request;
} else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -234,9 +244,9 @@ ContactManager.prototype = {
remove: function removeContact(aRecord) {
let request;
if (this.hasPrivileges) {
request = this._rs.createRequest(this._window);
this._mm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
requestID: this.getRequestId({ request: request })});
request = this.createRequest();
cpmm.sendAsyncMessage("Contact:Remove", {id: aRecord.id,
requestID: this.getRequestId(request)});
return request;
} else {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@ -260,26 +270,6 @@ ContactManager.prototype = {
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) {
debug("Contactmanager::receiveMessage: " + aMessage.name);
let msg = aMessage.json;
@ -291,7 +281,7 @@ ContactManager.prototype = {
if (req) {
let result = this._convertContactsArray(contacts);
debug("result: " + JSON.stringify(result));
this._rs.fireSuccess(req, result);
Services.rs.fireSuccess(req, result);
} else {
debug("no request stored!" + msg.requestID);
}
@ -301,7 +291,7 @@ ContactManager.prototype = {
case "Contact:Remove:Return:OK":
req = this.getRequest(msg.requestID);
if (req)
this._rs.fireSuccess(req, 0);
Services.rs.fireSuccess(req, null);
break;
case "Contacts:Find:Return:KO":
case "Contact:Save:Return:KO":
@ -309,7 +299,7 @@ ContactManager.prototype = {
case "Contacts:Clear:Return:KO":
req = this.getRequest(msg.requestID);
if (req)
this._rs.fireError(req, msg.errorMsg);
Services.rs.fireError(req, msg.errorMsg);
break;
default:
debug("Wrong message: " + aMessage.name);
@ -320,9 +310,9 @@ ContactManager.prototype = {
find: function(aOptions) {
let request;
if (this.hasPrivileges) {
request = this._rs.createRequest(this._window);
this._mm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions,
requestID: this.getRequestId({ request: request })});
request = this.createRequest();
cpmm.sendAsyncMessage("Contacts:Find", {findOptions: aOptions,
requestID: this.getRequestId(request)});
return request;
} else {
debug("find not allowed");
@ -333,8 +323,8 @@ ContactManager.prototype = {
clear: function() {
let request;
if (this.hasPrivileges) {
request = this._rs.createRequest(this._window);
this._mm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId({ request: request })});
request = this.createRequest();
cpmm.sendAsyncMessage("Contacts:Clear", {requestID: this.getRequestId(request)});
return request;
} else {
debug("clear not allowed");
@ -347,22 +337,12 @@ ContactManager.prototype = {
if (!Services.prefs.getBoolPref("dom.mozContacts.enabled"))
return null;
this._window = aWindow;
this._messages = ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
"Contacts:Clear:Return:OK", "Contacts:Clear: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);
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
this._innerWindowID = util.currentInnerWindowID;
let principal = aWindow.document.nodePrincipal;
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
@ -376,21 +356,6 @@ ContactManager.prototype = {
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,
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/ContactDB.jsm");
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
});
let myGlobal = this;
let DOMContactManager = {
init: function() {
debug("Init");
this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
this._messages = ["Contacts:Find", "Contacts:Clear", "Contact:Save", "Contact:Remove"];
this._messages.forEach((function(msgName) {
this._mm.addMessageListener(msgName, this);
ppmm.addMessageListener(msgName, this);
}).bind(this));
var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
@ -52,10 +54,10 @@ let DOMContactManager = {
observe: function(aSubject, aTopic, aData) {
myGlobal = null;
this._messages.forEach((function(msgName) {
this._mm.removeMessageListener(msgName, this);
ppmm.removeMessageListener(msgName, this);
}).bind(this));
Services.obs.removeObserver(this, "profile-before-change");
this._mm = null;
ppmm = null;
this._messages = null;
if (this._db)
this._db.close();
@ -72,23 +74,23 @@ let DOMContactManager = {
for (let i in contacts)
result.push(contacts[i]);
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),
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);
break;
case "Contact:Save":
this._db.saveContact(msg.contact, function() {this._mm.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));
this._db.saveContact(msg.contact, function() { ppmm.sendAsyncMessage("Contact:Save:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Save:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
break;
case "Contact:Remove":
this._db.removeContact(msg.id,
function() {this._mm.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() { ppmm.sendAsyncMessage("Contact:Remove:Return:OK", { requestID: msg.requestID }); }.bind(this),
function(aErrorMsg) { ppmm.sendAsyncMessage("Contact:Remove:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this));
break;
case "Contacts:Clear":
this._db.clear(function() { this._mm.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));
this._db.clear(function() { ppmm.sendAsyncMessage("Contacts:Clear:Return:OK", { requestID: msg.requestID }); }.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 (!JS_SetArrayLength(aCx, array, jsuint(aReadInfos.Length()))) {
if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
NS_WARNING("Failed to set array length!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}

View File

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

View File

@ -904,7 +904,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
}
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!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}

View File

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

View File

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

View File

@ -36,104 +36,79 @@
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
#include "nsIArray.idl"
#include "nsIDOMEvent.idl"
#include "nsIDOMEventTarget.idl"
[scriptable, uuid(e0c271cb-266b-48c9-a7e4-96590b445c26)]
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;
interface nsIDOMDOMRequest;
readonly attribute short code;
};
[scriptable, uuid(a6856a3d-dece-43ce-89b9-72dba07f4246)]
interface mozIDOMApplication : nsISupports
[scriptable, uuid(b70b84f1-7ac9-4a92-bc32-8b6a7eb7879e)]
interface mozIDOMApplication : nsISupports
{
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 installOrigin;
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)]
interface mozIDOMApplicationRegistryEnumerateCallback : nsISupports
[scriptable, uuid(870bfbdc-3e13-4042-99dd-18e25720782d)]
interface mozIDOMApplicationEvent : nsIDOMEvent
{
void handleEvent([array, size_is(count)] in mozIDOMApplication apps,
in unsigned long count);
readonly attribute mozIDOMApplication application;
};
[scriptable, function, uuid(ae0ed33d-35cf-443a-837b-a6cebf16bd49)]
interface mozIDOMApplicationRegistryErrorCallback : nsISupports
[scriptable, uuid(a82771f6-ba46-4073-9e6e-f1ad3f42b1f6)]
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
{
/**
* Install a web app. onerror can be used to report errors,
* and oninstall if the caller is privileged.
*
* @param manifestUrl : the URL of the webapps manifest
* @param receipt : An opaque string used to track payment status
* @param manifestUrl : the URL of the webapps manifest.
* @param parameters : A structure with optional information.
* { receipts: ... } will be used to specify the payment receipts for this installation.
*/
void install(in DOMString manifestUrl,
[optional] in DOMString receipt);
nsIDOMDOMRequest install(in DOMString manifestUrl, [optional] in jsval parameters);
/**
* This call is only accessible to privileged callers.
*
* @param origin : the origin of the application to uninstall.
* the request will return the application currently installed, or null.
*/
void uninstall(in DOMString origin);
nsIDOMDOMRequest getSelf();
/**
* Enumerate apps : either return itself if caller is an app, or
* 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
* the request will return the applications installed from this origin, or null.
*/
void enumerate(in mozIDOMApplicationRegistryEnumerateCallback success,
[optional] in mozIDOMApplicationRegistryErrorCallback error);
nsIDOMDOMRequest getInstalled();
/**
* 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;
readonly attribute mozIDOMApplicationMgmt mgmt;
};

View File

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

View File

@ -39,7 +39,7 @@
#include "domstubs.idl"
[scriptable, uuid(b1f4b1fa-49c2-4375-9ce8-bf97ecf6b428)]
[scriptable, uuid(e610c037-db58-4cd7-8ed3-0d7f1422b4d3)]
interface nsIDOMNavigator : nsISupports
{
readonly attribute DOMString appCodeName;
@ -110,4 +110,34 @@ interface nsIDOMNavigator : nsISupports
*/
[implicit_jscontext]
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 = \
PowerManagerService.h \
Types.h \
$(NULL)
CPPSRCS = \
PowerManager.cpp \
PowerManagerService.cpp \
WakeLock.cpp \
$(NULL)
XPIDLSRCS = \
nsIDOMPowerManager.idl \
nsIDOMWakeLock.idl \
nsIDOMWakeLockListener.idl \
nsIPowerManagerService.idl \
$(NULL)

View File

@ -36,9 +36,13 @@
* ***** END LICENSE BLOCK ***** */
#include "PowerManager.h"
#include "WakeLock.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIPowerManagerService.h"
#include "nsIPrincipal.h"
#include "nsPIDOMWindow.h"
#include "nsServiceManagerUtils.h"
DOMCI_DATA(MozPowerManager, mozilla::dom::power::PowerManager)
@ -50,20 +54,66 @@ namespace power {
NS_INTERFACE_MAP_BEGIN(PowerManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozPowerManager)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozPowerManager)
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWakeLockListener)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozPowerManager)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(PowerManager)
NS_IMPL_RELEASE(PowerManager)
NS_IMETHODIMP
PowerManager::Reboot()
nsresult
PowerManager::Init(nsIDOMWindow *aWindow)
{
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
mWindow = do_GetWeakReference(aWindow);
nsCOMPtr<nsIPowerManagerService> pmService =
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();
@ -73,17 +123,74 @@ PowerManager::Reboot()
NS_IMETHODIMP
PowerManager::PowerOff()
{
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
nsresult rv = CheckPermission();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
NS_ENSURE_TRUE(pmService, NS_OK);
NS_ENSURE_STATE(pmService);
pmService->PowerOff();
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
} // dom
} // mozilla

View File

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

View File

@ -36,7 +36,12 @@
* ***** END LICENSE BLOCK ***** */
#include "mozilla/Hal.h"
#include "mozilla/HalWakeLock.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsIDOMWakeLockListener.h"
#include "nsIDOMWindow.h"
#include "PowerManagerService.h"
#include "WakeLock.h"
namespace mozilla {
namespace dom {
@ -44,14 +49,67 @@ namespace power {
NS_IMPL_ISUPPORTS1(PowerManagerService, nsIPowerManagerService)
/* static */ nsRefPtr<PowerManagerService> PowerManagerService::sSingleton;
/* static */ already_AddRefed<nsIPowerManagerService>
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
@ -68,6 +126,50 @@ PowerManagerService::PowerOff()
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
} // dom
} // mozilla

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