зеркало из https://github.com/mozilla/pjs.git
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
e64ddd8c4b
|
@ -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.
|
||||
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -166,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);
|
||||
|
@ -711,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);
|
||||
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -737,8 +737,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:
|
||||
|
@ -795,8 +798,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):
|
||||
|
|
|
@ -66,7 +66,10 @@ _JAVA_HARNESS = \
|
|||
|
||||
_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 \
|
||||
|
|
|
@ -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@
|
||||
|
|
36
configure.in
36
configure.in
|
@ -1837,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 ========================================================
|
||||
|
@ -1847,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=''
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -66,10 +66,12 @@ EXTRA_COMPONENTS = \
|
|||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES += Webapps.jsm \
|
||||
DOMRequestHelper.jsm \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
EXTRA_JS_MODULES += DOMRequestHelper.jsm \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIDOMDOMError.idl \
|
||||
nsIDOMDOMRequest.idl \
|
||||
|
|
|
@ -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
|
||||
//*****************************************************************************
|
||||
|
|
|
@ -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"
|
||||
|
@ -1436,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)
|
||||
|
||||
|
@ -4031,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
|
||||
|
|
|
@ -429,6 +429,7 @@ DOMCI_CLASS(GeoPositionError)
|
|||
DOMCI_CLASS(MozBatteryManager)
|
||||
|
||||
DOMCI_CLASS(MozPowerManager)
|
||||
DOMCI_CLASS(MozWakeLock)
|
||||
|
||||
DOMCI_CLASS(MozSmsManager)
|
||||
DOMCI_CLASS(MozSmsMessage)
|
||||
|
|
|
@ -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]),
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,3 +131,4 @@ interface nsIDOMFontFaceList;
|
|||
|
||||
// Power
|
||||
interface nsIDOMMozPowerManager;
|
||||
interface nsIDOMMozWakeLock;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -37,8 +37,13 @@
|
|||
#ifndef mozilla_dom_power_PowerManagerService_h
|
||||
#define mozilla_dom_power_PowerManagerService_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "mozilla/Observer.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -46,12 +51,29 @@ namespace power {
|
|||
|
||||
class PowerManagerService
|
||||
: public nsIPowerManagerService
|
||||
, public WakeLockObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPOWERMANAGERSERVICE
|
||||
|
||||
static already_AddRefed<nsIPowerManagerService> GetInstance();
|
||||
|
||||
void Init();
|
||||
|
||||
// Implement WakeLockObserver
|
||||
void Notify(const hal::WakeLockInformation& aWakeLockInfo);
|
||||
|
||||
private:
|
||||
|
||||
~PowerManagerService();
|
||||
|
||||
void ComputeWakeLockState(const hal::WakeLockInformation& aWakeLockInfo,
|
||||
nsAString &aState);
|
||||
|
||||
static nsRefPtr<PowerManagerService> sSingleton;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mWakeLockListeners;
|
||||
};
|
||||
|
||||
} // namespace power
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
#ifndef mozilla_dom_power_Types_h
|
||||
#define mozilla_dom_power_Types_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
class WakeLockInformation;
|
||||
} // namespace hal
|
||||
|
||||
template <class T>
|
||||
class Observer;
|
||||
|
||||
typedef Observer<hal::WakeLockInformation> WakeLockObserver;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_power_Types_h
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/HalWakeLock.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "PowerManager.h"
|
||||
#include "WakeLock.h"
|
||||
|
||||
DOMCI_DATA(MozWakeLock, mozilla::dom::power::WakeLock)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace power {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(WakeLock)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMozWakeLock)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozWakeLock)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozWakeLock)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(WakeLock)
|
||||
NS_IMPL_RELEASE(WakeLock)
|
||||
|
||||
WakeLock::WakeLock()
|
||||
: mLocked(false)
|
||||
, mHidden(true)
|
||||
{
|
||||
}
|
||||
|
||||
WakeLock::~WakeLock()
|
||||
{
|
||||
DoUnlock();
|
||||
DetachEventListener();
|
||||
}
|
||||
|
||||
nsresult
|
||||
WakeLock::Init(const nsAString &aTopic, nsIDOMWindow *aWindow)
|
||||
{
|
||||
mTopic.Assign(aTopic);
|
||||
|
||||
mWindow = do_GetWeakReference(aWindow);
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
|
||||
/**
|
||||
* Null windows are allowed. A wake lock without associated window
|
||||
* is always considered invisible.
|
||||
*/
|
||||
if (window) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
|
||||
NS_ENSURE_STATE(domDoc);
|
||||
domDoc->GetMozHidden(&mHidden);
|
||||
}
|
||||
|
||||
AttachEventListener();
|
||||
DoLock();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WakeLock::DoLock()
|
||||
{
|
||||
if (!mLocked) {
|
||||
// Change the flag immediately to prevent recursive reentering
|
||||
mLocked = true;
|
||||
hal::ModifyWakeLock(mTopic,
|
||||
hal::WAKE_LOCK_ADD_ONE,
|
||||
mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_NO_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WakeLock::DoUnlock()
|
||||
{
|
||||
if (mLocked) {
|
||||
// Change the flag immediately to prevent recursive reentering
|
||||
mLocked = false;
|
||||
hal::ModifyWakeLock(mTopic,
|
||||
hal::WAKE_LOCK_REMOVE_ONE,
|
||||
mHidden ? hal::WAKE_LOCK_REMOVE_ONE : hal::WAKE_LOCK_NO_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WakeLock::AttachEventListener()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
|
||||
if (window) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
|
||||
if (domDoc) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDoc);
|
||||
target->AddSystemEventListener(NS_LITERAL_STRING("mozvisibilitychange"),
|
||||
this,
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
target = do_QueryInterface(window);
|
||||
target->AddSystemEventListener(NS_LITERAL_STRING("pagehide"),
|
||||
this,
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
target->AddSystemEventListener(NS_LITERAL_STRING("pageshow"),
|
||||
this,
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WakeLock::DetachEventListener()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
|
||||
if (window) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = window->GetExtantDocument();
|
||||
if (domDoc) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDoc);
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozvisibilitychange"),
|
||||
this,
|
||||
/* useCapture = */ true);
|
||||
target = do_QueryInterface(window);
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("pagehide"),
|
||||
this,
|
||||
/* useCapture = */ true);
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("pageshow"),
|
||||
this,
|
||||
/* useCapture = */ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WakeLock::Unlock()
|
||||
{
|
||||
/*
|
||||
* We throw NS_ERROR_DOM_INVALID_STATE_ERR on double unlock.
|
||||
*/
|
||||
if (!mLocked) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
DoUnlock();
|
||||
DetachEventListener();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WakeLock::GetTopic(nsAString &aTopic)
|
||||
{
|
||||
aTopic.Assign(mTopic);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WakeLock::HandleEvent(nsIDOMEvent *aEvent)
|
||||
{
|
||||
nsAutoString type;
|
||||
aEvent->GetType(type);
|
||||
|
||||
if (type.EqualsLiteral("mozvisibilitychange")) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(target);
|
||||
NS_ENSURE_STATE(domDoc);
|
||||
domDoc->GetMozHidden(&mHidden);
|
||||
|
||||
if (mLocked) {
|
||||
hal::ModifyWakeLock(mTopic,
|
||||
hal::WAKE_LOCK_NO_CHANGE,
|
||||
mHidden ? hal::WAKE_LOCK_ADD_ONE : hal::WAKE_LOCK_REMOVE_ONE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (type.EqualsLiteral("pagehide")) {
|
||||
DoUnlock();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (type.EqualsLiteral("pageshow")) {
|
||||
DoLock();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // power
|
||||
} // dom
|
||||
} // mozilla
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_power_WakeLock_h
|
||||
#define mozilla_dom_power_WakeLock_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMWakeLock.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace power {
|
||||
|
||||
class WakeLock
|
||||
: public nsIDOMMozWakeLock
|
||||
, public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMMOZWAKELOCK
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
WakeLock();
|
||||
virtual ~WakeLock();
|
||||
|
||||
nsresult Init(const nsAString &aTopic, nsIDOMWindow *aWindow);
|
||||
|
||||
private:
|
||||
void DoUnlock();
|
||||
void DoLock();
|
||||
void AttachEventListener();
|
||||
void DetachEventListener();
|
||||
|
||||
bool mLocked;
|
||||
bool mHidden;
|
||||
nsString mTopic;
|
||||
|
||||
// window that this was created for. Weak reference.
|
||||
nsWeakPtr mWindow;
|
||||
};
|
||||
|
||||
} // namespace power
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_power_WakeLock_h
|
|
@ -37,9 +37,40 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(6ec16abc-2fe8-4ab3-99b0-0f08405be81b)]
|
||||
interface nsIDOMMozWakeLockListener;
|
||||
|
||||
/**
|
||||
* This interface implements navigator.mozPower
|
||||
*/
|
||||
[scriptable, uuid(abf4b2b1-139d-4eff-998d-8f24616910ae)]
|
||||
interface nsIDOMMozPowerManager : nsISupports
|
||||
{
|
||||
void powerOff();
|
||||
void reboot();
|
||||
void powerOff();
|
||||
void reboot();
|
||||
|
||||
/**
|
||||
* The listeners are notified when a resource changes its lock state to:
|
||||
* - unlocked
|
||||
* - locked but not visible
|
||||
* - locked and visible
|
||||
*/
|
||||
void addWakeLockListener(in nsIDOMMozWakeLockListener aListener);
|
||||
void removeWakeLockListener(in nsIDOMMozWakeLockListener aListener);
|
||||
|
||||
/**
|
||||
* Query the wake lock state of the topic.
|
||||
*
|
||||
* Possible states are:
|
||||
*
|
||||
* - "unlocked" - nobody holds the wake lock.
|
||||
*
|
||||
* - "locked-foreground" - at least one window holds the wake lock,
|
||||
* and it is visible.
|
||||
*
|
||||
* - "locked-background" - at least one window holds the wake lock,
|
||||
* but all of them are hidden.
|
||||
*
|
||||
* @param aTopic The resource name related to the wake lock.
|
||||
*/
|
||||
DOMString getWakeLockState(in DOMString aTopic);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(2e61eed1-5983-4562-8f26-fd361ab4a00d)]
|
||||
interface nsIDOMMozWakeLock : nsISupports
|
||||
{
|
||||
readonly attribute DOMString topic;
|
||||
|
||||
/**
|
||||
* Release the wake lock.
|
||||
*
|
||||
* @throw NS_ERROR_DOM_INVALID_STATE_ERR if already unlocked.
|
||||
*/
|
||||
void unlock();
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, function, uuid(4e258af8-cffb-47bc-b16d-e8241243426e)]
|
||||
interface nsIDOMMozWakeLockListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* The callback will be called when a lock topic changes its lock
|
||||
* state.
|
||||
*
|
||||
* Possible states are:
|
||||
*
|
||||
* - "unlocked" - nobody holds the wake lock.
|
||||
*
|
||||
* - "locked-foreground" - at least one window holds the wake lock,
|
||||
* and it is visible.
|
||||
*
|
||||
* - "locked-background" - at least one window holds the wake lock,
|
||||
* but all of them are hidden.
|
||||
*
|
||||
* @param aTopic The resource name related to the wake lock.
|
||||
* @param aState The wake lock state
|
||||
*/
|
||||
void callback(in DOMString aTopic, in DOMString aState);
|
||||
};
|
|
@ -42,9 +42,26 @@
|
|||
#define POWERMANAGERSERVICE_CONTRACTID "@mozilla.org/power/powermanagerservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, builtinclass, uuid(38919539-4641-4f0b-9f11-6b6294a9386f)]
|
||||
interface nsIDOMMozWakeLock;
|
||||
interface nsIDOMMozWakeLockListener;
|
||||
interface nsIDOMWindow;
|
||||
|
||||
/**
|
||||
* For use with non-content code.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(235ca1a1-d0c8-41f3-9b4a-dbaa4437d69c)]
|
||||
interface nsIPowerManagerService : nsISupports
|
||||
{
|
||||
void powerOff();
|
||||
void reboot();
|
||||
void powerOff();
|
||||
void reboot();
|
||||
void addWakeLockListener(in nsIDOMMozWakeLockListener aListener);
|
||||
void removeWakeLockListener(in nsIDOMMozWakeLockListener aListener);
|
||||
DOMString getWakeLockState(in DOMString aTopic);
|
||||
|
||||
/**
|
||||
* Return a wake lock object of aTopic associated with aWindow.
|
||||
* A wake lock without associated window, e.g. used in chrome, is
|
||||
* always considered invisible.
|
||||
*/
|
||||
nsIDOMMozWakeLock newWakeLock(in DOMString aTopic, [optional] in nsIDOMWindow aWindow);
|
||||
};
|
||||
|
|
|
@ -52,8 +52,15 @@ _TEST_FILES = \
|
|||
test_power_basics.html \
|
||||
$(NULL)
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_bug697132.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
||||
#libs:: $(_CHROME_TEST_FILES)
|
||||
# $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
"use strict";
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let kPrefNode = "dom.power.whitelist";
|
||||
let kPageSource1 = "data:text/html,1";
|
||||
let kPageSource2 = "data:text/html,2";
|
||||
|
||||
let gOldPref;
|
||||
let gWin, gWin1, gWin2;
|
||||
let gTab, gTab1, gTab2;
|
||||
let gLock, gLock1, gLock2;
|
||||
let gCurStepIndex = -1;
|
||||
let gSteps = [
|
||||
function basicWakeLock() {
|
||||
gTab = gBrowser.addTab(kPageSource1);
|
||||
gWin = gBrowser.getBrowserForTab(gTab).contentWindow;
|
||||
let browser = gBrowser.getBrowserForTab(gTab);
|
||||
|
||||
browser.addEventListener("load", function onLoad(e) {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
let nav = gWin.navigator;
|
||||
let power = nav.mozPower;
|
||||
gLock = nav.requestWakeLock("test");
|
||||
|
||||
ok(gLock != null,
|
||||
"navigator.requestWakeLock should return a wake lock");
|
||||
is(gLock.topic, "test",
|
||||
"wake lock should remember the locked topic");
|
||||
isnot(power.getWakeLockState("test"), "unlocked",
|
||||
"topic is locked");
|
||||
|
||||
gLock.unlock();
|
||||
|
||||
is(gLock.topic, "test",
|
||||
"wake lock should remember the locked topic even after unlock");
|
||||
is(power.getWakeLockState("test"), "unlocked",
|
||||
"topic is unlocked");
|
||||
|
||||
try {
|
||||
gLock.unlock();
|
||||
ok(false, "Should have thrown an error.");
|
||||
} catch (e) {
|
||||
is(e.code, DOMException.INVALID_STATE_ERR, "double unlock should throw InvalidStateError");
|
||||
}
|
||||
|
||||
gBrowser.removeTab(gTab);
|
||||
|
||||
executeSoon(runNextStep);
|
||||
}, true);
|
||||
},
|
||||
function multiWakeLock() {
|
||||
gTab = gBrowser.addTab(kPageSource1);
|
||||
gWin = gBrowser.getBrowserForTab(gTab).contentWindow;
|
||||
let browser = gBrowser.getBrowserForTab(gTab);
|
||||
|
||||
browser.addEventListener("load", function onLoad(e) {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
let nav = gWin.navigator;
|
||||
let power = nav.mozPower;
|
||||
let count = 0;
|
||||
power.addWakeLockListener(function onWakeLockEvent(topic, state) {
|
||||
is(topic, "test", "gLock topic is test");
|
||||
ok(state == "unlocked" ||
|
||||
state == "locked-foreground" ||
|
||||
state == "locked-background",
|
||||
"wake lock should be either locked or unlocked");
|
||||
count++;
|
||||
if (state == "locked-foreground" ||
|
||||
state == "locked-background") {
|
||||
is(count, 1,
|
||||
"wake lock should be locked and the listener should only fire once");
|
||||
}
|
||||
if (state == "unlocked") {
|
||||
is(count, 2,
|
||||
"wake lock should be unlocked and the listener should only fire once");
|
||||
|
||||
ok(power.getWakeLockState("test") == "unlocked",
|
||||
"topic is unlocked");
|
||||
power.removeWakeLockListener(onWakeLockEvent);
|
||||
gBrowser.removeTab(gTab);
|
||||
executeSoon(runNextStep);
|
||||
}
|
||||
});
|
||||
|
||||
gLock1 = nav.requestWakeLock("test");
|
||||
isnot(power.getWakeLockState("test"), "unlocked",
|
||||
"topic is locked");
|
||||
|
||||
gLock2 = nav.requestWakeLock("test");
|
||||
isnot(power.getWakeLockState("test"), "unlocked",
|
||||
"topic is locked");
|
||||
|
||||
gLock1.unlock();
|
||||
isnot(power.getWakeLockState("test"), "unlocked",
|
||||
"topic is locked");
|
||||
|
||||
gLock2.unlock();
|
||||
}, true);
|
||||
},
|
||||
function crossTabWakeLock1() {
|
||||
gTab1 = gBrowser.addTab(kPageSource1);
|
||||
gWin1 = gBrowser.getBrowserForTab(gTab1).contentWindow;
|
||||
gTab2 = gBrowser.addTab(kPageSource1);
|
||||
gWin2 = gBrowser.getBrowserForTab(gTab2).contentWindow;
|
||||
|
||||
gBrowser.selectedTab = gTab1;
|
||||
let browser = gBrowser.getBrowserForTab(gTab2);
|
||||
|
||||
browser.addEventListener("load", function onLoad(e) {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
gLock2 = gWin2.navigator.requestWakeLock("test");
|
||||
is(gWin2.document.mozHidden, true,
|
||||
"window is background")
|
||||
is(gWin2.navigator.mozPower.getWakeLockState("test"), "locked-background",
|
||||
"wake lock is background");
|
||||
let doc2 = gWin2.document;
|
||||
doc2.addEventListener("mozvisibilitychange", function onVisibilityChange(e) {
|
||||
if (!doc2.mozHidden) {
|
||||
doc2.removeEventListener("mozvisibilitychange", onVisibilityChange);
|
||||
executeSoon(runNextStep);
|
||||
}
|
||||
});
|
||||
gBrowser.selectedTab = gTab2;
|
||||
}, true);
|
||||
},
|
||||
function crossTabWakeLock2() {
|
||||
is(gWin2.document.mozHidden, false,
|
||||
"window is foreground")
|
||||
is(gWin2.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
|
||||
"wake lock is foreground");
|
||||
gWin2.addEventListener("pagehide", function onPageHide(e) {
|
||||
gWin2.removeEventListener("pagehide", onPageHide, true);
|
||||
executeSoon(runNextStep);
|
||||
}, true);
|
||||
gWin2.addEventListener("pageshow", function onPageShow(e) {
|
||||
gWin2.removeEventListener("pageshow", onPageShow, true);
|
||||
executeSoon(runNextStep);
|
||||
}, true);
|
||||
gWin2.location = kPageSource2;
|
||||
},
|
||||
function crossTabWakeLock3() {
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "unlocked",
|
||||
"wake lock should auto-unlock when page is unloaded");
|
||||
gWin2.back();
|
||||
// runNextStep called in onPageShow
|
||||
},
|
||||
function crossTabWakeLock4() {
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
|
||||
"wake lock should auto-reacquire when page is available again");
|
||||
gBrowser.selectedTab = gTab1;
|
||||
executeSoon(runNextStep);
|
||||
},
|
||||
function crossTabWakeLock5() {
|
||||
// Test again in background tab
|
||||
is(gWin2.document.mozHidden, true,
|
||||
"window is background")
|
||||
is(gWin2.navigator.mozPower.getWakeLockState("test"), "locked-background",
|
||||
"wake lock is background");
|
||||
gWin2.addEventListener("pagehide", function onPageHide(e) {
|
||||
gWin2.removeEventListener("pagehide", onPageHide, true);
|
||||
executeSoon(runNextStep);
|
||||
}, true);
|
||||
gWin2.addEventListener("pageshow", function onPageShow(e) {
|
||||
gWin2.removeEventListener("pageshow", onPageShow, true);
|
||||
executeSoon(runNextStep);
|
||||
}, true);
|
||||
gWin2.location = kPageSource2;
|
||||
},
|
||||
function crossTabWakeLock6() {
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "unlocked",
|
||||
"wake lock should auto-unlock when page is unloaded");
|
||||
gWin2.back();
|
||||
// runNextStep called in onPageShow
|
||||
},
|
||||
function crossTabWakeLock7() {
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-background",
|
||||
"wake lock should auto-reacquire when page is available again");
|
||||
gLock2.unlock();
|
||||
gBrowser.selectedTab = gTab2;
|
||||
executeSoon(runNextStep);
|
||||
},
|
||||
function crossTabWakeLock8() {
|
||||
is(gWin1.document.mozHidden, true,
|
||||
"gWin1 is background");
|
||||
is(gWin2.document.mozHidden, false,
|
||||
"gWin2 is foreground");
|
||||
|
||||
gLock1 = gWin1.navigator.requestWakeLock("test");
|
||||
gLock2 = gWin2.navigator.requestWakeLock("test");
|
||||
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
|
||||
"topic is locked-foreground when one page is foreground and one is background");
|
||||
|
||||
gLock2.unlock();
|
||||
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-background",
|
||||
"topic is locked-background when all locks are background");
|
||||
|
||||
gLock2 = gWin2.navigator.requestWakeLock("test");
|
||||
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
|
||||
"topic is locked-foreground when one page is foreground and one is background");
|
||||
|
||||
gLock1.unlock();
|
||||
|
||||
is(gWin1.navigator.mozPower.getWakeLockState("test"), "locked-foreground",
|
||||
"topic is locked-foreground");
|
||||
|
||||
gBrowser.removeTab(gTab1);
|
||||
gBrowser.removeTab(gTab2);
|
||||
executeSoon(runNextStep);
|
||||
},
|
||||
];
|
||||
|
||||
function runNextStep() {
|
||||
gCurStepIndex++;
|
||||
if (gCurStepIndex < gSteps.length) {
|
||||
gSteps[gCurStepIndex]();
|
||||
} else {
|
||||
Services.prefs.setCharPref(kPrefNode, gOldPref);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
try {
|
||||
gOldPref = Services.prefs.getCharPref(kPrefNode);
|
||||
} catch (e) {
|
||||
gOldPref = "";
|
||||
}
|
||||
// data url inherits its parent's principal, which is |about:| here.
|
||||
Services.prefs.setCharPref(kPrefNode, "about:");
|
||||
runNextStep();
|
||||
}
|
|
@ -85,9 +85,14 @@ using namespace mozilla::xpconnect::memory;
|
|||
// consistency.
|
||||
#define WORKER_STACK_SIZE 256 * sizeof(size_t) * 1024
|
||||
|
||||
// The stack limit the JS engine will check. Half the size of the
|
||||
// actual C stack, to be safe.
|
||||
// The stack limit the JS engine will check.
|
||||
#ifdef MOZ_ASAN
|
||||
// For ASan, we need more stack space, so we use all that is available
|
||||
#define WORKER_CONTEXT_NATIVE_STACK_LIMIT WORKER_STACK_SIZE
|
||||
#else
|
||||
// Half the size of the actual C stack, to be safe.
|
||||
#define WORKER_CONTEXT_NATIVE_STACK_LIMIT 128 * sizeof(size_t) * 1024
|
||||
#endif
|
||||
|
||||
// The maximum number of threads to use for workers, overridable via pref.
|
||||
#define MAX_WORKERS_PER_DOMAIN 10
|
||||
|
|
|
@ -1820,6 +1820,9 @@ public class GeckoAppShell
|
|||
return false;
|
||||
}
|
||||
|
||||
public static void emitGeckoAccessibilityEvent (int eventType, String[] textList, String description, boolean enabled, boolean checked, boolean password) {
|
||||
}
|
||||
|
||||
public static double[] getCurrentNetworkInformation() {
|
||||
return GeckoNetworkManager.getInstance().getCurrentInformation();
|
||||
}
|
||||
|
|
|
@ -9443,125 +9443,127 @@
|
|||
> proprietorship/MS
|
||||
39039a44848
|
||||
> provender/M
|
||||
40036a45846
|
||||
39564a45374
|
||||
> quinoa
|
||||
40036a45847
|
||||
> recency
|
||||
40141a45952
|
||||
40141a45953
|
||||
> recuse/DGS
|
||||
40208a46020
|
||||
40208a46021
|
||||
> refactor/SMDG
|
||||
40244d46055
|
||||
40244d46056
|
||||
< reflexion/SM
|
||||
40829c46640
|
||||
40829c46641
|
||||
< reverie/M
|
||||
---
|
||||
> reverie/MS
|
||||
41415a47227
|
||||
41415a47228
|
||||
> sabre/MS
|
||||
41914c47726
|
||||
41914c47727
|
||||
< schnaps's
|
||||
---
|
||||
> schnaps/M
|
||||
41949c47761
|
||||
41949c47762
|
||||
< schrod's
|
||||
---
|
||||
> schrod/SM
|
||||
41998a47811
|
||||
41998a47812
|
||||
> scot-free
|
||||
42883,42885c48696
|
||||
42883,42885c48697
|
||||
< shit's
|
||||
< shit/S!
|
||||
< shite/S!
|
||||
---
|
||||
> shit/MS!
|
||||
42887,42888c48698,48699
|
||||
42887,42888c48699,48700
|
||||
< shithead/S!
|
||||
< shitload/!
|
||||
---
|
||||
> shithead/MS!
|
||||
> shitload/MS!
|
||||
42891c48702
|
||||
42891c48703
|
||||
< shitty/RT!
|
||||
---
|
||||
> shitty/TR!
|
||||
42976a48788
|
||||
42976a48789
|
||||
> should've
|
||||
43008c48820
|
||||
43008c48821
|
||||
< showtime
|
||||
---
|
||||
> showtime/MS
|
||||
43724,43726c49536
|
||||
43724,43726c49537
|
||||
< smoulder's
|
||||
< smouldered
|
||||
< smoulders
|
||||
---
|
||||
> smoulder/GSMD
|
||||
44062c49872
|
||||
44062c49873
|
||||
< sonofabitch
|
||||
---
|
||||
> sonofabitch/!
|
||||
44371a50182
|
||||
44371a50183
|
||||
> spick/S!
|
||||
44383c50194
|
||||
44383c50195
|
||||
< spik/S
|
||||
---
|
||||
> spik/S!
|
||||
46106a51918
|
||||
46106a51919
|
||||
> syllabi
|
||||
46160c51972
|
||||
46160c51973
|
||||
< synch/GMD
|
||||
---
|
||||
> synch/GMDS
|
||||
46167d51978
|
||||
46167d51979
|
||||
< synchs
|
||||
46203,46204c52014,52015
|
||||
46203,46204c52015,52016
|
||||
< sysadmin/S
|
||||
< sysop/S
|
||||
---
|
||||
> sysadmin/MS
|
||||
> sysop/MS
|
||||
46752a52564
|
||||
46752a52565
|
||||
> terabit/MS
|
||||
46753a52566,52567
|
||||
46753a52567,52568
|
||||
> terahertz/M
|
||||
> terapixel/MS
|
||||
46817a52632
|
||||
46817a52633
|
||||
> testcase/MS
|
||||
46831a52647
|
||||
46831a52648
|
||||
> testsuite/MS
|
||||
46925a52742
|
||||
46925a52743
|
||||
> theremin/MS
|
||||
47755a53573
|
||||
47755a53574
|
||||
> transfect/DSMG
|
||||
47774a53593,53594
|
||||
47774a53594,53595
|
||||
> transgenderism
|
||||
> transgene/MS
|
||||
47951c53771
|
||||
47951c53772
|
||||
< triage/M
|
||||
---
|
||||
> triage/MG
|
||||
48869a54690
|
||||
48869a54691
|
||||
> unlikeable
|
||||
49211c55032
|
||||
49211c55033
|
||||
< vagina/M
|
||||
---
|
||||
> vagina/MS
|
||||
49368,49369c55189
|
||||
49368,49369c55190
|
||||
< velour's
|
||||
< velours's
|
||||
---
|
||||
> velour/MS
|
||||
49478a55299
|
||||
49478a55300
|
||||
> vertices
|
||||
50148a55970
|
||||
50148a55971
|
||||
> weaponize/DSG
|
||||
50260,50261d56081
|
||||
50260,50261d56082
|
||||
< werwolf/M
|
||||
< werwolves
|
||||
50728c56548
|
||||
50728c56549
|
||||
< women
|
||||
---
|
||||
> women/M
|
||||
50794c56614
|
||||
50794c56615
|
||||
< wop/S!
|
||||
---
|
||||
> wop/MS!
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
57436
|
||||
57437
|
||||
0/nm
|
||||
0th/pt
|
||||
1/n1
|
||||
|
@ -45698,6 +45698,7 @@ quince/SM
|
|||
quincentenary
|
||||
quine/S
|
||||
quinine/M
|
||||
quinoa
|
||||
quinquennial
|
||||
quinsy/M
|
||||
quint/SM
|
||||
|
|
88
hal/Hal.cpp
88
hal/Hal.cpp
|
@ -184,19 +184,36 @@ public:
|
|||
if (mObservers->Length() == 0) {
|
||||
DisableNotifications();
|
||||
|
||||
OnNotificationsDisabled();
|
||||
|
||||
delete mObservers;
|
||||
mObservers = 0;
|
||||
|
||||
mHasValidCache = false;
|
||||
}
|
||||
}
|
||||
|
||||
void BroadcastInformation(const InfoType& aInfo) {
|
||||
MOZ_ASSERT(mObservers);
|
||||
mObservers->Broadcast(aInfo);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void EnableNotifications() = 0;
|
||||
virtual void DisableNotifications() = 0;
|
||||
virtual void OnNotificationsDisabled() {}
|
||||
|
||||
private:
|
||||
mozilla::ObserverList<InfoType>* mObservers;
|
||||
};
|
||||
|
||||
template <class InfoType>
|
||||
class CachingObserversManager : public ObserversManager<InfoType>
|
||||
{
|
||||
public:
|
||||
InfoType GetCurrentInformation() {
|
||||
if (mHasValidCache) {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
mHasValidCache = true;
|
||||
GetCurrentInformationInternal(&mInfo);
|
||||
return mInfo;
|
||||
}
|
||||
|
@ -207,22 +224,22 @@ public:
|
|||
}
|
||||
|
||||
void BroadcastCachedInformation() {
|
||||
MOZ_ASSERT(mObservers);
|
||||
mObservers->Broadcast(mInfo);
|
||||
this->BroadcastInformation(mInfo);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void EnableNotifications() = 0;
|
||||
virtual void DisableNotifications() = 0;
|
||||
virtual void GetCurrentInformationInternal(InfoType*) = 0;
|
||||
|
||||
virtual void OnNotificationsDisabled() {
|
||||
mHasValidCache = false;
|
||||
}
|
||||
|
||||
private:
|
||||
mozilla::ObserverList<InfoType>* mObservers;
|
||||
InfoType mInfo;
|
||||
bool mHasValidCache;
|
||||
};
|
||||
|
||||
class BatteryObserversManager : public ObserversManager<BatteryInformation>
|
||||
class BatteryObserversManager : public CachingObserversManager<BatteryInformation>
|
||||
{
|
||||
protected:
|
||||
void EnableNotifications() {
|
||||
|
@ -240,7 +257,7 @@ protected:
|
|||
|
||||
static BatteryObserversManager sBatteryObservers;
|
||||
|
||||
class NetworkObserversManager : public ObserversManager<NetworkInformation>
|
||||
class NetworkObserversManager : public CachingObserversManager<NetworkInformation>
|
||||
{
|
||||
protected:
|
||||
void EnableNotifications() {
|
||||
|
@ -258,6 +275,20 @@ protected:
|
|||
|
||||
static NetworkObserversManager sNetworkObservers;
|
||||
|
||||
class WakeLockObserversManager : public ObserversManager<WakeLockInformation>
|
||||
{
|
||||
protected:
|
||||
void EnableNotifications() {
|
||||
PROXY_IF_SANDBOXED(EnableWakeLockNotifications());
|
||||
}
|
||||
|
||||
void DisableNotifications() {
|
||||
PROXY_IF_SANDBOXED(DisableWakeLockNotifications());
|
||||
}
|
||||
};
|
||||
|
||||
static WakeLockObserversManager sWakeLockObservers;
|
||||
|
||||
void
|
||||
RegisterBatteryObserver(BatteryObserver* aObserver)
|
||||
{
|
||||
|
@ -435,5 +466,42 @@ void PowerOff()
|
|||
PROXY_IF_SANDBOXED(PowerOff());
|
||||
}
|
||||
|
||||
void
|
||||
RegisterWakeLockObserver(WakeLockObserver* aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
sWakeLockObservers.AddObserver(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
UnregisterWakeLockObserver(WakeLockObserver* aObserver)
|
||||
{
|
||||
AssertMainThread();
|
||||
sWakeLockObservers.RemoveObserver(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
ModifyWakeLock(const nsAString &aTopic,
|
||||
hal::WakeLockControl aLockAdjust,
|
||||
hal::WakeLockControl aHiddenAdjust)
|
||||
{
|
||||
AssertMainThread();
|
||||
PROXY_IF_SANDBOXED(ModifyWakeLock(aTopic, aLockAdjust, aHiddenAdjust));
|
||||
}
|
||||
|
||||
void
|
||||
GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
|
||||
{
|
||||
AssertMainThread();
|
||||
PROXY_IF_SANDBOXED(GetWakeLockInfo(aTopic, aWakeLockInfo));
|
||||
}
|
||||
|
||||
void
|
||||
NotifyWakeLockChange(const WakeLockInformation& aInfo)
|
||||
{
|
||||
AssertMainThread();
|
||||
sWakeLockObservers.BroadcastInformation(aInfo);
|
||||
}
|
||||
|
||||
} // namespace hal
|
||||
} // namespace mozilla
|
||||
|
|
50
hal/Hal.h
50
hal/Hal.h
|
@ -14,6 +14,7 @@
|
|||
#include "prlog.h"
|
||||
#include "mozilla/dom/battery/Types.h"
|
||||
#include "mozilla/dom/network/Types.h"
|
||||
#include "mozilla/dom/power/Types.h"
|
||||
#include "mozilla/hal_sandbox/PHal.h"
|
||||
|
||||
/*
|
||||
|
@ -240,6 +241,55 @@ void Reboot();
|
|||
*/
|
||||
void PowerOff();
|
||||
|
||||
/**
|
||||
* Enable wake lock notifications from the backend.
|
||||
*
|
||||
* This method is only used by WakeLockObserversManager.
|
||||
*/
|
||||
void EnableWakeLockNotifications();
|
||||
|
||||
/**
|
||||
* Disable wake lock notifications from the backend.
|
||||
*
|
||||
* This method is only used by WakeLockObserversManager.
|
||||
*/
|
||||
void DisableWakeLockNotifications();
|
||||
|
||||
/**
|
||||
* Inform the wake lock backend there is a new wake lock observer.
|
||||
* @param aWakeLockObserver The observer that should be added.
|
||||
*/
|
||||
void RegisterWakeLockObserver(WakeLockObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Inform the wake lock backend a wake lock observer unregistered.
|
||||
* @param aWakeLockObserver The observer that should be removed.
|
||||
*/
|
||||
void UnregisterWakeLockObserver(WakeLockObserver* aObserver);
|
||||
|
||||
/**
|
||||
* Adjust the internal wake lock counts.
|
||||
* @param aTopic lock topic
|
||||
* @param aLockAdjust to increase or decrease active locks
|
||||
* @param aHiddenAdjust to increase or decrease hidden locks
|
||||
*/
|
||||
void ModifyWakeLock(const nsAString &aTopic,
|
||||
hal::WakeLockControl aLockAdjust,
|
||||
hal::WakeLockControl aHiddenAdjust);
|
||||
|
||||
/**
|
||||
* Query the wake lock numbers of aTopic.
|
||||
* @param aTopic lock topic
|
||||
* @param aWakeLockInfo wake lock numbers
|
||||
*/
|
||||
void GetWakeLockInfo(const nsAString &aTopic, hal::WakeLockInformation *aWakeLockInfo);
|
||||
|
||||
/**
|
||||
* Notify of a change in the wake lock state.
|
||||
* @param aWakeLockInfo The new wake lock information.
|
||||
*/
|
||||
void NotifyWakeLockChange(const hal::WakeLockInformation& aWakeLockInfo);
|
||||
|
||||
} // namespace MOZ_HAL_NAMESPACE
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -36,9 +36,25 @@ enum FlashMode {
|
|||
eHalLightFlash_Timed = 1, // timed flashing. Use flashOnMS and flashOffMS for timing
|
||||
eHalLightFlash_Hardware = 2 // hardware assisted flashing
|
||||
};
|
||||
|
||||
} // namespace hal
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
|
||||
/**
|
||||
* Used by ModifyWakeLock
|
||||
*/
|
||||
enum WakeLockControl {
|
||||
WAKE_LOCK_REMOVE_ONE = -1,
|
||||
WAKE_LOCK_NO_CHANGE = 0,
|
||||
WAKE_LOCK_ADD_ONE = 1,
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
/**
|
||||
|
@ -71,6 +87,16 @@ struct ParamTraits<mozilla::hal::FlashMode>
|
|||
mozilla::hal::eHalLightFlash_Hardware>
|
||||
{};
|
||||
|
||||
/**
|
||||
* WakeLockControl serializer.
|
||||
*/
|
||||
template <>
|
||||
struct ParamTraits<mozilla::hal::WakeLockControl>
|
||||
: public EnumSerializer<mozilla::hal::WakeLockControl,
|
||||
mozilla::hal::WAKE_LOCK_REMOVE_ONE,
|
||||
mozilla::hal::WAKE_LOCK_ADD_ONE>
|
||||
{};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla_hal_Types_h
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/HalWakeLock.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
using namespace mozilla::hal;
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
|
||||
WakeLockState
|
||||
ComputeWakeLockState(int aNumLocks, int aNumHidden)
|
||||
{
|
||||
if (aNumLocks == 0) {
|
||||
return WAKE_LOCK_STATE_UNLOCKED;
|
||||
} else if (aNumLocks == aNumHidden) {
|
||||
return WAKE_LOCK_STATE_HIDDEN;
|
||||
} else {
|
||||
return WAKE_LOCK_STATE_VISIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
} // hal
|
||||
} // mozilla
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
|
||||
namespace {
|
||||
struct LockCount {
|
||||
PRUint32 numLocks;
|
||||
PRUint32 numHidden;
|
||||
};
|
||||
}
|
||||
|
||||
static int sActiveChildren = 0;
|
||||
static nsAutoPtr<nsDataHashtable<nsStringHashKey, LockCount> > sLockTable;
|
||||
static bool sInitialized = false;
|
||||
|
||||
static void
|
||||
Init()
|
||||
{
|
||||
sLockTable = new nsDataHashtable<nsStringHashKey, LockCount>();
|
||||
sLockTable->Init();
|
||||
ClearOnShutdown(&sLockTable);
|
||||
sInitialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
EnableWakeLockNotifications()
|
||||
{
|
||||
sActiveChildren++;
|
||||
}
|
||||
|
||||
void
|
||||
DisableWakeLockNotifications()
|
||||
{
|
||||
sActiveChildren--;
|
||||
}
|
||||
|
||||
void
|
||||
ModifyWakeLock(const nsAString &aTopic,
|
||||
hal::WakeLockControl aLockAdjust,
|
||||
hal::WakeLockControl aHiddenAdjust)
|
||||
{
|
||||
if (!sInitialized) {
|
||||
Init();
|
||||
}
|
||||
|
||||
LockCount count;
|
||||
count.numLocks = 0;
|
||||
count.numHidden = 0;
|
||||
sLockTable->Get(aTopic, &count);
|
||||
MOZ_ASSERT(count.numLocks >= count.numHidden);
|
||||
MOZ_ASSERT(aLockAdjust >= 0 || count.numLocks > 0);
|
||||
MOZ_ASSERT(aHiddenAdjust >= 0 || count.numHidden > 0);
|
||||
|
||||
WakeLockState oldState = ComputeWakeLockState(count.numLocks, count.numHidden);
|
||||
|
||||
count.numLocks += aLockAdjust;
|
||||
count.numHidden += aHiddenAdjust;
|
||||
MOZ_ASSERT(count.numLocks >= count.numHidden);
|
||||
|
||||
if (count.numLocks) {
|
||||
sLockTable->Put(aTopic, count);
|
||||
} else {
|
||||
sLockTable->Remove(aTopic);
|
||||
}
|
||||
|
||||
WakeLockState newState = ComputeWakeLockState(count.numLocks, count.numHidden);
|
||||
|
||||
if (sActiveChildren && oldState != newState) {
|
||||
WakeLockInformation info;
|
||||
info.numLocks() = count.numLocks;
|
||||
info.numHidden() = count.numHidden;
|
||||
info.topic() = aTopic;
|
||||
NotifyWakeLockChange(info);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
|
||||
{
|
||||
if (!sInitialized) {
|
||||
Init();
|
||||
}
|
||||
|
||||
LockCount count;
|
||||
count.numLocks = 0;
|
||||
count.numHidden = 0;
|
||||
sLockTable->Get(aTopic, &count);
|
||||
|
||||
aWakeLockInfo->numLocks() = count.numLocks;
|
||||
aWakeLockInfo->numHidden() = count.numHidden;
|
||||
aWakeLockInfo->topic() = aTopic;
|
||||
}
|
||||
|
||||
} // hal_impl
|
||||
} // mozilla
|
|
@ -0,0 +1,26 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef __HAL_WAKELOCK_H_
|
||||
#define __HAL_WAKELOCK_H_
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
|
||||
enum WakeLockState {
|
||||
WAKE_LOCK_STATE_UNLOCKED,
|
||||
WAKE_LOCK_STATE_HIDDEN,
|
||||
WAKE_LOCK_STATE_VISIBLE
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the wake lock state according to the numbers.
|
||||
*/
|
||||
WakeLockState ComputeWakeLockState(int aNumLocks, int aNumHidden);
|
||||
|
||||
} // hal
|
||||
} // mozilla
|
||||
|
||||
#endif /* __HAL_WAKELOCK_H_ */
|
|
@ -63,12 +63,14 @@ EXPORTS_mozilla = \
|
|||
HalSandbox.h \
|
||||
HalSensor.h \
|
||||
HalTypes.h \
|
||||
HalWakeLock.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
Hal.cpp \
|
||||
SandboxHal.cpp \
|
||||
WindowIdentifier.cpp \
|
||||
HalWakeLock.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
@ -113,4 +115,4 @@ include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
|
||||
CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) -DHAVE_PTHREADS
|
||||
CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
|
||||
|
|
|
@ -11,10 +11,13 @@
|
|||
#include "hardware/sensors.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "SensorDevice.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using namespace mozilla::hal;
|
||||
using namespace android;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static SensorType
|
||||
HardwareSensorToHalSensor(int type)
|
||||
{
|
||||
|
@ -63,19 +66,19 @@ SensorseventToSensorData(const sensors_event_t& data, SensorData* aSensorData)
|
|||
static void
|
||||
onSensorChanged(const sensors_event_t& data, SensorData* aSensorData)
|
||||
{
|
||||
mozilla::DebugOnly<bool> convertedData = SensorseventToSensorData(data, aSensorData);
|
||||
DebugOnly<bool> convertedData = SensorseventToSensorData(data, aSensorData);
|
||||
MOZ_ASSERT(convertedData);
|
||||
NotifySensorChange(*aSensorData);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
|
||||
static pthread_t sThread;
|
||||
static bool sInitialized = false;
|
||||
static bool sContinue = false;
|
||||
static int sActivatedSensors = 0;
|
||||
static bool sInitialized;
|
||||
static bool sContinue;
|
||||
static int sActivatedSensors;
|
||||
static SensorData sSensordata[NUM_SENSOR_TYPE];
|
||||
static nsCOMPtr<nsIThread> sSwitchThread;
|
||||
|
||||
static void*
|
||||
UpdateSensorData(void* /*unused*/)
|
||||
|
@ -100,9 +103,10 @@ UpdateSensorData(void* /*unused*/)
|
|||
}
|
||||
|
||||
static void
|
||||
InitialResources()
|
||||
InitializeResources()
|
||||
{
|
||||
pthread_create(&sThread, NULL, &UpdateSensorData, NULL);
|
||||
NS_NewThread(getter_AddRefs(sSwitchThread));
|
||||
sInitialized = true;
|
||||
sContinue = true;
|
||||
}
|
||||
|
@ -112,9 +116,30 @@ ReleaseResources()
|
|||
{
|
||||
sContinue = false;
|
||||
pthread_join(sThread, NULL);
|
||||
sSwitchThread->Shutdown();
|
||||
sInitialized = false;
|
||||
}
|
||||
|
||||
// This class is used as a runnable on the sSwitchThread
|
||||
class SensorInfo {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(SensorInfo)
|
||||
|
||||
SensorInfo(bool aActivate, sensor_t aSensor, pthread_t aThreadId) :
|
||||
activate(aActivate), sensor(aSensor), threadId(aThreadId) { }
|
||||
|
||||
void Switch() {
|
||||
SensorDevice& device = SensorDevice::getInstance();
|
||||
device.activate((void*)threadId, sensor.handle, activate);
|
||||
}
|
||||
|
||||
protected:
|
||||
SensorInfo() { };
|
||||
bool activate;
|
||||
sensor_t sensor;
|
||||
pthread_t threadId;
|
||||
};
|
||||
|
||||
static void
|
||||
SensorSwitch(SensorType aSensor, bool activate)
|
||||
{
|
||||
|
@ -122,10 +147,12 @@ SensorSwitch(SensorType aSensor, bool activate)
|
|||
const sensor_t* sensors = NULL;
|
||||
SensorDevice& device = SensorDevice::getInstance();
|
||||
size_t size = device.getSensorList(&sensors);
|
||||
|
||||
for (size_t i=0; i<size; i++) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (sensors[i].type == type) {
|
||||
device.activate((void*)pthread_self(), sensors[i].handle, activate);
|
||||
// Post an event to the activation thread
|
||||
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(new SensorInfo(activate, sensors[i], pthread_self()),
|
||||
&SensorInfo::Switch);
|
||||
sSwitchThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +162,7 @@ void
|
|||
EnableSensorNotifications(SensorType aSensor)
|
||||
{
|
||||
if (!sInitialized) {
|
||||
InitialResources();
|
||||
InitializeResources();
|
||||
}
|
||||
|
||||
SensorSwitch(aSensor, true);
|
||||
|
|
|
@ -48,6 +48,7 @@ using mozilla::hal::FlashMode;
|
|||
using mozilla::hal::LightType;
|
||||
using mozilla::hal::LightMode;
|
||||
using mozilla::hal::SensorType;
|
||||
using mozilla::hal::WakeLockControl;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -81,6 +82,14 @@ namespace hal {
|
|||
};
|
||||
}
|
||||
|
||||
namespace hal {
|
||||
struct WakeLockInformation {
|
||||
uint32_t numLocks;
|
||||
uint32_t numHidden;
|
||||
nsString topic;
|
||||
};
|
||||
}
|
||||
|
||||
namespace hal_sandbox {
|
||||
|
||||
sync protocol PHal {
|
||||
|
@ -89,6 +98,7 @@ sync protocol PHal {
|
|||
child:
|
||||
NotifyBatteryChange(BatteryInformation aBatteryInfo);
|
||||
NotifyNetworkChange(NetworkInformation aNetworkInfo);
|
||||
NotifyWakeLockChange(WakeLockInformation aWakeLockInfo);
|
||||
|
||||
parent:
|
||||
Vibrate(uint32[] pattern, uint64[] id, PBrowser browser);
|
||||
|
@ -121,6 +131,12 @@ parent:
|
|||
Reboot();
|
||||
PowerOff();
|
||||
|
||||
ModifyWakeLock(nsString aTopic, WakeLockControl aLockAdjust, WakeLockControl aHiddenAdjust);
|
||||
EnableWakeLockNotifications();
|
||||
DisableWakeLockNotifications();
|
||||
sync GetWakeLockInfo(nsString aTopic)
|
||||
returns (WakeLockInformation aWakeLockInfo);
|
||||
|
||||
child:
|
||||
NotifySensorChange(SensorData aSensorData);
|
||||
|
||||
|
|
|
@ -169,10 +169,35 @@ DisableSensorNotifications(SensorType aSensor) {
|
|||
Hal()->SendDisableSensorNotifications(aSensor);
|
||||
}
|
||||
|
||||
void
|
||||
EnableWakeLockNotifications()
|
||||
{
|
||||
Hal()->SendEnableWakeLockNotifications();
|
||||
}
|
||||
|
||||
void
|
||||
DisableWakeLockNotifications()
|
||||
{
|
||||
Hal()->SendDisableWakeLockNotifications();
|
||||
}
|
||||
|
||||
void
|
||||
ModifyWakeLock(const nsAString &aTopic, WakeLockControl aLockAdjust, WakeLockControl aHiddenAdjust)
|
||||
{
|
||||
Hal()->SendModifyWakeLock(nsString(aTopic), aLockAdjust, aHiddenAdjust);
|
||||
}
|
||||
|
||||
void
|
||||
GetWakeLockInfo(const nsAString &aTopic, WakeLockInformation *aWakeLockInfo)
|
||||
{
|
||||
Hal()->SendGetWakeLockInfo(nsString(aTopic), aWakeLockInfo);
|
||||
}
|
||||
|
||||
class HalParent : public PHalParent
|
||||
, public BatteryObserver
|
||||
, public NetworkObserver
|
||||
, public ISensorObserver
|
||||
, public WakeLockObserver
|
||||
{
|
||||
public:
|
||||
NS_OVERRIDE virtual bool
|
||||
|
@ -343,6 +368,41 @@ public:
|
|||
void Notify(const SensorData& aSensorData) {
|
||||
unused << SendNotifySensorChange(aSensorData);
|
||||
}
|
||||
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvModifyWakeLock(const nsString &aTopic,
|
||||
const WakeLockControl &aLockAdjust,
|
||||
const WakeLockControl &aHiddenAdjust)
|
||||
{
|
||||
hal::ModifyWakeLock(aTopic, aLockAdjust, aHiddenAdjust);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvEnableWakeLockNotifications()
|
||||
{
|
||||
hal::RegisterWakeLockObserver(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvDisableWakeLockNotifications()
|
||||
{
|
||||
hal::UnregisterWakeLockObserver(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvGetWakeLockInfo(const nsString &aTopic, WakeLockInformation *aWakeLockInfo)
|
||||
{
|
||||
hal::GetWakeLockInfo(aTopic, aWakeLockInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Notify(const WakeLockInformation& aWakeLockInfo)
|
||||
{
|
||||
unused << SendNotifyWakeLockChange(aWakeLockInfo);
|
||||
}
|
||||
};
|
||||
|
||||
class HalChild : public PHalChild {
|
||||
|
@ -361,6 +421,12 @@ public:
|
|||
hal::NotifyNetworkChange(aNetworkInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_OVERRIDE virtual bool
|
||||
RecvNotifyWakeLockChange(const WakeLockInformation& aWakeLockInfo) {
|
||||
hal::NotifyWakeLockChange(aWakeLockInfo);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
|
@ -916,6 +916,52 @@ BooleanHistogram::BooleanHistogram(const std::string& name)
|
|||
: LinearHistogram(name, 1, 2, 3) {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FlagHistogram:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Histogram *
|
||||
FlagHistogram::FactoryGet(const std::string &name, Flags flags)
|
||||
{
|
||||
Histogram *h(nsnull);
|
||||
|
||||
if (!StatisticsRecorder::FindHistogram(name, &h)) {
|
||||
// To avoid racy destruction at shutdown, the following will be leaked.
|
||||
FlagHistogram *fh = new FlagHistogram(name);
|
||||
fh->InitializeBucketRange();
|
||||
fh->SetFlags(flags);
|
||||
size_t zero_index = fh->BucketIndex(0);
|
||||
fh->Histogram::Accumulate(1, 1, zero_index);
|
||||
h = StatisticsRecorder::RegisterOrDeleteDuplicate(fh);
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
FlagHistogram::FlagHistogram(const std::string &name)
|
||||
: BooleanHistogram(name), mSwitched(false) {
|
||||
}
|
||||
|
||||
Histogram::ClassType
|
||||
FlagHistogram::histogram_type() const
|
||||
{
|
||||
return FLAG_HISTOGRAM;
|
||||
}
|
||||
|
||||
void
|
||||
FlagHistogram::Accumulate(Sample value, Count count, size_t index)
|
||||
{
|
||||
if (mSwitched) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSwitched = true;
|
||||
DCHECK_EQ(value, 1);
|
||||
Histogram::Accumulate(value, 1, index);
|
||||
size_t zero_index = BucketIndex(0);
|
||||
Histogram::Accumulate(1, -1, zero_index);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CustomHistogram:
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
@ -276,6 +276,7 @@ class Histogram {
|
|||
HISTOGRAM,
|
||||
LINEAR_HISTOGRAM,
|
||||
BOOLEAN_HISTOGRAM,
|
||||
FLAG_HISTOGRAM,
|
||||
CUSTOM_HISTOGRAM,
|
||||
NOT_VALID_IN_RENDERER
|
||||
};
|
||||
|
@ -642,7 +643,7 @@ class BooleanHistogram : public LinearHistogram {
|
|||
|
||||
virtual void AddBoolean(bool value);
|
||||
|
||||
private:
|
||||
protected:
|
||||
explicit BooleanHistogram(const std::string& name);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BooleanHistogram);
|
||||
|
@ -650,6 +651,25 @@ class BooleanHistogram : public LinearHistogram {
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// FlagHistogram is like boolean histogram, but only allows a single off/on value.
|
||||
class FlagHistogram : public BooleanHistogram
|
||||
{
|
||||
public:
|
||||
static Histogram *FactoryGet(const std::string &name, Flags flags);
|
||||
|
||||
virtual ClassType histogram_type() const;
|
||||
|
||||
virtual void Accumulate(Sample value, Count count, size_t index);
|
||||
|
||||
private:
|
||||
explicit FlagHistogram(const std::string &name);
|
||||
bool mSwitched;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FlagHistogram);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// CustomHistogram is a histogram for a set of custom integers.
|
||||
class CustomHistogram : public Histogram {
|
||||
public:
|
||||
|
|
|
@ -206,17 +206,20 @@ ProcessOrDeferMessage(HWND hwnd,
|
|||
case WM_CAPTURECHANGED:
|
||||
case WM_CHILDACTIVATE:
|
||||
case WM_DESTROY:
|
||||
case WM_DISPLAYCHANGE:
|
||||
case WM_ENABLE:
|
||||
case WM_IME_NOTIFY:
|
||||
case WM_IME_SETCONTEXT:
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_KILLFOCUS:
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_NCDESTROY:
|
||||
case WM_PARENTNOTIFY:
|
||||
case WM_SETFOCUS:
|
||||
case WM_SYSCOMMAND:
|
||||
case WM_DISPLAYCHANGE:
|
||||
case WM_SHOWWINDOW: // Intentional fall-through.
|
||||
case WM_SHOWWINDOW:
|
||||
case WM_VSCROLL: // Intentional fall-through.
|
||||
case WM_XP_THEMECHANGED: {
|
||||
deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
|
||||
break;
|
||||
|
@ -324,7 +327,11 @@ ProcessOrDeferMessage(HWND hwnd,
|
|||
log.AppendLiteral("\")");
|
||||
}
|
||||
|
||||
log.AppendLiteral(", sending it to DefWindowProc instead of the normal "
|
||||
log.AppendLiteral(", wParam = ");
|
||||
log.AppendInt(wParam);
|
||||
log.AppendLiteral(", lParam = ");
|
||||
log.AppendInt(lParam);
|
||||
log.AppendLiteral("; sending it to DefWindowProc instead of the normal "
|
||||
"window procedure.");
|
||||
NS_ERROR(log.get());
|
||||
#endif
|
||||
|
|
|
@ -1767,6 +1767,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 ========================================================
|
||||
|
@ -1775,8 +1802,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=''
|
||||
|
|
|
@ -4086,7 +4086,11 @@ EmitCatch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
/*
|
||||
* Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr12127. See
|
||||
* the comment on EmitSwitch.
|
||||
*/
|
||||
MOZ_NEVER_INLINE static bool
|
||||
EmitTry(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
StmtInfo stmtInfo;
|
||||
|
@ -4446,7 +4450,11 @@ EmitIf(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* JSOP_LEAVEBLOCKEXPR to the beginning of the let and is only needed for
|
||||
* let-expressions.
|
||||
*/
|
||||
static bool
|
||||
/*
|
||||
* Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr12127. See
|
||||
* the comment on EmitSwitch.
|
||||
*/
|
||||
MOZ_NEVER_INLINE static bool
|
||||
EmitLet(JSContext *cx, BytecodeEmitter *bce, ParseNode *pnLet)
|
||||
{
|
||||
JS_ASSERT(pnLet->isArity(PN_BINARY));
|
||||
|
@ -4590,7 +4598,11 @@ EmitXMLProcessingInstruction(JSContext *cx, BytecodeEmitter *bce, XMLProcessingI
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
/*
|
||||
* Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr12127. See
|
||||
* the comment on EmitSwitch.
|
||||
*/
|
||||
MOZ_NEVER_INLINE static bool
|
||||
EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
|
||||
|
@ -5811,7 +5823,11 @@ EmitIncOrDec(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
/*
|
||||
* Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr12127. See
|
||||
* the comment on EmitSwitch.
|
||||
*/
|
||||
MOZ_NEVER_INLINE static bool
|
||||
EmitLabel(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -1213,25 +1213,29 @@ mjit::Compiler::ensureDoubleArguments()
|
|||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::markUndefinedLocals()
|
||||
mjit::Compiler::markUndefinedLocal(uint32_t offset, uint32_t i)
|
||||
{
|
||||
uint32_t depth = ssa.getFrame(a->inlineIndex).depth;
|
||||
uint32_t slot = LocalSlot(script, i);
|
||||
Address local(JSFrameReg, sizeof(StackFrame) + (depth + i) * sizeof(Value));
|
||||
if (!cx->typeInferenceEnabled() || !analysis->trackSlot(slot)) {
|
||||
masm.storeValue(UndefinedValue(), local);
|
||||
} else {
|
||||
Lifetime *lifetime = analysis->liveness(slot).live(offset);
|
||||
if (lifetime)
|
||||
masm.storeValue(UndefinedValue(), local);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::markUndefinedLocals()
|
||||
{
|
||||
/*
|
||||
* Set locals to undefined, as in initCallFrameLatePrologue.
|
||||
* Skip locals which aren't closed and are known to be defined before used,
|
||||
*/
|
||||
for (uint32_t i = 0; i < script->nfixed; i++) {
|
||||
uint32_t slot = LocalSlot(script, i);
|
||||
Address local(JSFrameReg, sizeof(StackFrame) + (depth + i) * sizeof(Value));
|
||||
if (!cx->typeInferenceEnabled() || !analysis->trackSlot(slot)) {
|
||||
masm.storeValue(UndefinedValue(), local);
|
||||
} else {
|
||||
Lifetime *lifetime = analysis->liveness(slot).live(0);
|
||||
if (lifetime)
|
||||
masm.storeValue(UndefinedValue(), local);
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < script->nfixed; i++)
|
||||
markUndefinedLocal(0, i);
|
||||
}
|
||||
|
||||
CompileStatus
|
||||
|
@ -3050,6 +3054,10 @@ mjit::Compiler::generateMethod()
|
|||
{
|
||||
uint32_t slot = GET_SLOTNO(PC);
|
||||
JSFunction *fun = script->getFunction(GET_UINT32_INDEX(PC + SLOTNO_LEN));
|
||||
|
||||
/* See JSOP_DEFLOCALFUN. */
|
||||
markUndefinedLocal(PC - script->code, slot);
|
||||
|
||||
prepareStubCall(Uses(frame.frameSlots()));
|
||||
masm.move(ImmPtr(fun), Registers::ArgReg1);
|
||||
INLINE_STUBCALL(stubs::DefLocalFun_FC, REJOIN_DEFLOCALFUN);
|
||||
|
@ -3130,6 +3138,16 @@ mjit::Compiler::generateMethod()
|
|||
{
|
||||
uint32_t slot = GET_SLOTNO(PC);
|
||||
JSFunction *fun = script->getFunction(GET_UINT32_INDEX(PC + SLOTNO_LEN));
|
||||
|
||||
/*
|
||||
* The liveness analysis will report that the value in |slot| is
|
||||
* defined at the start of this opcode. However, we don't actually
|
||||
* fill it in until the stub returns. This will cause a problem if
|
||||
* we GC inside the stub. So we write a safe value here so that the
|
||||
* GC won't crash.
|
||||
*/
|
||||
markUndefinedLocal(PC - script->code, slot);
|
||||
|
||||
prepareStubCall(Uses(0));
|
||||
masm.move(ImmPtr(fun), Registers::ArgReg1);
|
||||
INLINE_STUBCALL(stubs::DefLocalFun, REJOIN_DEFLOCALFUN);
|
||||
|
|
|
@ -574,6 +574,7 @@ private:
|
|||
/* Analysis helpers. */
|
||||
CompileStatus prepareInferenceTypes(JSScript *script, ActiveFrame *a);
|
||||
void ensureDoubleArguments();
|
||||
void markUndefinedLocal(uint32_t offset, uint32_t i);
|
||||
void markUndefinedLocals();
|
||||
void fixDoubleTypes(jsbytecode *target);
|
||||
void watchGlobalReallocation();
|
||||
|
|
|
@ -2061,7 +2061,12 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
|||
// to cause period, and we hope hygienic, last-ditch GCs from within
|
||||
// the GC's allocator.
|
||||
JS_SetGCParameter(mJSRuntime, JSGC_MAX_BYTES, 0xffffffff);
|
||||
#ifdef MOZ_ASAN
|
||||
// ASan requires more stack space due to redzones
|
||||
JS_SetNativeStackQuota(mJSRuntime, 2 * 128 * sizeof(size_t) * 1024);
|
||||
#else
|
||||
JS_SetNativeStackQuota(mJSRuntime, 128 * sizeof(size_t) * 1024);
|
||||
#endif
|
||||
JS_SetContextCallback(mJSRuntime, ContextCallback);
|
||||
JS_SetCompartmentCallback(mJSRuntime, CompartmentCallback);
|
||||
JS_SetGCCallback(mJSRuntime, GCCallback);
|
||||
|
|
|
@ -644,7 +644,7 @@ nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
|
|||
for (nsBlockFrame* block = aBlockFrame; block;
|
||||
block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
|
||||
block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
|
||||
nsBlockInFlowLineIterator lineIter(block, block->begin_lines(), false);
|
||||
nsBlockInFlowLineIterator lineIter(block, block->begin_lines());
|
||||
bpd.mPrevFrame = nsnull;
|
||||
bpd.GetSubParagraph()->mPrevFrame = nsnull;
|
||||
TraverseFrames(aBlockFrame, &lineIter, block->GetFirstPrincipalChild(), &bpd);
|
||||
|
|
|
@ -169,6 +169,7 @@ _TEST_FILES = \
|
|||
test_bug588174.html \
|
||||
test_bug607529.html \
|
||||
file_bug607529.html \
|
||||
test_bug667512.html \
|
||||
test_bug677878.html \
|
||||
test_bug696020.html \
|
||||
test_flush_on_paint.html \
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=667512
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 667512</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<table contenteditable="true"><tbody><tr><td id="b"><br id="a"></td></tr></tbody></table>
|
||||
<span style="display: list-item;direction: rtl;"></span>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 667512 **/
|
||||
function appendElements() {
|
||||
window.focus();
|
||||
window.getSelection().collapse(document.documentElement, 0);
|
||||
|
||||
var x=document.getElementById('a');
|
||||
x.parentNode.removeChild(x);
|
||||
|
||||
var x=document.getElementById('b');
|
||||
x.parentNode.removeChild(x);
|
||||
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
|
||||
ok(true, "Should not crash!");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
addLoadEvent(appendElements);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1324,7 +1324,7 @@ nsComboboxControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
nsBlockFrame::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
nsFrameList
|
||||
const nsFrameList&
|
||||
nsComboboxControlFrame::GetChildList(ChildListID aListID) const
|
||||
{
|
||||
if (kSelectPopupList == aListID) {
|
||||
|
|
|
@ -141,7 +141,7 @@ public:
|
|||
virtual void DestroyFrom(nsIFrame* aDestructRoot);
|
||||
NS_IMETHOD SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList);
|
||||
virtual nsFrameList GetChildList(ChildListID aListID) const;
|
||||
virtual const nsFrameList& GetChildList(ChildListID aListID) const;
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
|
||||
|
||||
virtual nsIFrame* GetContentInsertionFrame();
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -154,11 +154,6 @@ public:
|
|||
|
||||
friend nsIFrame* NS_NewBlockFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
|
||||
|
||||
// This is a child list too, but we let nsBlockReflowState get to it
|
||||
// directly too.
|
||||
NS_DECLARE_FRAME_PROPERTY(PushedFloatProperty,
|
||||
nsContainerFrame::DestroyFrameList)
|
||||
|
||||
// nsQueryFrame
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
|
@ -175,7 +170,7 @@ public:
|
|||
nsFrameList& aFrameList);
|
||||
NS_IMETHOD RemoveFrame(ChildListID aListID,
|
||||
nsIFrame* aOldFrame);
|
||||
virtual nsFrameList GetChildList(ChildListID aListID) const;
|
||||
virtual const nsFrameList& GetChildList(ChildListID aListID) const;
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
|
||||
virtual nscoord GetBaseline() const;
|
||||
virtual nscoord GetCaretBaseline() const;
|
||||
|
@ -246,12 +241,14 @@ public:
|
|||
/**
|
||||
* Return the bullet text equivalent.
|
||||
*/
|
||||
virtual void GetBulletText(nsAString& aText) const;
|
||||
void GetBulletText(nsAString& aText) const;
|
||||
|
||||
/**
|
||||
* Return true if there's a bullet.
|
||||
*/
|
||||
virtual bool HasBullet() const;
|
||||
bool HasBullet() const {
|
||||
return HasOutsideBullet() || HasInsideBullet();
|
||||
}
|
||||
|
||||
virtual void MarkIntrinsicWidthsDirty();
|
||||
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
|
||||
|
@ -328,6 +325,11 @@ public:
|
|||
*/
|
||||
static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
|
||||
|
||||
struct FrameLines {
|
||||
nsLineList mLines;
|
||||
nsFrameList mFrames;
|
||||
};
|
||||
|
||||
protected:
|
||||
nsBlockFrame(nsStyleContext* aContext)
|
||||
: nsContainerFrame(aContext)
|
||||
|
@ -355,22 +357,14 @@ protected:
|
|||
void TryAllLines(nsLineList::iterator* aIterator,
|
||||
nsLineList::iterator* aStartIterator,
|
||||
nsLineList::iterator* aEndIterator,
|
||||
bool* aInOverflowLines);
|
||||
bool* aInOverflowLines,
|
||||
FrameLines** aOverflowLines);
|
||||
|
||||
void SetFlags(nsFrameState aFlags) {
|
||||
mState &= ~NS_BLOCK_FLAGS_MASK;
|
||||
mState |= aFlags;
|
||||
}
|
||||
|
||||
bool HaveOutsideBullet() const {
|
||||
#if defined(DEBUG) && !defined(DEBUG_rods)
|
||||
if(mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET) {
|
||||
NS_ASSERTION(mBullet,"NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET flag set and no mBullet");
|
||||
}
|
||||
#endif
|
||||
return 0 != (mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET);
|
||||
}
|
||||
|
||||
/** move the frames contained by aLine by aDY
|
||||
* if aLine is a block, its child floats are added to the state manager
|
||||
*/
|
||||
|
@ -646,8 +640,14 @@ protected:
|
|||
nsLineBox* aLine,
|
||||
nsBlockFrame* aFromContainer,
|
||||
bool aFromOverflowLine,
|
||||
nsFrameList& aFromFrameList,
|
||||
nsLineList::iterator aFromLine);
|
||||
|
||||
/**
|
||||
* Push the line after aLineBefore to the overflow line list.
|
||||
* @param aLineBefore a line in 'mLines' (or begin_lines() when
|
||||
* pushing the first line)
|
||||
*/
|
||||
void PushLines(nsBlockReflowState& aState,
|
||||
nsLineList::iterator aLineBefore);
|
||||
|
||||
|
@ -675,7 +675,8 @@ protected:
|
|||
|
||||
static bool FrameStartsCounterScope(nsIFrame* aFrame);
|
||||
|
||||
void ReflowBullet(nsBlockReflowState& aState,
|
||||
void ReflowBullet(nsIFrame* aBulletFrame,
|
||||
nsBlockReflowState& aState,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nscoord aLineTop);
|
||||
|
||||
|
@ -684,10 +685,14 @@ protected:
|
|||
virtual nsILineIterator* GetLineIterator();
|
||||
|
||||
public:
|
||||
nsLineList* GetOverflowLines() const;
|
||||
bool HasOverflowLines() const {
|
||||
return 0 != (GetStateBits() & NS_BLOCK_HAS_OVERFLOW_LINES);
|
||||
}
|
||||
FrameLines* GetOverflowLines() const;
|
||||
protected:
|
||||
nsLineList* RemoveOverflowLines();
|
||||
nsresult SetOverflowLines(nsLineList* aOverflowLines);
|
||||
FrameLines* RemoveOverflowLines();
|
||||
void SetOverflowLines(FrameLines* aOverflowLines);
|
||||
void DestroyOverflowLines();
|
||||
|
||||
// Determine the computed height that's in effect for this block
|
||||
// frame (that is, our computed height minus the heights of our
|
||||
|
@ -724,6 +729,50 @@ protected:
|
|||
nsFrameList* GetOverflowOutOfFlows() const;
|
||||
void SetOverflowOutOfFlows(const nsFrameList& aList, nsFrameList* aPropValue);
|
||||
|
||||
/**
|
||||
* @return true if this frame has an inside bullet frame.
|
||||
*/
|
||||
bool HasInsideBullet() const {
|
||||
return 0 != (mState & NS_BLOCK_FRAME_HAS_INSIDE_BULLET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the inside bullet frame or nsnull if we don't have one.
|
||||
*/
|
||||
nsBulletFrame* GetInsideBullet() const;
|
||||
|
||||
/**
|
||||
* @return true if this frame has an outside bullet frame.
|
||||
*/
|
||||
bool HasOutsideBullet() const {
|
||||
return 0 != (mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the outside bullet frame or nsnull if we don't have one.
|
||||
*/
|
||||
nsBulletFrame* GetOutsideBullet() const;
|
||||
|
||||
/**
|
||||
* @return the outside bullet frame list frame property.
|
||||
*/
|
||||
nsFrameList* GetOutsideBulletList() const;
|
||||
|
||||
/**
|
||||
* @return the bullet frame or nsnull if we don't have one.
|
||||
*/
|
||||
nsBulletFrame* GetBullet() const {
|
||||
nsBulletFrame* outside = GetOutsideBullet();
|
||||
return outside ? outside : GetInsideBullet();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this frame has pushed floats.
|
||||
*/
|
||||
bool HasPushedFloats() const {
|
||||
return 0 != (GetStateBits() & NS_BLOCK_HAS_PUSHED_FLOATS);
|
||||
}
|
||||
|
||||
// Get the pushed floats list
|
||||
nsFrameList* GetPushedFloats() const;
|
||||
// Get the pushed floats list, or if there is not currently one,
|
||||
|
@ -743,12 +792,9 @@ protected:
|
|||
nsLineList mLines;
|
||||
|
||||
// List of all floats in this block
|
||||
// XXXmats blocks rarely have floats, make it a frame property
|
||||
nsFrameList mFloats;
|
||||
|
||||
// XXX_fix_me: subclass one more time!
|
||||
// For list-item frames, this is the bullet frame.
|
||||
nsBulletFrame* mBullet;
|
||||
|
||||
friend class nsBlockReflowState;
|
||||
friend class nsBlockInFlowLineIterator;
|
||||
|
||||
|
@ -798,7 +844,11 @@ private:
|
|||
class nsBlockInFlowLineIterator {
|
||||
public:
|
||||
typedef nsBlockFrame::line_iterator line_iterator;
|
||||
nsBlockInFlowLineIterator(nsBlockFrame* aFrame, line_iterator aLine, bool aInOverflow);
|
||||
/**
|
||||
* Set up the iterator to point to aLine which must be a normal line
|
||||
* in aFrame (not an overflow line).
|
||||
*/
|
||||
nsBlockInFlowLineIterator(nsBlockFrame* aFrame, line_iterator aLine);
|
||||
/**
|
||||
* Set up the iterator to point to the first line found starting from
|
||||
* aFrame. Sets aFoundValidLine to false if there is no such line.
|
||||
|
@ -845,6 +895,10 @@ public:
|
|||
bool Prev();
|
||||
|
||||
private:
|
||||
friend class nsBlockFrame;
|
||||
// XXX nsBlockFrame uses this internally in one place. Try to remove it.
|
||||
nsBlockInFlowLineIterator(nsBlockFrame* aFrame, line_iterator aLine, bool aInOverflow);
|
||||
|
||||
nsBlockFrame* mFrame;
|
||||
line_iterator mLine;
|
||||
nsLineList* mInOverflowLines;
|
||||
|
|
|
@ -124,7 +124,8 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
|
|||
nsBlockFrame::line_iterator line_end;
|
||||
bool anyLines = true;
|
||||
if (overflowLines) {
|
||||
nsLineList* lines = block->GetOverflowLines();
|
||||
nsBlockFrame::FrameLines* frames = block->GetOverflowLines();
|
||||
nsLineList* lines = frames ? &frames->mLines : nsnull;
|
||||
if (!lines) {
|
||||
anyLines = false;
|
||||
} else {
|
||||
|
|
|
@ -273,7 +273,7 @@ nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Child frame enumeration
|
||||
|
||||
nsFrameList
|
||||
const nsFrameList&
|
||||
nsContainerFrame::GetChildList(ChildListID aListID) const
|
||||
{
|
||||
// We only know about the principal child list and the overflow lists.
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
NS_IMETHOD RemoveFrame(ChildListID aListID,
|
||||
nsIFrame* aOldFrame);
|
||||
|
||||
virtual nsFrameList GetChildList(ChildListID aList) const;
|
||||
virtual const nsFrameList& GetChildList(ChildListID aList) const;
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot);
|
||||
virtual void ChildIsDirty(nsIFrame* aChild);
|
||||
|
|
|
@ -1187,7 +1187,7 @@ nsFrame::GetBaseline() const
|
|||
return mRect.height + GetUsedMargin().bottom;
|
||||
}
|
||||
|
||||
nsFrameList
|
||||
const nsFrameList&
|
||||
nsFrame::GetChildList(ChildListID aListID) const
|
||||
{
|
||||
if (IsAbsoluteContainer() &&
|
||||
|
|
|
@ -190,7 +190,7 @@ public:
|
|||
nsStyleContext* aStyleContext);
|
||||
virtual void SetParent(nsIFrame* aParent);
|
||||
virtual nscoord GetBaseline() const;
|
||||
virtual nsFrameList GetChildList(ChildListID aListID) const;
|
||||
virtual const nsFrameList& GetChildList(ChildListID aListID) const;
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
|
||||
|
||||
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
||||
|
|
|
@ -73,6 +73,10 @@ class nsTableColFrame;
|
|||
* frame among the block's descendants. If there is a floating first-letter
|
||||
* frame, or the block has first-letter style but has no first letter, this
|
||||
* bit is not set. This bit is set on the first continuation only.
|
||||
*
|
||||
* NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET and NS_BLOCK_FRAME_HAS_INSIDE_BULLET
|
||||
* means the block has an associated bullet frame, they are mutually exclusive.
|
||||
*
|
||||
*/
|
||||
#define NS_BLOCK_MARGIN_ROOT NS_FRAME_STATE_BIT(22)
|
||||
#define NS_BLOCK_FLOAT_MGR NS_FRAME_STATE_BIT(23)
|
||||
|
@ -80,14 +84,25 @@ class nsTableColFrame;
|
|||
#define NS_BLOCK_HAS_FIRST_LETTER_STYLE NS_FRAME_STATE_BIT(29)
|
||||
#define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET NS_FRAME_STATE_BIT(30)
|
||||
#define NS_BLOCK_HAS_FIRST_LETTER_CHILD NS_FRAME_STATE_BIT(31)
|
||||
// These are the bits that get inherited from a block frame to its
|
||||
// next-in-flows and are not private to blocks
|
||||
#define NS_BLOCK_FLAGS_MASK (NS_BLOCK_MARGIN_ROOT | \
|
||||
NS_BLOCK_FLOAT_MGR | \
|
||||
NS_BLOCK_CLIP_PAGINATED_OVERFLOW | \
|
||||
NS_BLOCK_HAS_FIRST_LETTER_STYLE | \
|
||||
NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET | \
|
||||
NS_BLOCK_HAS_FIRST_LETTER_CHILD)
|
||||
#define NS_BLOCK_FRAME_HAS_INSIDE_BULLET NS_FRAME_STATE_BIT(63)
|
||||
// These are all the block specific frame bits, they are copied from
|
||||
// the prev-in-flow to a newly created next-in-flow, except for the
|
||||
// NS_BLOCK_FLAGS_NON_INHERITED_MASK bits below.
|
||||
#define NS_BLOCK_FLAGS_MASK (NS_BLOCK_MARGIN_ROOT | \
|
||||
NS_BLOCK_FLOAT_MGR | \
|
||||
NS_BLOCK_CLIP_PAGINATED_OVERFLOW | \
|
||||
NS_BLOCK_HAS_FIRST_LETTER_STYLE | \
|
||||
NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET | \
|
||||
NS_BLOCK_HAS_FIRST_LETTER_CHILD | \
|
||||
NS_BLOCK_FRAME_HAS_INSIDE_BULLET)
|
||||
|
||||
// This is the subset of NS_BLOCK_FLAGS_MASK that is NOT inherited
|
||||
// by default. They should only be set on the first-in-flow.
|
||||
// See nsBlockFrame::Init.
|
||||
#define NS_BLOCK_FLAGS_NON_INHERITED_MASK \
|
||||
(NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET | \
|
||||
NS_BLOCK_HAS_FIRST_LETTER_CHILD | \
|
||||
NS_BLOCK_FRAME_HAS_INSIDE_BULLET)
|
||||
|
||||
// Factory methods for creating html layout objects
|
||||
|
||||
|
|
|
@ -1057,12 +1057,8 @@ public:
|
|||
* @return the child list. If the requested list is unsupported by this
|
||||
* frame type, an empty list will be returned.
|
||||
*/
|
||||
// XXXbz if all our frame storage were actually backed by nsFrameList, we
|
||||
// could make this return a const reference... nsBlockFrame is the only real
|
||||
// culprit here. Make sure to assign the return value of this function into
|
||||
// a |const nsFrameList&|, not an nsFrameList.
|
||||
virtual nsFrameList GetChildList(ChildListID aListID) const = 0;
|
||||
nsFrameList PrincipalChildList() { return GetChildList(kPrincipalList); }
|
||||
virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
|
||||
const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); }
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
|
||||
// XXXbz this method should go away
|
||||
nsIFrame* GetFirstChild(ChildListID aListID) const {
|
||||
|
|
|
@ -235,6 +235,7 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
nsIFrame*
|
||||
nsLineBox::LastChild() const
|
||||
{
|
||||
|
@ -245,13 +246,7 @@ nsLineBox::LastChild() const
|
|||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
bool
|
||||
nsLineBox::IsLastChild(nsIFrame* aFrame) const
|
||||
{
|
||||
nsIFrame* lastFrame = LastChild();
|
||||
return aFrame == lastFrame;
|
||||
}
|
||||
#endif
|
||||
|
||||
PRInt32
|
||||
nsLineBox::IndexOf(nsIFrame* aFrame) const
|
||||
|
@ -373,7 +368,7 @@ nsLineBox::RFindLineContaining(nsIFrame* aFrame,
|
|||
nsIFrame* curFrame = aLastFrameBeforeEnd;
|
||||
while (aBegin != aEnd) {
|
||||
--aEnd;
|
||||
NS_ASSERTION(aEnd->IsLastChild(curFrame), "Unexpected curFrame");
|
||||
NS_ASSERTION(aEnd->LastChild() == curFrame, "Unexpected curFrame");
|
||||
// i is the index of curFrame in aEnd
|
||||
PRInt32 i = aEnd->GetChildCount() - 1;
|
||||
while (i >= 0) {
|
||||
|
|
|
@ -470,11 +470,8 @@ public:
|
|||
char* StateToString(char* aBuf, PRInt32 aBufSize) const;
|
||||
|
||||
void List(FILE* out, PRInt32 aIndent) const;
|
||||
#endif
|
||||
|
||||
nsIFrame* LastChild() const;
|
||||
|
||||
bool IsLastChild(nsIFrame* aFrame) const;
|
||||
#endif
|
||||
|
||||
PRInt32 IndexOf(nsIFrame* aFrame) const;
|
||||
|
||||
|
|
|
@ -351,6 +351,9 @@ nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
mBackgroundSink->Destroy();
|
||||
}
|
||||
|
||||
if (mInstanceOwner) {
|
||||
mInstanceOwner->SetFrame(nsnull);
|
||||
}
|
||||
SetInstanceOwner(nsnull);
|
||||
|
||||
nsObjectFrameSuper::DestroyFrom(aDestructRoot);
|
||||
|
|
|
@ -1212,7 +1212,7 @@ BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame,
|
|||
bool isValid = true;
|
||||
nsBlockInFlowLineIterator backIterator(block, &isValid);
|
||||
if (aForFrameLine) {
|
||||
backIterator = nsBlockInFlowLineIterator(block, *aForFrameLine, false);
|
||||
backIterator = nsBlockInFlowLineIterator(block, *aForFrameLine);
|
||||
} else {
|
||||
backIterator = nsBlockInFlowLineIterator(block, lineContainerChild, &isValid);
|
||||
NS_ASSERTION(isValid, "aForFrame not found in block, someone lied to us");
|
||||
|
|
|
@ -1215,6 +1215,11 @@ nsSVGUtils::HitTestChildren(nsIFrame *aFrame, const nsPoint &aPoint)
|
|||
current = current->GetPrevSibling()) {
|
||||
nsISVGChildFrame* SVGFrame = do_QueryFrame(current);
|
||||
if (SVGFrame) {
|
||||
const nsIContent* content = current->GetContent();
|
||||
if (content->IsSVG() &&
|
||||
!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
|
||||
continue;
|
||||
}
|
||||
result = SVGFrame->GetFrameForPoint(aPoint);
|
||||
if (result)
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
|
||||
|
||||
<symbol id="z">
|
||||
<use xlink:href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' id='root' />#root" />
|
||||
</symbol>
|
||||
|
||||
<use id="a" xlink:href="#z" width="20"/>
|
||||
|
||||
<script>
|
||||
window.addEventListener("load", function() {
|
||||
window.scrollByPages(0);
|
||||
document.getElementById("a").removeAttribute("width");
|
||||
document.elementFromPoint(0, 0);
|
||||
}, false);
|
||||
</script>
|
||||
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 485 B |
|
@ -124,3 +124,4 @@ load 709920-2.svg
|
|||
load 713413-1.svg
|
||||
load 722003-1.svg
|
||||
load 725918-1.svg
|
||||
load 732836-1.svg
|
||||
|
|
|
@ -1045,7 +1045,7 @@ nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Child frame enumeration
|
||||
|
||||
nsFrameList
|
||||
const nsFrameList&
|
||||
nsTableFrame::GetChildList(ChildListID aListID) const
|
||||
{
|
||||
if (aListID == kColGroupList) {
|
||||
|
|
|
@ -244,7 +244,7 @@ public:
|
|||
NS_IMETHOD SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList);
|
||||
|
||||
virtual nsFrameList GetChildList(ChildListID aListID) const;
|
||||
virtual const nsFrameList& GetChildList(ChildListID aListID) const;
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
|
||||
|
||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -215,7 +215,7 @@ nsTableOuterFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
nsContainerFrame::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
nsFrameList
|
||||
const nsFrameList&
|
||||
nsTableOuterFrame::GetChildList(ChildListID aListID) const
|
||||
{
|
||||
if (aListID == kCaptionList) {
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
NS_IMETHOD SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList);
|
||||
|
||||
virtual nsFrameList GetChildList(ChildListID aListID) const;
|
||||
virtual const nsFrameList& GetChildList(ChildListID aListID) const;
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
|
||||
|
||||
NS_IMETHOD AppendFrames(ChildListID aListID,
|
||||
|
|
|
@ -61,7 +61,7 @@ class nsBoxLayoutState;
|
|||
#define NS_STATE_CURRENTLY_IN_DEBUG NS_FRAME_STATE_BIT(25)
|
||||
//#define NS_STATE_SET_TO_DEBUG NS_FRAME_STATE_BIT(26) moved to nsBox.h
|
||||
//#define NS_STATE_DEBUG_WAS_SET NS_FRAME_STATE_BIT(27) moved to nsBox.h
|
||||
// NS_FRAME_STATE_BIT(28) not used anymore
|
||||
#define NS_STATE_MENU_HAS_POPUP_LIST NS_FRAME_STATE_BIT(28) /* used on nsMenuFrame */
|
||||
#define NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK NS_FRAME_STATE_BIT(29)
|
||||
#define NS_STATE_EQUAL_SIZE NS_FRAME_STATE_BIT(30)
|
||||
//#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31) moved to nsIFrame.h
|
||||
|
|
|
@ -87,6 +87,13 @@ using namespace mozilla;
|
|||
#define NSCONTEXTMENUISMOUSEUP 1
|
||||
#endif
|
||||
|
||||
static void
|
||||
AssertNotCalled(void* aPropertyValue)
|
||||
{
|
||||
NS_ERROR("popup list should never be destroyed by the FramePropertyTable");
|
||||
}
|
||||
NS_DECLARE_FRAME_PROPERTY(PopupListProperty, AssertNotCalled)
|
||||
|
||||
static PRInt32 gEatMouseMove = false;
|
||||
|
||||
const PRInt32 kBlinkDelay = 67; // milliseconds
|
||||
|
@ -207,9 +214,6 @@ NS_QUERYFRAME_HEAD(nsMenuFrame)
|
|||
NS_QUERYFRAME_ENTRY(nsMenuFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
|
||||
//
|
||||
// nsMenuFrame cntr
|
||||
//
|
||||
nsMenuFrame::nsMenuFrame(nsIPresShell* aShell, nsStyleContext* aContext):
|
||||
nsBoxFrame(aShell, aContext),
|
||||
mIsMenu(false),
|
||||
|
@ -217,11 +221,9 @@ nsMenuFrame::nsMenuFrame(nsIPresShell* aShell, nsStyleContext* aContext):
|
|||
mIgnoreAccelTextChange(false),
|
||||
mType(eMenuType_Normal),
|
||||
mMenuParent(nsnull),
|
||||
mPopupFrame(nsnull),
|
||||
mBlinkState(0)
|
||||
{
|
||||
|
||||
} // cntr
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuFrame::SetParent(nsIFrame* aParent)
|
||||
|
@ -298,11 +300,12 @@ nsMenuFrame::Init(nsIContent* aContent,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsFrameList
|
||||
const nsFrameList&
|
||||
nsMenuFrame::GetChildList(ChildListID aListID) const
|
||||
{
|
||||
if (kPopupList == aListID) {
|
||||
return nsFrameList(mPopupFrame, mPopupFrame);
|
||||
nsFrameList* list = GetPopupList();
|
||||
return list ? *list : nsFrameList::EmptyList();
|
||||
}
|
||||
return nsBoxFrame::GetChildList(aListID);
|
||||
}
|
||||
|
@ -311,8 +314,44 @@ void
|
|||
nsMenuFrame::GetChildLists(nsTArray<ChildList>* aLists) const
|
||||
{
|
||||
nsBoxFrame::GetChildLists(aLists);
|
||||
nsFrameList popupList(mPopupFrame, mPopupFrame);
|
||||
popupList.AppendIfNonempty(aLists, kPopupList);
|
||||
nsFrameList* list = GetPopupList();
|
||||
if (list) {
|
||||
list->AppendIfNonempty(aLists, kPopupList);
|
||||
}
|
||||
}
|
||||
|
||||
nsMenuPopupFrame*
|
||||
nsMenuFrame::GetPopup()
|
||||
{
|
||||
nsFrameList* popupList = GetPopupList();
|
||||
return popupList ? static_cast<nsMenuPopupFrame*>(popupList->FirstChild()) :
|
||||
nsnull;
|
||||
}
|
||||
|
||||
nsFrameList*
|
||||
nsMenuFrame::GetPopupList() const
|
||||
{
|
||||
if (!HasPopup()) {
|
||||
return nsnull;
|
||||
}
|
||||
nsFrameList* prop =
|
||||
static_cast<nsFrameList*>(Properties().Get(PopupListProperty()));
|
||||
NS_ASSERTION(prop && prop->GetLength() == 1 &&
|
||||
prop->FirstChild()->GetType() == nsGkAtoms::menuPopupFrame,
|
||||
"popup list should have exactly one nsMenuPopupFrame");
|
||||
return prop;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuFrame::DestroyPopupList()
|
||||
{
|
||||
NS_ASSERTION(HasPopup(), "huh?");
|
||||
nsFrameList* prop =
|
||||
static_cast<nsFrameList*>(Properties().Remove(PopupListProperty()));
|
||||
NS_ASSERTION(prop && prop->IsEmpty(),
|
||||
"popup list must exist and be empty when destroying");
|
||||
RemoveStateBits(NS_STATE_MENU_HAS_POPUP_LIST);
|
||||
delete prop;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -320,9 +359,12 @@ nsMenuFrame::SetPopupFrame(nsFrameList& aFrameList)
|
|||
{
|
||||
for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
|
||||
if (e.get()->GetType() == nsGkAtoms::menuPopupFrame) {
|
||||
// Remove this frame from the list and set it as mPopupFrame
|
||||
mPopupFrame = (nsMenuPopupFrame *)e.get();
|
||||
aFrameList.RemoveFrame(e.get());
|
||||
// Remove the frame from the list and store it in a nsFrameList* property.
|
||||
nsIFrame* popupFrame = e.get();
|
||||
aFrameList.RemoveFrame(popupFrame);
|
||||
nsFrameList* popupList = new nsFrameList(popupFrame, popupFrame);
|
||||
Properties().Set(PopupListProperty(), popupList);
|
||||
AddStateBits(NS_STATE_MENU_HAS_POPUP_LIST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +374,7 @@ NS_IMETHODIMP
|
|||
nsMenuFrame::SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList)
|
||||
{
|
||||
NS_ASSERTION(!mPopupFrame, "already have a popup frame set");
|
||||
NS_ASSERTION(!HasPopup(), "SetInitialChildList called twice?");
|
||||
if (aListID == kPrincipalList || aListID == kPopupList) {
|
||||
SetPopupFrame(aChildList);
|
||||
}
|
||||
|
@ -365,8 +407,11 @@ nsMenuFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
mMenuParent->CurrentMenuIsBeingDestroyed();
|
||||
}
|
||||
|
||||
if (mPopupFrame)
|
||||
mPopupFrame->DestroyFrom(aDestructRoot);
|
||||
nsFrameList* popupList = GetPopupList();
|
||||
if (popupList) {
|
||||
popupList->DestroyFramesFrom(aDestructRoot);
|
||||
DestroyPopupList();
|
||||
}
|
||||
|
||||
nsBoxFrame::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
@ -675,8 +720,8 @@ nsMenuFrame::CloseMenu(bool aDeselectMenu)
|
|||
|
||||
// Close the menu asynchronously
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm && mPopupFrame)
|
||||
pm->HidePopup(mPopupFrame->GetContent(), false, aDeselectMenu, true);
|
||||
if (pm && HasPopup())
|
||||
pm->HidePopup(GetPopup()->GetContent(), false, aDeselectMenu, true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -713,9 +758,10 @@ nsMenuFrame::DoLayout(nsBoxLayoutState& aState)
|
|||
// lay us out
|
||||
nsresult rv = nsBoxFrame::DoLayout(aState);
|
||||
|
||||
if (mPopupFrame) {
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (popupFrame) {
|
||||
bool sizeToPopup = IsSizedToPopup(mContent, false);
|
||||
mPopupFrame->LayoutPopup(aState, this, sizeToPopup);
|
||||
popupFrame->LayoutPopup(aState, this, sizeToPopup);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -733,8 +779,9 @@ nsMenuFrame::SetDebug(nsBoxLayoutState& aState, bool aDebug)
|
|||
if (debugChanged)
|
||||
{
|
||||
nsBoxFrame::SetDebug(aState, aDebug);
|
||||
if (mPopupFrame)
|
||||
SetDebug(aState, mPopupFrame, aDebug);
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (popupFrame)
|
||||
SetDebug(aState, popupFrame, aDebug);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -797,7 +844,8 @@ nsMenuFrame::Enter(nsGUIEvent *aEvent)
|
|||
bool
|
||||
nsMenuFrame::IsOpen()
|
||||
{
|
||||
return mPopupFrame && mPopupFrame->IsOpen();
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
return popupFrame && popupFrame->IsOpen();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1248,21 +1296,15 @@ NS_IMETHODIMP
|
|||
nsMenuFrame::RemoveFrame(ChildListID aListID,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mPopupFrame == aOldFrame) {
|
||||
// Go ahead and remove this frame.
|
||||
mPopupFrame->Destroy();
|
||||
mPopupFrame = nsnull;
|
||||
nsFrameList* popupList = GetPopupList();
|
||||
if (popupList && popupList->DestroyFrameIfPresent(aOldFrame)) {
|
||||
DestroyPopupList();
|
||||
PresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
||||
NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = nsBoxFrame::RemoveFrame(aListID, aOldFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return nsBoxFrame::RemoveFrame(aListID, aOldFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1270,9 +1312,9 @@ nsMenuFrame::InsertFrames(ChildListID aListID,
|
|||
nsIFrame* aPrevFrame,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
if (!mPopupFrame && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
if (!HasPopup() && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
SetPopupFrame(aFrameList);
|
||||
if (mPopupFrame) {
|
||||
if (HasPopup()) {
|
||||
#ifdef DEBUG_LAYOUT
|
||||
nsBoxLayoutState state(PresContext());
|
||||
SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG);
|
||||
|
@ -1287,7 +1329,7 @@ nsMenuFrame::InsertFrames(ChildListID aListID,
|
|||
if (aFrameList.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
if (NS_UNLIKELY(aPrevFrame == mPopupFrame)) {
|
||||
if (NS_UNLIKELY(aPrevFrame && aPrevFrame == GetPopup())) {
|
||||
aPrevFrame = nsnull;
|
||||
}
|
||||
|
||||
|
@ -1298,9 +1340,9 @@ NS_IMETHODIMP
|
|||
nsMenuFrame::AppendFrames(ChildListID aListID,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
if (!mPopupFrame && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
if (!HasPopup() && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
SetPopupFrame(aFrameList);
|
||||
if (mPopupFrame) {
|
||||
if (HasPopup()) {
|
||||
|
||||
#ifdef DEBUG_LAYOUT
|
||||
nsBoxLayoutState state(PresContext());
|
||||
|
@ -1326,9 +1368,10 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
|
|||
nsSize tmpSize(-1, 0);
|
||||
nsIBox::AddCSSPrefSize(this, tmpSize, widthSet, heightSet);
|
||||
if (!widthSet && GetFlex(aState) == 0) {
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return false;
|
||||
tmpSize = mPopupFrame->GetPrefSize(aState);
|
||||
tmpSize = popupFrame->GetPrefSize(aState);
|
||||
|
||||
// Produce a size such that:
|
||||
// (1) the menu and its popup can be the same width
|
||||
|
@ -1340,7 +1383,7 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
|
|||
GetBorderAndPadding(borderPadding);
|
||||
|
||||
// if there is a scroll frame, add the desired width of the scrollbar as well
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(mPopupFrame->GetFirstPrincipalChild());
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(popupFrame->GetFirstPrincipalChild());
|
||||
nscoord scrollbarWidth = 0;
|
||||
if (scrollFrame) {
|
||||
scrollbarWidth =
|
||||
|
@ -1380,10 +1423,11 @@ nsMenuFrame::GetPrefSize(nsBoxLayoutState& aState)
|
|||
NS_IMETHODIMP
|
||||
nsMenuFrame::GetActiveChild(nsIDOMElement** aResult)
|
||||
{
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsMenuFrame* menuFrame = mPopupFrame->GetCurrentMenuItem();
|
||||
nsMenuFrame* menuFrame = popupFrame->GetCurrentMenuItem();
|
||||
if (!menuFrame) {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
@ -1399,12 +1443,13 @@ nsMenuFrame::GetActiveChild(nsIDOMElement** aResult)
|
|||
NS_IMETHODIMP
|
||||
nsMenuFrame::SetActiveChild(nsIDOMElement* aChild)
|
||||
{
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!aChild) {
|
||||
// Remove the current selection
|
||||
mPopupFrame->ChangeMenuItem(nsnull, false);
|
||||
popupFrame->ChangeMenuItem(nsnull, false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1412,17 +1457,18 @@ nsMenuFrame::SetActiveChild(nsIDOMElement* aChild)
|
|||
|
||||
nsIFrame* kid = child->GetPrimaryFrame();
|
||||
if (kid && kid->GetType() == nsGkAtoms::menuFrame)
|
||||
mPopupFrame->ChangeMenuItem(static_cast<nsMenuFrame *>(kid), false);
|
||||
popupFrame->ChangeMenuItem(static_cast<nsMenuFrame *>(kid), false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* nsMenuFrame::GetScrollTargetFrame()
|
||||
{
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return nsnull;
|
||||
nsIFrame* childFrame = mPopupFrame->GetFirstPrincipalChild();
|
||||
nsIFrame* childFrame = popupFrame->GetFirstPrincipalChild();
|
||||
if (childFrame)
|
||||
return mPopupFrame->GetScrollFrame(childFrame);
|
||||
return popupFrame->GetScrollFrame(childFrame);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ public:
|
|||
// The following methods are all overridden so that the menupopup
|
||||
// can be stored in a separate list, so that it doesn't impact reflow of the
|
||||
// actual menu item at all.
|
||||
virtual nsFrameList GetChildList(ChildListID aList) const;
|
||||
virtual const nsFrameList& GetChildList(ChildListID aList) const;
|
||||
virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
|
||||
NS_IMETHOD SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList);
|
||||
|
@ -185,7 +185,16 @@ public:
|
|||
virtual nsMenuParent *GetMenuParent() { return mMenuParent; }
|
||||
const nsAString& GetRadioGroupName() { return mGroupName; }
|
||||
nsMenuType GetMenuType() { return mType; }
|
||||
nsMenuPopupFrame* GetPopup() { return mPopupFrame; }
|
||||
nsMenuPopupFrame* GetPopup();
|
||||
|
||||
/**
|
||||
* @return true if this frame has a popup child frame.
|
||||
*/
|
||||
bool HasPopup() const
|
||||
{
|
||||
return (GetStateBits() & NS_STATE_MENU_HAS_POPUP_LIST) != 0;
|
||||
}
|
||||
|
||||
|
||||
// nsMenuFrame methods
|
||||
|
||||
|
@ -226,10 +235,23 @@ protected:
|
|||
friend class nsASyncMenuInitialization;
|
||||
friend class nsMenuAttributeChangedEvent;
|
||||
|
||||
// initialize mPopupFrame to the first popup frame within
|
||||
// aChildList. Removes the popup, if any, from aChildList.
|
||||
/**
|
||||
* Initialize the popup list to the first popup frame within
|
||||
* aChildList. Removes the popup, if any, from aChildList.
|
||||
*/
|
||||
void SetPopupFrame(nsFrameList& aChildList);
|
||||
|
||||
/**
|
||||
* Get the popup frame list from the frame property.
|
||||
* @return the property value if it exists, nsnull otherwise.
|
||||
*/
|
||||
nsFrameList* GetPopupList() const;
|
||||
|
||||
/**
|
||||
* Destroy the popup list property. The list must exist and be empty.
|
||||
*/
|
||||
void DestroyPopupList();
|
||||
|
||||
// set mMenuParent to the nearest enclosing menu bar or menupopup frame of
|
||||
// aParent (or aParent itself). This is called when initializing the frame,
|
||||
// so aParent should be the expected parent of this frame.
|
||||
|
@ -275,9 +297,6 @@ protected:
|
|||
|
||||
nsMenuParent* mMenuParent; // Our parent menu.
|
||||
|
||||
// the popup for this menu, owned
|
||||
nsMenuPopupFrame* mPopupFrame;
|
||||
|
||||
// Reference to the mediator which wraps this frame.
|
||||
nsRefPtr<nsMenuTimerMediator> mTimerMediator;
|
||||
|
||||
|
|
|
@ -0,0 +1,273 @@
|
|||
= mfbt style rules =
|
||||
|
||||
== Line length ==
|
||||
|
||||
The line limit is 80 characters, except that excessively long blocks of preprocessor directives may exceed this if it makes the code more readable (e.g. MOZ_STATIC_ASSERT in Assertions.h.), and unbreakable text in comments (e.g. URLs) may exceed this as well. Wrap expressions after binary operators.
|
||||
|
||||
== Capitalization ==
|
||||
|
||||
Standalone functions, classes, structs, and template parameters are named InterCaps-style. Member functions and fields in classes and structs are named camelCaps-style.
|
||||
|
||||
== Indentation ==
|
||||
|
||||
Indentation is two spaces, never tabs.
|
||||
|
||||
if (x == 2)
|
||||
return 17;
|
||||
|
||||
== Whitespace ==
|
||||
|
||||
Surround binary operators with a single space on either side.
|
||||
|
||||
if (x == 2)
|
||||
return 17;
|
||||
|
||||
When describing pointer types, the * shall be adjacent to the type name. (Same goes for references -- & goes by the type name.)
|
||||
|
||||
int
|
||||
Foo(int* p)
|
||||
{
|
||||
typedef void* VoidPtr;
|
||||
int& i = *p;
|
||||
}
|
||||
|
||||
A corollary: don't mix declaration types by declaring a T and a T* (or a T**, &c.) in the same declaration.
|
||||
|
||||
T* foo, bar; // BAD
|
||||
|
||||
== Bracing ==
|
||||
|
||||
Don't brace single statements.
|
||||
|
||||
if (y == 7)
|
||||
return 3;
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
frob(i);
|
||||
|
||||
But do brace them if the statement (or condition(s) or any additional consequents, if the braces would be associated with an if statement) occupies multiple lines.
|
||||
|
||||
if (cond1 ||
|
||||
cond2)
|
||||
{
|
||||
action();
|
||||
}
|
||||
if (cond1) {
|
||||
consequent();
|
||||
} else {
|
||||
alternative(arg1,
|
||||
arg2);
|
||||
}
|
||||
if (cond1 || cond2) {
|
||||
callMethod(arg1,
|
||||
arg2);
|
||||
}
|
||||
for (size_t j = 0;
|
||||
j < 17;
|
||||
j++)
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
Braces in control flow go at the end of the line except when associated with an |if| or loop-head where the condition covers multiple lines
|
||||
|
||||
== Classes and structs ==
|
||||
|
||||
Inside class and structure definitions, public/private consume one level of indentation.
|
||||
|
||||
class Baz
|
||||
{
|
||||
public:
|
||||
Baz() { }
|
||||
};
|
||||
|
||||
The absence of public/private in structs in which all members are public still consumes a level.
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int field;
|
||||
};
|
||||
|
||||
Braces delimiting a class or struct go on their own lines.
|
||||
|
||||
Member initialization in constructors should be formatted as follows:
|
||||
|
||||
class Fnord
|
||||
{
|
||||
size_t s1, s2, s3, s4, s5;
|
||||
|
||||
public:
|
||||
Fnord(size_t s) : s1(s), s2(s), s3(s), s4(s), s5(s) { }
|
||||
Fnord()
|
||||
: s1(0), /* member initialization can be compressed if desired */
|
||||
s2(0),
|
||||
s3(0),
|
||||
s4(0),
|
||||
s5(0)
|
||||
{
|
||||
...
|
||||
}
|
||||
};
|
||||
|
||||
Fields should go first in the class so that the basic structure is all in one place, consistently.
|
||||
|
||||
Use the inline keyword to annotate functions defined inline in a header. (If the function is defined inline in the class, don't bother adding it redundantly.)
|
||||
|
||||
Explicitly delete (using Attributes.h's MOZ_DELETE) the copy constructor and assignment operator from classes not intended to be copied or assigned to avoid mistakes.
|
||||
|
||||
class Funky
|
||||
{
|
||||
public:
|
||||
Funky() { }
|
||||
|
||||
private:
|
||||
Funky(const Funky& other) MOZ_DELETE;
|
||||
void operator=(const Funky& other) MOZ_DELETE;
|
||||
};
|
||||
|
||||
Include a blank line between sections of structs and classes with different access control.
|
||||
|
||||
The "get" prefix is used when a method is fallible. If it's infallible, don't use it.
|
||||
|
||||
class String
|
||||
{
|
||||
public:
|
||||
size_t length() const; // not getLength()
|
||||
};
|
||||
|
||||
== Templates ==
|
||||
|
||||
Capitalize template parameter names to distinguish them from fields.
|
||||
|
||||
template<size_t KeySize, typename T>
|
||||
class BloomFilter
|
||||
{
|
||||
};
|
||||
|
||||
Use single-letter names if it makes sense (T for an arbitrary type, K for key type, V for value type, &c.). Otherwise use InterCaps-style names.
|
||||
|
||||
When declaring or defining a function, template<...> goes on one line, the return type and other specifiers go on another line, and the function name and argument list go on a third line.
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
Vector::add(T t)
|
||||
{
|
||||
}
|
||||
|
||||
== Namespaces ==
|
||||
|
||||
All C++ code shall be in the mozilla namespace, except that functionality only used to implement external-facing API should be in the mozilla::detail namespace, indicating that it should not be directly used.
|
||||
|
||||
Namespace opening braces go on the same line as the namespace declaration. Namespace closing braces shall be commented. Namespace contents are not indented.
|
||||
|
||||
namespace mozilla {
|
||||
...
|
||||
} // namespace mozilla
|
||||
|
||||
Don't use |using| in a header unless it's confined to a class or method. Implementation files for out-of-line functionality may use |using|.
|
||||
|
||||
== #includes ==
|
||||
|
||||
Headers that include mfbt headers use a fully-qualified include path, even if full qualification is not strictly necessary.
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
mfbt headers should be included first, alphabetically. Standard includes should follow, separated from mfbt includes by a blank line.
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
If a header dependency is limited simply to the existence of a class, forward-declare it rather than #include that header.
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class BloomFilter;
|
||||
extern bool
|
||||
Test(BloomFilter* bf);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
== Preprocessor ==
|
||||
|
||||
Include guards should be named by determining the fully-qualified include path, then substituting _ for / and . in it, and finally appending a trailing _. For example, "mozilla/Assertions.h" becomes mozilla_Assertions_h_.
|
||||
|
||||
Nested preprocessor directives indent the directive name (but not the #) by two spaces.
|
||||
|
||||
#ifdef __clang__
|
||||
# define FOO ...
|
||||
#else
|
||||
# define FOO ...
|
||||
#endif
|
||||
|
||||
Comments within nested preprocessor directives align with directive names at that nesting depth.
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/* gcc supports C++11 override syntax. */
|
||||
# define MOZ_OVERRIDE override
|
||||
#else
|
||||
# define MOZ_OVERRIDE /* unsupported */
|
||||
#endif
|
||||
|
||||
Feature-testing macros may be defined to nothing. Macros intended to be textually expanded should be defined to a comment indicating non-support, as above or as appropriate to the situation.
|
||||
|
||||
No particular preference is expressed between testing for a macro being defined using defined(...) and using #ifdef.
|
||||
|
||||
When defining a macro with different expansions for different compilers, the top level of distinction should be the compiler, and the next nested level should be the compiler version. Clang seems likely to be around for awhile, so to reduce confusion test for it separately from gcc even when it's not strictly necessary.
|
||||
|
||||
#if defined(__clang__)
|
||||
#elif defined(__GNUC__)
|
||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
# else
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
#endif
|
||||
|
||||
But don't distinguish clang's feature support using version checks: use the __has_feature() and __has_extension() macros instead, because vendors may customize clang's version numbers.
|
||||
|
||||
Prefer inline functions to macros whenever possible.
|
||||
|
||||
== Comments ==
|
||||
|
||||
Header files shall have a short descriptive comment underneath license boilerplate indicating what functionality the file implements, to be picked up by MXR and displayed in directory listings. (But see bug 717196, which currently prevents MXR from doing this if the MPL2 boilerplate is used.)
|
||||
|
||||
Assertions.h:
|
||||
...license boilerplate...
|
||||
|
||||
/* Implementations of runtime and static assertion macros for C and C++. */
|
||||
|
||||
Classes intended for public use shall have interface comments explaining their functionality from the user's perspective. These comments shall include examples of how the relevant functionality might be used. These interface comments use /** */ doxygen/Javadoc-style comments.
|
||||
|
||||
/**
|
||||
* The Frobber class simplifies the process of frobbing.
|
||||
*/
|
||||
class Frobber
|
||||
{
|
||||
};
|
||||
|
||||
Comments describing implementation details (tradeoffs considered, assumptions made, mathematical background, &c.) occur separately from interface comments so that users need not consider them. They should go inside the class definition or inside the appropriate method, depending on the specificity of the comment.
|
||||
|
||||
Headers which are intended to be C-compatible shall use only /**/-style comments. (Code examples nested inside documentation comments may use //-style comments.) Headers which are C++-compatible may also use //-style comments.
|
||||
|
||||
Non-interface comments that are /**/-style shall not also be doxygen-style.
|
||||
|
||||
Use Python-style ** to denote exponentiation inside comments, not ^ (which can be confused with C-style bitwise xor). If you're writing sufficiently complex math, feel free to descend into LaTeX math mode ;-) inside implementation comments if you need to. (But keep it out of interface comments, because most people probably haven't seen LaTeX.)
|
||||
|
||||
== Miscellaneous ==
|
||||
|
||||
Enclose C-compatible code in |extern "C"| blocks, and #ifdef __cplusplus the block start/end as needed. The contents of these blocks should not be indented.
|
||||
|
||||
Add new functionality to new headers unless an existing header makes sense. Err on the side of more headers rather than fewer, as this helps to minimize dependencies. Don't add anything to Util.h, which will be split into multiple headers at some point (bug 713082).
|
||||
|
||||
Don't use bool for argument types unless the method is a "set" or "enable"-style method where the method name and bool value together indicate the sense of its effect. Use well-named enums in all other places, so that the semantics of the argument are clear at a glance and do not require knowing how the method interprets that argument.
|
||||
|
||||
void
|
||||
setVisible(bool visible); // true clearly means visible, false clearly not
|
||||
enum Enumerability {
|
||||
Enumerable,
|
||||
NonEnumerable
|
||||
};
|
||||
bool
|
||||
DefineProperty(JSObject* obj, const char* name, Value v, Enumerability e);
|
||||
|
||||
Use NULL for the null pointer constant.
|
|
@ -202,6 +202,7 @@ public class AwesomeBarTabs extends TabHost {
|
|||
private static final int VIEW_TYPE_COUNT = 2;
|
||||
|
||||
private LayoutInflater mInflater;
|
||||
private Resources mResources;
|
||||
private LinkedList<Pair<Integer, String>> mParentStack;
|
||||
private RefreshBookmarkCursorTask mRefreshTask = null;
|
||||
private TextView mBookmarksTitleView;
|
||||
|
@ -210,6 +211,7 @@ public class AwesomeBarTabs extends TabHost {
|
|||
super(context, layout, c, from, to);
|
||||
|
||||
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mResources = mContext.getResources();
|
||||
|
||||
// mParentStack holds folder id/title pairs that allow us to navigate
|
||||
// back up the folder heirarchy
|
||||
|
@ -268,6 +270,24 @@ public class AwesomeBarTabs extends TabHost {
|
|||
if (!c.moveToPosition(position))
|
||||
return "";
|
||||
|
||||
String guid = c.getString(c.getColumnIndexOrThrow(Bookmarks.GUID));
|
||||
|
||||
// If we don't have a special GUID, just return the folder title from the DB.
|
||||
if (guid == null || guid.length() == 12)
|
||||
return c.getString(c.getColumnIndexOrThrow(Bookmarks.TITLE));
|
||||
|
||||
// Use localized strings for special folder names.
|
||||
if (guid.equals(Bookmarks.MOBILE_FOLDER_GUID))
|
||||
return mResources.getString(R.string.bookmarks_folder_mobile);
|
||||
else if (guid.equals(Bookmarks.MENU_FOLDER_GUID))
|
||||
return mResources.getString(R.string.bookmarks_folder_menu);
|
||||
else if (guid.equals(Bookmarks.TOOLBAR_FOLDER_GUID))
|
||||
return mResources.getString(R.string.bookmarks_folder_toolbar);
|
||||
else if (guid.equals(Bookmarks.UNFILED_FOLDER_GUID))
|
||||
return mResources.getString(R.string.bookmarks_folder_unfiled);
|
||||
|
||||
// If for some reason we have a folder with a special GUID, but it's not one of
|
||||
// the special folders we expect in the UI, just return the title from the DB.
|
||||
return c.getString(c.getColumnIndexOrThrow(Bookmarks.TITLE));
|
||||
}
|
||||
|
||||
|
|
|
@ -300,7 +300,7 @@ public class BrowserToolbar extends LinearLayout {
|
|||
}
|
||||
|
||||
public void setFavicon(Drawable image) {
|
||||
if (Tabs.getInstance().getSelectedTab().isLoading())
|
||||
if (Tabs.getInstance().getSelectedTab().getState() == Tab.STATE_LOADING)
|
||||
return;
|
||||
|
||||
if (image != null)
|
||||
|
@ -343,7 +343,7 @@ public class BrowserToolbar extends LinearLayout {
|
|||
setTitle(tab.getDisplayTitle());
|
||||
setFavicon(tab.getFavicon());
|
||||
setSecurityMode(tab.getSecurityMode());
|
||||
setProgressVisibility(tab.isLoading());
|
||||
setProgressVisibility(tab.getState() == Tab.STATE_LOADING);
|
||||
setShadowVisibility((url == null) || !url.startsWith("about:"));
|
||||
updateTabCount(Tabs.getInstance().getCount());
|
||||
}
|
||||
|
|
|
@ -610,7 +610,7 @@ abstract public class GeckoApp
|
|||
bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
|
||||
processThumbnail(tab, bitmap, bos.toByteArray());
|
||||
} else {
|
||||
if (!tab.hasLoaded()) {
|
||||
if (tab.getState() == Tab.STATE_DELAYED) {
|
||||
byte[] thumbnail = BrowserDB.getThumbnailForUrl(getContentResolver(), tab.getURL());
|
||||
if (thumbnail != null)
|
||||
processThumbnail(tab, null, thumbnail);
|
||||
|
@ -783,7 +783,7 @@ abstract public class GeckoApp
|
|||
mBrowserToolbar.setTitle(tab.getDisplayTitle());
|
||||
mBrowserToolbar.setFavicon(tab.getFavicon());
|
||||
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
|
||||
mBrowserToolbar.setProgressVisibility(tab.isLoading());
|
||||
mBrowserToolbar.setProgressVisibility(tab.getState() == Tab.STATE_LOADING);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -925,6 +925,7 @@ abstract public class GeckoApp
|
|||
handleSecurityChange(tabId, mode);
|
||||
} else if (event.equals("Content:StateChange")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
final boolean success = message.getBoolean("success");
|
||||
int state = message.getInt("state");
|
||||
Log.i(LOGTAG, "State - " + state);
|
||||
if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
|
||||
|
@ -934,7 +935,7 @@ abstract public class GeckoApp
|
|||
handleDocumentStart(tabId, showProgress);
|
||||
} else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
|
||||
Log.i(LOGTAG, "Got a document stop");
|
||||
handleDocumentStop(tabId);
|
||||
handleDocumentStop(tabId, success);
|
||||
}
|
||||
}
|
||||
} else if (event.equals("Content:LoadError")) {
|
||||
|
@ -972,6 +973,13 @@ abstract public class GeckoApp
|
|||
mBrowserToolbar.show();
|
||||
}
|
||||
});
|
||||
} else if (event.equals("ToggleChrome:Focus")) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mBrowserToolbar.setVisibility(View.VISIBLE);
|
||||
mBrowserToolbar.requestFocusFromTouch();
|
||||
}
|
||||
});
|
||||
} else if (event.equals("DOMFullScreen:Start")) {
|
||||
mDOMFullScreen = true;
|
||||
} else if (event.equals("DOMFullScreen:Stop")) {
|
||||
|
@ -1218,7 +1226,7 @@ abstract public class GeckoApp
|
|||
if (tab == null)
|
||||
return;
|
||||
|
||||
tab.setLoading(true);
|
||||
tab.setState(Tab.STATE_LOADING);
|
||||
tab.updateSecurityMode("unknown");
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
|
@ -1233,12 +1241,12 @@ abstract public class GeckoApp
|
|||
});
|
||||
}
|
||||
|
||||
void handleDocumentStop(int tabId) {
|
||||
void handleDocumentStop(int tabId, boolean success) {
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
tab.setLoading(false);
|
||||
tab.setState(success ? Tab.STATE_SUCCESS : Tab.STATE_ERROR);
|
||||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
|
@ -1273,7 +1281,6 @@ abstract public class GeckoApp
|
|||
return;
|
||||
|
||||
tab.updateTitle(title);
|
||||
tab.setHasLoaded(true);
|
||||
|
||||
// Make the UI changes
|
||||
mMainHandler.post(new Runnable() {
|
||||
|
@ -1314,7 +1321,7 @@ abstract public class GeckoApp
|
|||
// want to load the image straight away. If tab is still
|
||||
// loading, we only load the favicon once the page's content
|
||||
// is fully loaded (see handleContentLoaded()).
|
||||
if (!tab.isLoading()) {
|
||||
if (tab.getState() != tab.STATE_LOADING) {
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
loadFavicon(tab);
|
||||
|
@ -1644,6 +1651,7 @@ abstract public class GeckoApp
|
|||
mInitialized = true;
|
||||
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
String args = intent.getStringExtra("args");
|
||||
if (args != null && args.contains("-profile")) {
|
||||
Pattern p = Pattern.compile("(?:-profile\\s*)(\\w*)(\\s*)");
|
||||
|
@ -1656,7 +1664,7 @@ abstract public class GeckoApp
|
|||
}
|
||||
}
|
||||
|
||||
if (ACTION_UPDATE.equals(intent.getAction()) || args != null && args.contains("-alert update-app")) {
|
||||
if (ACTION_UPDATE.equals(action) || args != null && args.contains("-alert update-app")) {
|
||||
Log.i(LOGTAG,"onCreate: Update request");
|
||||
checkAndLaunchUpdate();
|
||||
}
|
||||
|
@ -1697,9 +1705,20 @@ abstract public class GeckoApp
|
|||
}
|
||||
|
||||
sGeckoThread = new GeckoThread(intent, passedUri, mRestoreSession);
|
||||
if (!ACTION_DEBUG.equals(intent.getAction()) &&
|
||||
checkAndSetLaunchState(LaunchState.Launching, LaunchState.Launched))
|
||||
if (!ACTION_DEBUG.equals(action) &&
|
||||
checkAndSetLaunchState(LaunchState.Launching, LaunchState.Launched)) {
|
||||
sGeckoThread.start();
|
||||
} else if (ACTION_DEBUG.equals(action) &&
|
||||
checkAndSetLaunchState(LaunchState.Launching, LaunchState.WaitForDebugger)) {
|
||||
mMainHandler.postDelayed(new Runnable() {
|
||||
public void run() {
|
||||
Log.i(LOGTAG, "Launching from debug intent after 5s wait");
|
||||
setLaunchState(LaunchState.Launching);
|
||||
sGeckoThread.start();
|
||||
}
|
||||
}, 1000 * 5 /* 5 seconds */);
|
||||
Log.i(LOGTAG, "Intent : ACTION_DEBUG - waiting 5s before launching");
|
||||
}
|
||||
|
||||
mFavicons = new Favicons(this);
|
||||
|
||||
|
@ -1776,6 +1795,7 @@ abstract public class GeckoApp
|
|||
GeckoAppShell.registerGeckoEventListener("DOMFullScreen:Stop", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("ToggleChrome:Focus", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("Downloads:Done", GeckoApp.mAppContext);
|
||||
GeckoAppShell.registerGeckoEventListener("CharEncoding:Data", GeckoApp.mAppContext);
|
||||
|
@ -1946,6 +1966,10 @@ abstract public class GeckoApp
|
|||
return;
|
||||
}
|
||||
|
||||
// don't perform any actions if launching from recent apps
|
||||
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0)
|
||||
return;
|
||||
|
||||
if (checkLaunchState(LaunchState.Launched)) {
|
||||
Uri data = intent.getData();
|
||||
Bundle bundle = intent.getExtras();
|
||||
|
@ -2148,6 +2172,7 @@ abstract public class GeckoApp
|
|||
GeckoAppShell.unregisterGeckoEventListener("Toast:Show", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Focus", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Permissions:Data", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Downloads:Done", GeckoApp.mAppContext);
|
||||
GeckoAppShell.unregisterGeckoEventListener("CharEncoding:Data", GeckoApp.mAppContext);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче