Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2012-03-08 13:14:47 +00:00
Родитель 96cfa44876 397e0b591e
Коммит 214e82db8b
125 изменённых файлов: 3197 добавлений и 1386 удалений

Просмотреть файл

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

Просмотреть файл

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

21
dom/power/Types.h Normal file
Просмотреть файл

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

204
dom/power/WakeLock.cpp Normal file
Просмотреть файл

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

53
dom/power/WakeLock.h Normal file
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

125
hal/HalWakeLock.cpp Normal file
Просмотреть файл

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

26
hal/HalWakeLock.h Normal file
Просмотреть файл

@ -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,&lt;svg xmlns='http://www.w3.org/2000/svg' id='root' /&gt;#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;

273
mfbt/STYLE Normal file
Просмотреть файл

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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше