зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c. a=merge
This commit is contained in:
Коммит
a33e05c88c
|
@ -163,22 +163,24 @@ getTextAfterOffsetCB(AtkText *aText, gint aOffset,
|
|||
AtkTextBoundary aBoundaryType,
|
||||
gint *aStartOffset, gint *aEndOffset)
|
||||
{
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
|
||||
if (!accWrap)
|
||||
return nullptr;
|
||||
|
||||
HyperTextAccessible* text = accWrap->AsHyperText();
|
||||
if (!text || !text->IsTextRole())
|
||||
return nullptr;
|
||||
|
||||
nsAutoString autoStr;
|
||||
nsAutoString autoStr;
|
||||
int32_t startOffset = 0, endOffset = 0;
|
||||
text->TextAfterOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
|
||||
if (accWrap) {
|
||||
HyperTextAccessible* text = accWrap->AsHyperText();
|
||||
if (!text || !text->IsTextRole())
|
||||
return nullptr;
|
||||
|
||||
text->TextAfterOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
|
||||
ConvertTexttoAsterisks(accWrap, autoStr);
|
||||
} else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
|
||||
proxy->GetTextAfterOffset(aOffset, aBoundaryType, autoStr, &startOffset,
|
||||
&endOffset);
|
||||
}
|
||||
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
|
||||
ConvertTexttoAsterisks(accWrap, autoStr);
|
||||
NS_ConvertUTF16toUTF8 cautoStr(autoStr);
|
||||
return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
|
||||
}
|
||||
|
@ -188,23 +190,26 @@ getTextAtOffsetCB(AtkText *aText, gint aOffset,
|
|||
AtkTextBoundary aBoundaryType,
|
||||
gint *aStartOffset, gint *aEndOffset)
|
||||
{
|
||||
nsAutoString autoStr;
|
||||
int32_t startOffset = 0, endOffset = 0;
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
|
||||
if (!accWrap)
|
||||
return nullptr;
|
||||
if (accWrap) {
|
||||
HyperTextAccessible* text = accWrap->AsHyperText();
|
||||
if (!text || !text->IsTextRole())
|
||||
return nullptr;
|
||||
|
||||
HyperTextAccessible* text = accWrap->AsHyperText();
|
||||
if (!text || !text->IsTextRole())
|
||||
return nullptr;
|
||||
|
||||
nsAutoString autoStr;
|
||||
int32_t startOffset = 0, endOffset = 0;
|
||||
text->TextAtOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
|
||||
ConvertTexttoAsterisks(accWrap, autoStr);
|
||||
NS_ConvertUTF16toUTF8 cautoStr(autoStr);
|
||||
return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
|
||||
} else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
|
||||
proxy->GetTextAtOffset(aOffset, aBoundaryType, autoStr, &startOffset,
|
||||
&endOffset);
|
||||
}
|
||||
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
|
||||
NS_ConvertUTF16toUTF8 cautoStr(autoStr);
|
||||
return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
|
||||
}
|
||||
|
||||
static gunichar
|
||||
|
@ -233,22 +238,25 @@ getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
|
|||
AtkTextBoundary aBoundaryType,
|
||||
gint *aStartOffset, gint *aEndOffset)
|
||||
{
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
|
||||
if (!accWrap)
|
||||
return nullptr;
|
||||
|
||||
HyperTextAccessible* text = accWrap->AsHyperText();
|
||||
if (!text || !text->IsTextRole())
|
||||
return nullptr;
|
||||
|
||||
nsAutoString autoStr;
|
||||
int32_t startOffset = 0, endOffset = 0;
|
||||
text->TextBeforeOffset(aOffset, aBoundaryType,
|
||||
&startOffset, &endOffset, autoStr);
|
||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
|
||||
if (accWrap) {
|
||||
HyperTextAccessible* text = accWrap->AsHyperText();
|
||||
if (!text || !text->IsTextRole())
|
||||
return nullptr;
|
||||
|
||||
text->TextBeforeOffset(aOffset, aBoundaryType,
|
||||
&startOffset, &endOffset, autoStr);
|
||||
ConvertTexttoAsterisks(accWrap, autoStr);
|
||||
} else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
|
||||
proxy->GetTextBeforeOffset(aOffset, aBoundaryType, autoStr, &startOffset,
|
||||
&endOffset);
|
||||
}
|
||||
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
|
||||
ConvertTexttoAsterisks(accWrap, autoStr);
|
||||
NS_ConvertUTF16toUTF8 cautoStr(autoStr);
|
||||
return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsITextControlElement.h"
|
||||
#include "nsIMathMLFrame.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "mozilla/BinarySearch.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
@ -952,6 +953,145 @@ HyperTextAccessible::GetLevelInternal()
|
|||
return AccessibleWrap::GetLevelInternal();
|
||||
}
|
||||
|
||||
void
|
||||
HyperTextAccessible::SetMathMLXMLRoles(nsIPersistentProperties* aAttributes)
|
||||
{
|
||||
// Add MathML xmlroles based on the position inside the parent.
|
||||
Accessible* parent = Parent();
|
||||
if (parent) {
|
||||
switch (parent->Role()) {
|
||||
case roles::MATHML_CELL:
|
||||
case roles::MATHML_ENCLOSED:
|
||||
case roles::MATHML_ERROR:
|
||||
case roles::MATHML_MATH:
|
||||
case roles::MATHML_ROW:
|
||||
case roles::MATHML_SQUARE_ROOT:
|
||||
case roles::MATHML_STYLE:
|
||||
if (Role() == roles::MATHML_OPERATOR) {
|
||||
// This is an operator inside an <mrow> (or an inferred <mrow>).
|
||||
// See http://www.w3.org/TR/MathML3/chapter3.html#presm.inferredmrow
|
||||
// XXX We should probably do something similar for MATHML_FENCED, but
|
||||
// operators do not appear in the accessible tree. See bug 1175747.
|
||||
nsIMathMLFrame* mathMLFrame = do_QueryFrame(GetFrame());
|
||||
if (mathMLFrame) {
|
||||
nsEmbellishData embellishData;
|
||||
mathMLFrame->GetEmbellishData(embellishData);
|
||||
if (NS_MATHML_EMBELLISH_IS_FENCE(embellishData.flags)) {
|
||||
if (!PrevSibling()) {
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
nsGkAtoms::open_fence);
|
||||
} else if (!NextSibling()) {
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
nsGkAtoms::close_fence);
|
||||
}
|
||||
}
|
||||
if (NS_MATHML_EMBELLISH_IS_SEPARATOR(embellishData.flags)) {
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
nsGkAtoms::separator_);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case roles::MATHML_FRACTION:
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
IndexInParent() == 0 ?
|
||||
nsGkAtoms::numerator :
|
||||
nsGkAtoms::denominator);
|
||||
break;
|
||||
case roles::MATHML_ROOT:
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
IndexInParent() == 0 ? nsGkAtoms::base :
|
||||
nsGkAtoms::root_index);
|
||||
break;
|
||||
case roles::MATHML_SUB:
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
IndexInParent() == 0 ? nsGkAtoms::base :
|
||||
nsGkAtoms::subscript);
|
||||
break;
|
||||
case roles::MATHML_SUP:
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
IndexInParent() == 0 ? nsGkAtoms::base :
|
||||
nsGkAtoms::superscript);
|
||||
break;
|
||||
case roles::MATHML_SUB_SUP: {
|
||||
int32_t index = IndexInParent();
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
index == 0 ? nsGkAtoms::base :
|
||||
(index == 1 ? nsGkAtoms::subscript :
|
||||
nsGkAtoms::superscript));
|
||||
} break;
|
||||
case roles::MATHML_UNDER:
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
IndexInParent() == 0 ? nsGkAtoms::base :
|
||||
nsGkAtoms::underscript);
|
||||
break;
|
||||
case roles::MATHML_OVER:
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
IndexInParent() == 0 ? nsGkAtoms::base :
|
||||
nsGkAtoms::overscript);
|
||||
break;
|
||||
case roles::MATHML_UNDER_OVER: {
|
||||
int32_t index = IndexInParent();
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
index == 0 ? nsGkAtoms::base :
|
||||
(index == 1 ? nsGkAtoms::underscript :
|
||||
nsGkAtoms::overscript));
|
||||
} break;
|
||||
case roles::MATHML_MULTISCRIPTS: {
|
||||
// Get the <multiscripts> base.
|
||||
nsIContent* child;
|
||||
bool baseFound = false;
|
||||
for (child = parent->GetContent()->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
if (child->IsMathMLElement()) {
|
||||
baseFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (baseFound) {
|
||||
nsIContent* content = GetContent();
|
||||
if (child == content) {
|
||||
// We are the base.
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
nsGkAtoms::base);
|
||||
} else {
|
||||
// Browse the list of scripts to find us and determine our type.
|
||||
bool postscript = true;
|
||||
bool subscript = true;
|
||||
for (child = child->GetNextSibling(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
if (!child->IsMathMLElement())
|
||||
continue;
|
||||
if (child->IsMathMLElement(nsGkAtoms::mprescripts_)) {
|
||||
postscript = false;
|
||||
subscript = true;
|
||||
continue;
|
||||
}
|
||||
if (child == content) {
|
||||
if (postscript) {
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
subscript ?
|
||||
nsGkAtoms::subscript :
|
||||
nsGkAtoms::superscript);
|
||||
} else {
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
subscript ?
|
||||
nsGkAtoms::presubscript :
|
||||
nsGkAtoms::presuperscript);
|
||||
}
|
||||
break;
|
||||
}
|
||||
subscript = !subscript;
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsIPersistentProperties>
|
||||
HyperTextAccessible::NativeAttributes()
|
||||
{
|
||||
|
@ -976,8 +1116,11 @@ HyperTextAccessible::NativeAttributes()
|
|||
}
|
||||
}
|
||||
|
||||
if (HasOwnContent())
|
||||
if (HasOwnContent()) {
|
||||
GetAccService()->MarkupAttributes(mContent, attributes);
|
||||
if (mContent->IsMathMLElement())
|
||||
SetMathMLXMLRoles(attributes);
|
||||
}
|
||||
|
||||
return attributes.forget();
|
||||
}
|
||||
|
|
|
@ -561,6 +561,12 @@ protected:
|
|||
uint32_t* aStartOffset, uint32_t* aEndOffset,
|
||||
nsIPersistentProperties* aAttributes);
|
||||
|
||||
/**
|
||||
* Set xml-roles attributes for MathML elements.
|
||||
* @param aAttributes
|
||||
*/
|
||||
void SetMathMLXMLRoles(nsIPersistentProperties* aAttributes);
|
||||
|
||||
private:
|
||||
/**
|
||||
* End text offsets array.
|
||||
|
|
|
@ -1652,6 +1652,24 @@ DocAccessibleChild::RecvEmbeddedChildAt(const uint64_t& aID,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvFocusedChild(const uint64_t& aID,
|
||||
uint64_t* aChild,
|
||||
bool* aOk)
|
||||
{
|
||||
*aChild = 0;
|
||||
*aOk = false;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
Accessible* child = acc->FocusedChild();
|
||||
if (child) {
|
||||
*aChild = reinterpret_cast<uint64_t>(child->UniqueID());
|
||||
*aOk = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvChildAtPoint(const uint64_t& aID,
|
||||
const int32_t& aX,
|
||||
|
|
|
@ -411,6 +411,10 @@ public:
|
|||
virtual bool RecvEmbeddedChildAt(const uint64_t& aID, const uint32_t& aIdx,
|
||||
uint64_t* aChildID) override final;
|
||||
|
||||
virtual bool RecvFocusedChild(const uint64_t& aID,
|
||||
uint64_t* aChild,
|
||||
bool* aOk) override;
|
||||
|
||||
virtual bool RecvChildAtPoint(const uint64_t& aID,
|
||||
const int32_t& aX,
|
||||
const int32_t& aY,
|
||||
|
|
|
@ -222,6 +222,8 @@ child:
|
|||
returns(uint32_t childIdx);
|
||||
prio(high) sync EmbeddedChildAt(uint64_t aID, uint32_t aChildIdx)
|
||||
returns(uint64_t aChild);
|
||||
prio(high) sync FocusedChild(uint64_t aID)
|
||||
returns(uint64_t aChild, bool aOk);
|
||||
prio(high) sync ChildAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aWhich)
|
||||
returns(uint64_t aChild, bool aOk);
|
||||
prio(high) sync Bounds(uint64_t aID) returns(nsIntRect aRect);
|
||||
|
|
|
@ -520,15 +520,27 @@ ProxyAccessible::RowExtent()
|
|||
}
|
||||
|
||||
void
|
||||
ProxyAccessible::ColHeaderCells(nsTArray<uint64_t>* aCells)
|
||||
ProxyAccessible::ColHeaderCells(nsTArray<ProxyAccessible*>* aCells)
|
||||
{
|
||||
unused << mDoc->SendColHeaderCells(mID, aCells);
|
||||
nsTArray<uint64_t> targetIDs;
|
||||
unused << mDoc->SendColHeaderCells(mID, &targetIDs);
|
||||
|
||||
size_t targetCount = targetIDs.Length();
|
||||
for (size_t i = 0; i < targetCount; i++) {
|
||||
aCells->AppendElement(mDoc->GetAccessible(targetIDs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProxyAccessible::RowHeaderCells(nsTArray<uint64_t>* aCells)
|
||||
ProxyAccessible::RowHeaderCells(nsTArray<ProxyAccessible*>* aCells)
|
||||
{
|
||||
unused << mDoc->SendRowHeaderCells(mID, aCells);
|
||||
nsTArray<uint64_t> targetIDs;
|
||||
unused << mDoc->SendRowHeaderCells(mID, &targetIDs);
|
||||
|
||||
size_t targetCount = targetIDs.Length();
|
||||
for (size_t i = 0; i < targetCount; i++) {
|
||||
aCells->AppendElement(mDoc->GetAccessible(targetIDs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -924,6 +936,15 @@ ProxyAccessible::EmbeddedChildAt(size_t aChildIdx)
|
|||
return mDoc->GetAccessible(childID);
|
||||
}
|
||||
|
||||
ProxyAccessible*
|
||||
ProxyAccessible::FocusedChild()
|
||||
{
|
||||
uint64_t childID = 0;
|
||||
bool ok = false;
|
||||
unused << mDoc->SendFocusedChild(mID, &childID, &ok);
|
||||
return ok ? mDoc->GetAccessible(childID) : nullptr;
|
||||
}
|
||||
|
||||
ProxyAccessible*
|
||||
ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY,
|
||||
Accessible::EWhichChildAtPoint aWhichChild)
|
||||
|
|
|
@ -194,6 +194,12 @@ public:
|
|||
|
||||
bool IsLinkValid();
|
||||
|
||||
// XXX checking mRole alone may not result in same behavior as Accessibles
|
||||
// due to ARIA roles
|
||||
inline bool IsTable() const { return mRole == roles::TABLE; }
|
||||
inline bool IsTableRow() const { return mRole == roles::ROW; }
|
||||
inline bool IsTableCell() const { return mRole == roles::CELL; }
|
||||
|
||||
uint32_t AnchorCount(bool* aOk);
|
||||
|
||||
void AnchorURIAt(uint32_t aIndex, nsCString& aURI, bool* aOk);
|
||||
|
@ -218,9 +224,9 @@ public:
|
|||
|
||||
uint32_t RowExtent();
|
||||
|
||||
void ColHeaderCells(nsTArray<uint64_t>* aCells);
|
||||
void ColHeaderCells(nsTArray<ProxyAccessible*>* aCells);
|
||||
|
||||
void RowHeaderCells(nsTArray<uint64_t>* aCells);
|
||||
void RowHeaderCells(nsTArray<ProxyAccessible*>* aCells);
|
||||
|
||||
bool IsCellSelected();
|
||||
|
||||
|
@ -277,6 +283,7 @@ public:
|
|||
double Step();
|
||||
|
||||
void TakeFocus();
|
||||
ProxyAccessible* FocusedChild();
|
||||
ProxyAccessible* ChildAtPoint(int32_t aX, int32_t aY,
|
||||
Accessible::EWhichChildAtPoint aWhichChild);
|
||||
nsIntRect Bounds();
|
||||
|
|
|
@ -40,4 +40,6 @@ LOCAL_INCLUDES += [
|
|||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "RootAccessible.h"
|
||||
#include "TableAccessible.h"
|
||||
#include "TableCellAccessible.h"
|
||||
#include "mozilla/a11y/PDocAccessible.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsRect.h"
|
||||
|
@ -211,9 +212,14 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
// unknown (either unimplemented, or irrelevant) elements are marked as ignored
|
||||
// as well as expired elements.
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
return !accWrap || ([[self role] isEqualToString:NSAccessibilityUnknownRole] &&
|
||||
!(accWrap->InteractiveState() & states::FOCUSABLE));
|
||||
bool noRole = [[self role] isEqualToString:NSAccessibilityUnknownRole];
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
|
||||
return (noRole && !(accWrap->InteractiveState() & states::FOCUSABLE));
|
||||
|
||||
if (ProxyAccessible* proxy = [self getProxyAccessible])
|
||||
return (noRole && !(proxy->State() & states::FOCUSABLE));
|
||||
|
||||
return true;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
||||
}
|
||||
|
@ -269,7 +275,8 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
|
||||
// if we're expired, we don't support any attributes.
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
if (!accWrap)
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy)
|
||||
return [NSArray array];
|
||||
|
||||
static NSArray* generalAttributes = nil;
|
||||
|
@ -328,11 +335,11 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
|
||||
NSArray* objectAttributes = generalAttributes;
|
||||
|
||||
if (accWrap->IsTable())
|
||||
if ((accWrap && accWrap->IsTable()) || (proxy && proxy->IsTable()))
|
||||
objectAttributes = tableAttrs;
|
||||
else if (accWrap->IsTableRow())
|
||||
else if ((accWrap && accWrap->IsTableRow()) || (proxy && proxy->IsTableRow()))
|
||||
objectAttributes = tableRowAttrs;
|
||||
else if (accWrap->IsTableCell())
|
||||
else if ((accWrap && accWrap->IsTableCell()) || (proxy && proxy->IsTableCell()))
|
||||
objectAttributes = tableCellAttrs;
|
||||
|
||||
NSArray* additionalAttributes = [self additionalAccessibilityAttributeNames];
|
||||
|
@ -364,7 +371,8 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
if (!accWrap)
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy)
|
||||
return nil;
|
||||
|
||||
#if DEBUG
|
||||
|
@ -406,62 +414,117 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
|
||||
return [self title];
|
||||
if ([attribute isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
|
||||
Relation rel =
|
||||
accWrap->RelationByType(RelationType::LABELLED_BY);
|
||||
Accessible* tempAcc = rel.Next();
|
||||
return tempAcc ? GetNativeFromGeckoAccessible(tempAcc) : nil;
|
||||
if (accWrap) {
|
||||
Relation rel = accWrap->RelationByType(RelationType::LABELLED_BY);
|
||||
Accessible* tempAcc = rel.Next();
|
||||
return tempAcc ? GetNativeFromGeckoAccessible(tempAcc) : nil;
|
||||
}
|
||||
nsTArray<ProxyAccessible*> rel = proxy->RelationByType(RelationType::LABELLED_BY);
|
||||
ProxyAccessible* tempProxy = rel.SafeElementAt(0);
|
||||
return tempProxy ? GetNativeFromProxy(tempProxy) : nil;
|
||||
}
|
||||
if ([attribute isEqualToString:NSAccessibilityHelpAttribute])
|
||||
return [self help];
|
||||
|
||||
if (accWrap->IsTable()) {
|
||||
TableAccessible* table = accWrap->AsTable();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
|
||||
return @(table->RowCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
|
||||
return @(table->ColCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
|
||||
// Create a new array with the list of table rows.
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
uint32_t totalCount = accWrap->ChildCount();
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
if (accWrap->GetChildAt(i)->IsTableRow()) {
|
||||
mozAccessible* curNative =
|
||||
GetNativeFromGeckoAccessible(accWrap->GetChildAt(i));
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
if (accWrap) {
|
||||
if (accWrap->IsTable()) {
|
||||
TableAccessible* table = accWrap->AsTable();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
|
||||
return @(table->RowCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
|
||||
return @(table->ColCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
|
||||
// Create a new array with the list of table rows.
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
uint32_t totalCount = accWrap->ChildCount();
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
if (accWrap->GetChildAt(i)->IsTableRow()) {
|
||||
mozAccessible* curNative =
|
||||
GetNativeFromGeckoAccessible(accWrap->GetChildAt(i));
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
}
|
||||
return nativeArray;
|
||||
}
|
||||
return nativeArray;
|
||||
}
|
||||
} else if (accWrap->IsTableRow()) {
|
||||
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
|
||||
// Count the number of rows before that one to obtain the row index.
|
||||
uint32_t index = 0;
|
||||
for (int32_t i = accWrap->IndexInParent() - 1; i >= 0; i--) {
|
||||
if (accWrap->GetChildAt(i)->IsTableRow()) {
|
||||
index++;
|
||||
} else if (accWrap->IsTableRow()) {
|
||||
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
|
||||
// Count the number of rows before that one to obtain the row index.
|
||||
uint32_t index = 0;
|
||||
for (int32_t i = accWrap->IndexInParent() - 1; i >= 0; i--) {
|
||||
if (accWrap->GetChildAt(i)->IsTableRow()) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return [NSNumber numberWithUnsignedInteger:index];
|
||||
}
|
||||
} else if (accWrap->IsTableCell()) {
|
||||
TableCellAccessible* cell = accWrap->AsTableCell();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->RowIdx(),
|
||||
cell->RowExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->ColIdx(),
|
||||
cell->ColExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
|
||||
nsAutoTArray<Accessible*, 10> headerCells;
|
||||
cell->RowHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
|
||||
nsAutoTArray<Accessible*, 10> headerCells;
|
||||
cell->ColHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
return [NSNumber numberWithUnsignedInteger:index];
|
||||
}
|
||||
} else if (accWrap->IsTableCell()) {
|
||||
TableCellAccessible* cell = accWrap->AsTableCell();
|
||||
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->RowIdx(),
|
||||
cell->RowExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(cell->ColIdx(),
|
||||
cell->ColExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
|
||||
nsAutoTArray<Accessible*, 10> headerCells;
|
||||
cell->RowHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
|
||||
nsAutoTArray<Accessible*, 10> headerCells;
|
||||
cell->ColHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
} else if (proxy) {
|
||||
if (proxy->IsTable()) {
|
||||
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
|
||||
return @(proxy->TableRowCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
|
||||
return @(proxy->TableColumnCount());
|
||||
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
|
||||
// Create a new array with the list of table rows.
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
uint32_t totalCount = proxy->ChildrenCount();
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
if (proxy->ChildAt(i)->IsTableRow()) {
|
||||
mozAccessible* curNative =
|
||||
GetNativeFromProxy(proxy->ChildAt(i));
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
}
|
||||
return nativeArray;
|
||||
}
|
||||
} else if (proxy->IsTableRow()) {
|
||||
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
|
||||
// Count the number of rows before that one to obtain the row index.
|
||||
uint32_t index = 0;
|
||||
for (int32_t i = proxy->IndexInParent() - 1; i >= 0; i--) {
|
||||
if (proxy->ChildAt(i)->IsTableRow()) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return [NSNumber numberWithUnsignedInteger:index];
|
||||
}
|
||||
} else if (proxy->IsTableCell()) {
|
||||
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->RowIdx(),
|
||||
proxy->RowExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
|
||||
return [NSValue valueWithRange:NSMakeRange(proxy->ColIdx(),
|
||||
proxy->ColExtent())];
|
||||
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
|
||||
nsTArray<ProxyAccessible*> headerCells;
|
||||
proxy->RowHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
if ([attribute isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
|
||||
nsTArray<ProxyAccessible*> headerCells;
|
||||
proxy->ColHeaderCells(&headerCells);
|
||||
return ConvertToNSArray(headerCells);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,9 +553,20 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
// Per the MathML 3 spec, the latter happens iff the linethickness
|
||||
// attribute is of the form [zero-float][optional-unit]. In that case we
|
||||
// set line thickness to zero and in the other cases we set it to one.
|
||||
nsCOMPtr<nsIPersistentProperties> attributes = accWrap->Attributes();
|
||||
nsAutoString thickness;
|
||||
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::linethickness_, thickness);
|
||||
if (accWrap) {
|
||||
nsCOMPtr<nsIPersistentProperties> attributes = accWrap->Attributes();
|
||||
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::linethickness_, thickness);
|
||||
} else {
|
||||
nsAutoTArray<Attribute, 10> attrs;
|
||||
proxy->Attributes(&attrs);
|
||||
for (size_t i = 0 ; i < attrs.Length() ; i++) {
|
||||
if (attrs.ElementAt(i).Name() == "thickness") {
|
||||
thickness = attrs.ElementAt(i).Value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
double value = 1.0;
|
||||
if (!thickness.IsEmpty())
|
||||
value = PR_strtod(NS_LossyConvertUTF16toASCII(thickness).get(),
|
||||
|
@ -606,7 +680,8 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
- (id)accessibilityHitTest:(NSPoint)point
|
||||
{
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
if (!accWrap)
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy)
|
||||
return nil;
|
||||
|
||||
// Convert the given screen-global point in the cocoa coordinate system (with
|
||||
|
@ -618,16 +693,22 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
nsIntPoint geckoPoint = nsCocoaUtils::
|
||||
CocoaPointsToDevPixels(tmpPoint, nsCocoaUtils::GetBackingScaleFactor(mainView));
|
||||
|
||||
Accessible* child =
|
||||
accWrap->ChildAtPoint(geckoPoint.x, geckoPoint.y,
|
||||
Accessible::eDeepestChild);
|
||||
|
||||
if (child) {
|
||||
mozAccessible* nativeChild = GetNativeFromGeckoAccessible(child);
|
||||
if (nativeChild)
|
||||
return GetClosestInterestingAccessible(nativeChild);
|
||||
mozAccessible* nativeChild = nil;
|
||||
if (accWrap) {
|
||||
Accessible* child = accWrap->ChildAtPoint(geckoPoint.x, geckoPoint.y,
|
||||
Accessible::eDeepestChild);
|
||||
if (child)
|
||||
nativeChild = GetNativeFromGeckoAccessible(child);
|
||||
} else if (proxy) {
|
||||
ProxyAccessible* child = proxy->ChildAtPoint(geckoPoint.x, geckoPoint.y,
|
||||
Accessible::eDeepestChild);
|
||||
if (child)
|
||||
nativeChild = GetNativeFromProxy(child);
|
||||
}
|
||||
|
||||
if (nativeChild)
|
||||
return GetClosestInterestingAccessible(nativeChild);
|
||||
|
||||
// if we didn't find anything, return ourself (or the first unignored ancestor).
|
||||
return GetClosestInterestingAccessible(self);
|
||||
}
|
||||
|
@ -651,16 +732,24 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
|||
- (id)accessibilityFocusedUIElement
|
||||
{
|
||||
AccessibleWrap* accWrap = [self getGeckoAccessible];
|
||||
if (!accWrap)
|
||||
ProxyAccessible* proxy = [self getProxyAccessible];
|
||||
if (!accWrap && !proxy)
|
||||
return nil;
|
||||
|
||||
Accessible* focusedGeckoChild = accWrap->FocusedChild();
|
||||
if (focusedGeckoChild) {
|
||||
mozAccessible *focusedChild = GetNativeFromGeckoAccessible(focusedGeckoChild);
|
||||
if (focusedChild)
|
||||
return GetClosestInterestingAccessible(focusedChild);
|
||||
mozAccessible* focusedChild = nil;
|
||||
if (accWrap) {
|
||||
Accessible* focusedGeckoChild = accWrap->FocusedChild();
|
||||
if (focusedGeckoChild)
|
||||
focusedChild = GetNativeFromGeckoAccessible(focusedGeckoChild);
|
||||
} else if (proxy) {
|
||||
ProxyAccessible* focusedGeckoChild = proxy->FocusedChild();
|
||||
if (focusedGeckoChild)
|
||||
focusedChild = GetNativeFromProxy(focusedGeckoChild);
|
||||
}
|
||||
|
||||
if (focusedChild)
|
||||
return GetClosestInterestingAccessible(focusedChild);
|
||||
|
||||
// return ourself if we can't get a native focused child.
|
||||
return GetClosestInterestingAccessible(self);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ enum CheckboxValue {
|
|||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
return ![self getGeckoAccessible];
|
||||
return ![self getGeckoAccessible] && ![self getProxyAccessible];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityActionNames
|
||||
|
|
|
@ -55,7 +55,7 @@ ToNSString(id aValue)
|
|||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
return ![self getGeckoAccessible];
|
||||
return ![self getGeckoAccessible] && ![self getProxyAccessible];
|
||||
}
|
||||
|
||||
- (NSArray*)accessibilityAttributeNames
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>XML landmark tests</title>
|
||||
<title>XML roles tests</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
|
@ -36,6 +36,60 @@
|
|||
|
||||
testAttrs("search", {"xml-roles" : "searchbox"}, true);
|
||||
|
||||
testAttrs("open-1", {"xml-roles" : "open-fence"}, true);
|
||||
testAttrs("open-2", {"xml-roles" : "open-fence"}, true);
|
||||
testAttrs("open-3", {"xml-roles" : "open-fence"}, true);
|
||||
testAttrs("open-4", {"xml-roles" : "open-fence"}, true);
|
||||
testAttrs("open-5", {"xml-roles" : "open-fence"}, true);
|
||||
testAttrs("open-6", {"xml-roles" : "open-fence"}, true);
|
||||
testAttrs("open-7", {"xml-roles" : "open-fence"}, true);
|
||||
|
||||
testAttrs("sep-1", {"xml-roles" : "separator"}, true);
|
||||
testAttrs("sep-2", {"xml-roles" : "separator"}, true);
|
||||
testAttrs("sep-3", {"xml-roles" : "separator"}, true);
|
||||
testAttrs("sep-4", {"xml-roles" : "separator"}, true);
|
||||
testAttrs("sep-5", {"xml-roles" : "separator"}, true);
|
||||
testAttrs("sep-6", {"xml-roles" : "separator"}, true);
|
||||
testAttrs("sep-7", {"xml-roles" : "separator"}, true);
|
||||
|
||||
testAttrs("close-1", {"xml-roles" : "close-fence"}, true);
|
||||
testAttrs("close-2", {"xml-roles" : "close-fence"}, true);
|
||||
testAttrs("close-3", {"xml-roles" : "close-fence"}, true);
|
||||
testAttrs("close-4", {"xml-roles" : "close-fence"}, true);
|
||||
testAttrs("close-5", {"xml-roles" : "close-fence"}, true);
|
||||
testAttrs("close-6", {"xml-roles" : "close-fence"}, true);
|
||||
testAttrs("close-7", {"xml-roles" : "close-fence"}, true);
|
||||
|
||||
testAttrs("num", {"xml-roles" : "numerator"}, true);
|
||||
testAttrs("den", {"xml-roles" : "denominator"}, true);
|
||||
|
||||
testAttrs("sub-1", {"xml-roles" : "subscript"}, true);
|
||||
testAttrs("sub-2", {"xml-roles" : "subscript"}, true);
|
||||
testAttrs("sub-3", {"xml-roles" : "subscript"}, true);
|
||||
testAttrs("sup-1", {"xml-roles" : "superscript"}, true);
|
||||
testAttrs("sup-2", {"xml-roles" : "superscript"}, true);
|
||||
testAttrs("sup-3", {"xml-roles" : "superscript"}, true);
|
||||
testAttrs("sup-4", {"xml-roles" : "superscript"}, true);
|
||||
testAttrs("presub-1", {"xml-roles" : "presubscript"}, true);
|
||||
testAttrs("presub-2", {"xml-roles" : "presubscript"}, true);
|
||||
testAttrs("presup-1", {"xml-roles" : "presuperscript"}, true);
|
||||
|
||||
testAttrs("under-1", {"xml-roles" : "underscript"}, true);
|
||||
testAttrs("under-2", {"xml-roles" : "underscript"}, true);
|
||||
testAttrs("over-1", {"xml-roles" : "overscript"}, true);
|
||||
testAttrs("over-2", {"xml-roles" : "overscript"}, true);
|
||||
|
||||
testAttrs("root-index-1", {"xml-roles" : "root-index"}, true);
|
||||
|
||||
testAttrs("base-1", {"xml-roles" : "base"}, true);
|
||||
testAttrs("base-2", {"xml-roles" : "base"}, true);
|
||||
testAttrs("base-3", {"xml-roles" : "base"}, true);
|
||||
testAttrs("base-4", {"xml-roles" : "base"}, true);
|
||||
testAttrs("base-5", {"xml-roles" : "base"}, true);
|
||||
testAttrs("base-6", {"xml-roles" : "base"}, true);
|
||||
testAttrs("base-7", {"xml-roles" : "base"}, true);
|
||||
testAttrs("base-8", {"xml-roles" : "base"}, true);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -109,5 +163,87 @@
|
|||
<main id="main_element">another main area</main>
|
||||
|
||||
<input id="search" type="search"/>
|
||||
|
||||
<!-- open-fence, separator, close-fence -->
|
||||
<math><mo id="open-1">(</mo><mi>x</mi><mo id="sep-1">,</mo><mi>y</mi><mo id="close-1">)</mo></math>
|
||||
<math><mrow><mo id="open-2">(</mo><mi>x</mi><mo id="sep-2">,</mo><mi>y</mi><mo id="close-2">)</mo></mrow></math>
|
||||
<math><mstyle><mo id="open-3">(</mo><mi>x</mi><mo id="sep-3">,</mo><mi>y</mi><mo id="close-3">)</mo></mstyle></math>
|
||||
<math><msqrt><mo id="open-4">(</mo><mi>x</mi><mo id="sep-4">,</mo><mi>y</mi><mo id="close-4">)</mo></msqrt></math>
|
||||
<math><menclose><mo id="open-5">(</mo><mi>x</mi><mo id="sep-5">,</mo><mi>y</mi><mo id="close-5">)</mo></menclose></math>
|
||||
<math><merror><mo id="open-6">(</mo><mi>x</mi><mo id="sep-6">,</mo><mi>y</mi><mo id="close-6">)</mo></merror></math>
|
||||
<math><mtable><mtr><mtd><mo id="open-7">(</mo><mi>x</mi><mo id="sep-7">,</mo><mi>y</mi><mo id="close-7">)</mo></mtd></mtr></mtable></math>
|
||||
|
||||
<!-- numerator, denominator -->
|
||||
<math>
|
||||
<mfrac>
|
||||
<mi id="num">a</mi>
|
||||
<mi id="den">b</mi>
|
||||
</mfrac>
|
||||
</math>
|
||||
|
||||
<!-- subscript, superscript, presubscript, presuperscript -->
|
||||
<math>
|
||||
<msub>
|
||||
<mi id="base-1">a</mi>
|
||||
<mi id="sub-1">b</mi>
|
||||
</msub>
|
||||
</math>
|
||||
<math>
|
||||
<msup>
|
||||
<mi id="base-2">a</mi>
|
||||
<mi id="sup-1">b</mi>
|
||||
</msup>
|
||||
</math>
|
||||
<math>
|
||||
<msubsup>
|
||||
<mi id="base-3">a</mi>
|
||||
<mi id="sub-2">b</mi>
|
||||
<mi id="sup-2">c</mi>
|
||||
</msubsup>
|
||||
</math>
|
||||
<math>
|
||||
<mmultiscripts>
|
||||
<mi id="base-4">a</mi>
|
||||
<mi id="sub-3">b</mi>
|
||||
<mi id="sup-3">c</mi>
|
||||
<none/>
|
||||
<mi id="sup-4">d</mi>
|
||||
<mprescripts/>
|
||||
<mi id="presub-1">e</mi>
|
||||
<none/>
|
||||
<mi id="presub-2">f</mi>
|
||||
<mi id="presup-1">g</mi>
|
||||
</mmultiscripts>
|
||||
</math>
|
||||
|
||||
<!-- underscript, overscript -->
|
||||
<math>
|
||||
<munder>
|
||||
<mi id="base-5">a</mi>
|
||||
<mi id="under-1">b</mi>
|
||||
</munder>
|
||||
</math>
|
||||
<math>
|
||||
<mover>
|
||||
<mi id="base-6">a</mi>
|
||||
<mi id="over-1">b</mi>
|
||||
</mover>
|
||||
</math>
|
||||
<math>
|
||||
<munderover>
|
||||
<mi id="base-7">a</mi>
|
||||
<mi id="under-2">b</mi>
|
||||
<mi id="over-2">c</mi>
|
||||
</munderover>
|
||||
</math>
|
||||
|
||||
<!-- root-index -->
|
||||
<math>
|
||||
<mroot>
|
||||
<mi id="base-8">a</mi>
|
||||
<mi id="root-index-1">b</mi>
|
||||
</mroot>
|
||||
</math>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -8,7 +8,13 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
MOZ_PKG_REMOVALS = $(srcdir)/removed-files.in
|
||||
|
||||
MOZ_PKG_MANIFEST_P = $(srcdir)/package-manifest.in
|
||||
MOZ_PKG_MANIFEST = $(srcdir)/package-manifest.in
|
||||
|
||||
ifdef MOZ_CHROME_MULTILOCALE
|
||||
MOZ_PKG_MANIFEST_DEPS = locale-manifest.in
|
||||
|
||||
DEFINES += -DPKG_LOCALE_MANIFEST=$(CURDIR)/locale-manifest.in
|
||||
endif
|
||||
|
||||
DEFINES += \
|
||||
-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
|
||||
|
@ -42,10 +48,6 @@ ifdef ENABLE_MARIONETTE
|
|||
DEFINES += -DENABLE_MARIONETTE=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
MOZ_PKG_MANIFEST = package-manifest
|
||||
endif
|
||||
|
||||
MOZ_PACKAGER_MINIFY=1
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
@ -107,19 +109,16 @@ DEFINES += -DMOZ_GTK3=1
|
|||
endif
|
||||
endif
|
||||
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
$(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P) FORCE
|
||||
$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) $< -o $@)
|
||||
ifdef MOZ_CHROME_MULTILOCALE
|
||||
printf '\n[multilocale]\n' >> $@
|
||||
locale-manifest.in: $(GLOBAL_DEPS) FORCE
|
||||
printf '\n[multilocale]\n' > $@
|
||||
for LOCALE in $(MOZ_CHROME_MULTILOCALE) ;\
|
||||
do \
|
||||
printf '$(BINPATH)/chrome/'"$$LOCALE"'$(JAREXT)\n' >> $@; \
|
||||
printf '$(BINPATH)/chrome/'"$$LOCALE"'.manifest\n' >> $@; \
|
||||
done
|
||||
endif
|
||||
|
||||
GARBAGE += $(MOZ_PKG_MANIFEST)
|
||||
GARBAGE += locale-manifest.in
|
||||
endif
|
||||
|
||||
ifdef FXOS_SIMULATOR
|
||||
|
|
|
@ -980,3 +980,7 @@ bin/libfreebl_32int64_3.so
|
|||
@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
|
||||
@RESPATH@/gmp-clearkey/0.1/clearkey.info
|
||||
#endif
|
||||
|
||||
#ifdef PKG_LOCALE_MANIFEST
|
||||
#include @PKG_LOCALE_MANIFEST@
|
||||
#endif
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
# This file has default permissions for the permission manager.
|
||||
# The file-format is strict:
|
||||
# * matchtype \t type \t permission \t host
|
||||
# * Only "host" is supported for matchtype
|
||||
# * "origin" should be used for matchtype, "host" is supported for legacy reasons
|
||||
# * type is a string that identifies the type of permission (e.g. "cookie")
|
||||
# * permission is an integer between 1 and 15
|
||||
# See nsPermissionManager.cpp for more...
|
||||
|
||||
# UITour
|
||||
host uitour 1 www.mozilla.org
|
||||
host uitour 1 self-repair.mozilla.org
|
||||
host uitour 1 support.mozilla.org
|
||||
host uitour 1 about:home
|
||||
origin uitour 1 https://www.mozilla.org
|
||||
origin uitour 1 https://self-repair.mozilla.org
|
||||
origin uitour 1 https://support.mozilla.org
|
||||
origin uitour 1 about:home
|
||||
|
||||
# XPInstall
|
||||
host install 1 addons.mozilla.org
|
||||
host install 1 marketplace.firefox.com
|
||||
origin install 1 https://addons.mozilla.org
|
||||
origin install 1 https://marketplace.firefox.com
|
||||
|
||||
# Remote troubleshooting
|
||||
host remote-troubleshooting 1 input.mozilla.org
|
||||
host remote-troubleshooting 1 support.mozilla.org
|
||||
origin remote-troubleshooting 1 https://input.mozilla.org
|
||||
origin remote-troubleshooting 1 https://support.mozilla.org
|
||||
|
|
|
@ -44,14 +44,14 @@ var gPluginHandler = {
|
|||
switch (msg.name) {
|
||||
case "PluginContent:ShowClickToPlayNotification":
|
||||
this.showClickToPlayNotification(msg.target, msg.data.plugins, msg.data.showNow,
|
||||
msg.principal, msg.data.host, msg.data.location);
|
||||
msg.principal, msg.data.location);
|
||||
break;
|
||||
case "PluginContent:RemoveNotification":
|
||||
this.removeNotification(msg.target, msg.data.name);
|
||||
break;
|
||||
case "PluginContent:UpdateHiddenPluginUI":
|
||||
this.updateHiddenPluginUI(msg.target, msg.data.haveInsecure, msg.data.actions,
|
||||
msg.principal, msg.data.host, msg.data.location);
|
||||
msg.principal, msg.data.location);
|
||||
break;
|
||||
case "PluginContent:HideNotificationBar":
|
||||
this.hideNotificationBar(msg.target, msg.data.name);
|
||||
|
@ -216,8 +216,8 @@ var gPluginHandler = {
|
|||
});
|
||||
},
|
||||
|
||||
showClickToPlayNotification: function (browser, plugins, showNow, principal,
|
||||
host, location) {
|
||||
showClickToPlayNotification: function (browser, plugins, showNow,
|
||||
principal, location) {
|
||||
// It is possible that we've received a message from the frame script to show
|
||||
// a click to play notification for a principal that no longer matches the one
|
||||
// that the browser's content now has assigned (ie, the browser has browsed away
|
||||
|
@ -295,7 +295,6 @@ var gPluginHandler = {
|
|||
primaryPlugin: primaryPluginPermission,
|
||||
pluginData: pluginData,
|
||||
principal: principal,
|
||||
host: host,
|
||||
};
|
||||
PopupNotifications.show(browser, "click-to-play-plugins",
|
||||
"", "plugins-notification-icon",
|
||||
|
@ -316,8 +315,10 @@ var gPluginHandler = {
|
|||
notificationBox.removeNotification(notification, true);
|
||||
},
|
||||
|
||||
updateHiddenPluginUI: function (browser, haveInsecure, actions, principal,
|
||||
host, location) {
|
||||
updateHiddenPluginUI: function (browser, haveInsecure, actions,
|
||||
principal, location) {
|
||||
let origin = principal.originNoSuffix;
|
||||
|
||||
// It is possible that we've received a message from the frame script to show
|
||||
// the hidden plugin notification for a principal that no longer matches the one
|
||||
// that the browser's content now has assigned (ie, the browser has browsed away
|
||||
|
@ -380,22 +381,22 @@ var gPluginHandler = {
|
|||
case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
|
||||
message = gNavigatorBundle.getFormattedString(
|
||||
"pluginActivateNew.message",
|
||||
[pluginName, host]);
|
||||
[pluginName, origin]);
|
||||
break;
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
|
||||
message = gNavigatorBundle.getFormattedString(
|
||||
"pluginActivateOutdated.message",
|
||||
[pluginName, host, brand]);
|
||||
[pluginName, origin, brand]);
|
||||
break;
|
||||
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
|
||||
message = gNavigatorBundle.getFormattedString(
|
||||
"pluginActivateVulnerable.message",
|
||||
[pluginName, host, brand]);
|
||||
[pluginName, origin, brand]);
|
||||
}
|
||||
} else {
|
||||
// Multi-plugin
|
||||
message = gNavigatorBundle.getFormattedString(
|
||||
"pluginActivateMultiple.message", [host]);
|
||||
"pluginActivateMultiple.message", [origin]);
|
||||
}
|
||||
|
||||
let buttons = [
|
||||
|
|
|
@ -99,7 +99,11 @@ let TrackingProtection = {
|
|||
// Remove the current host from the 'trackingprotection' consumer
|
||||
// of the permission manager. This effectively removes this host
|
||||
// from the tracking protection allowlist.
|
||||
Services.perms.remove(gBrowser.selectedBrowser.currentURI,
|
||||
let normalizedUrl = Services.io.newURI(
|
||||
"https://" + gBrowser.selectedBrowser.currentURI.hostPort,
|
||||
null, null);
|
||||
|
||||
Services.perms.remove(normalizedUrl,
|
||||
"trackingprotection");
|
||||
|
||||
// Telemetry for enable protection.
|
||||
|
|
|
@ -1422,6 +1422,20 @@ var gBrowserInit = {
|
|||
this.gmpInstallManager.simpleCheckAndInstall().then(null, () => {});
|
||||
}, 1000 * 60);
|
||||
|
||||
// Report via telemetry whether we're able to play MP4/H.264/AAC video.
|
||||
// We suspect that some Windows users have a broken or have not installed
|
||||
// Windows Media Foundation, and we'd like to know how many. We'd also like
|
||||
// to know how good our coverage is on other platforms.
|
||||
// Note: we delay by 90 seconds reporting this, as calling canPlayType()
|
||||
// on Windows will cause DLLs to load, i.e. cause disk I/O.
|
||||
setTimeout(() => {
|
||||
let v = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
|
||||
let aacWorks = v.canPlayType("audio/mp4") != "";
|
||||
Services.telemetry.getHistogramById("VIDEO_CAN_CREATE_AAC_DECODER").add(aacWorks);
|
||||
let h264Works = v.canPlayType("video/mp4") != "";
|
||||
Services.telemetry.getHistogramById("VIDEO_CAN_CREATE_H264_DECODER").add(h264Works);
|
||||
}, 90 * 1000);
|
||||
|
||||
SessionStore.promiseInitialized.then(() => {
|
||||
// Bail out if the window has been closed in the meantime.
|
||||
if (window.closed) {
|
||||
|
|
|
@ -1117,8 +1117,9 @@ var imagePermissionObserver = {
|
|||
var row = getSelectedRow(imageTree);
|
||||
var item = gImageView.data[row][COL_IMAGE_NODE];
|
||||
var url = gImageView.data[row][COL_IMAGE_ADDRESS];
|
||||
if (makeURI(url).host == permission.host)
|
||||
if (permission.matchesURI(makeURI(url), true)) {
|
||||
makeBlockImage(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ var permissionObserver = {
|
|||
{
|
||||
if (aTopic == "perm-changed") {
|
||||
var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
|
||||
if (permission.host == gPermURI.host) {
|
||||
if (permission.matchesURI(gPermURI, true)) {
|
||||
if (gPermissions.indexOf(permission.type) > -1)
|
||||
initRow(permission.type);
|
||||
else if (permission.type.startsWith("plugin"))
|
||||
|
@ -35,7 +35,7 @@ function onLoadPermission()
|
|||
if (SitePermissions.isSupportedURI(uri)) {
|
||||
gPermURI = uri;
|
||||
var hostText = document.getElementById("hostText");
|
||||
hostText.value = gPermURI.host;
|
||||
hostText.value = gPermURI.prePath;
|
||||
|
||||
for (var i of gPermissions)
|
||||
initRow(i);
|
||||
|
|
|
@ -1926,7 +1926,7 @@
|
|||
}
|
||||
|
||||
if (animate) {
|
||||
mozRequestAnimationFrame(function () {
|
||||
requestAnimationFrame(function () {
|
||||
this.tabContainer._handleTabTelemetryStart(t, aURI);
|
||||
|
||||
// kick the animation off
|
||||
|
|
|
@ -7,7 +7,7 @@ function test() {
|
|||
isnot(tab.getAttribute("fadein"), "true", "newly opened tab is yet to fade in");
|
||||
|
||||
// Try to remove the tab right before the opening animation's first frame
|
||||
window.mozRequestAnimationFrame(checkAnimationState);
|
||||
window.requestAnimationFrame(checkAnimationState);
|
||||
}
|
||||
|
||||
function checkAnimationState() {
|
||||
|
|
|
@ -47,7 +47,7 @@ function test_install_lwtheme() {
|
|||
is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
|
||||
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
pm.add(makeURI("https://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab("https://example.com/browser/browser/base/content/test/general/bug592338.html");
|
||||
gBrowser.selectedBrowser.addEventListener("pageshow", function() {
|
||||
|
|
|
@ -80,7 +80,7 @@ add_task(function* () {
|
|||
utils.sendMouseEvent("mousedown", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0);
|
||||
utils.sendMouseEvent("mouseup", overlayLeft, overlayTop, 0, 1, 0, false, 0, 0);
|
||||
|
||||
return plugin && !overlay.classList.contains("visible");
|
||||
return overlay.hasAttribute("dismissed") && !overlay.classList.contains("visible");
|
||||
});
|
||||
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins");
|
||||
|
|
|
@ -238,7 +238,7 @@ function clearAllPluginPermissions() {
|
|||
while (perms.hasMoreElements()) {
|
||||
let perm = perms.getNext();
|
||||
if (perm.type.startsWith('plugin')) {
|
||||
info("removing permission:" + perm.host + " " + perm.type + "\n");
|
||||
info("removing permission:" + perm.principal.origin + " " + perm.type + "\n");
|
||||
Services.perms.removePermission(perm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2432,9 +2432,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
let normalizedUrl = Services.io.newURI(
|
||||
"https://" + gBrowser.selectedBrowser.currentURI.hostPort,
|
||||
null, null);
|
||||
// Add the current host in the 'trackingprotection' consumer of
|
||||
// Add the current host/port combination in the 'trackingprotection' consumer of
|
||||
// the permission manager using a normalized URI. This effectively
|
||||
// places this host on the tracking protection allowlist.
|
||||
// places this host/port combination on the tracking protection allowlist.
|
||||
Services.perms.add(normalizedUrl,
|
||||
"trackingprotection", Services.perms.ALLOW_ACTION);
|
||||
BrowserReload();
|
||||
|
@ -2442,10 +2442,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
</method>
|
||||
<method name="enableTrackingContentProtection">
|
||||
<body><![CDATA[
|
||||
// Remove the current host from the 'trackingprotection' consumer
|
||||
// of the permission manager. This effectively removes this host
|
||||
// Remove the current host/port combination from the 'trackingprotection' consumer
|
||||
// of the permission manager. This effectively removes this host/port combination
|
||||
// from the tracking protection allowlist.
|
||||
Services.perms.remove(gBrowser.selectedBrowser.currentURI,
|
||||
let normalizedUrl = Services.io.newURI(
|
||||
"https://" + gBrowser.selectedBrowser.currentURI.hostPort,
|
||||
null, null);
|
||||
Services.perms.remove(normalizedUrl,
|
||||
"trackingprotection");
|
||||
BrowserReload();
|
||||
]]></body>
|
||||
|
@ -2561,8 +2564,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
return;
|
||||
}
|
||||
|
||||
let host = this.notification.options.host;
|
||||
this._setupDescription("pluginActivateMultiple.message", null, host);
|
||||
let prePath = this.notification.options.principal.URI.prePath;
|
||||
this._setupDescription("pluginActivateMultiple.message", null, prePath);
|
||||
|
||||
var showBox = document.getAnonymousElementByAttribute(this, "anonid", "plugin-notification-showbox");
|
||||
|
||||
|
@ -2601,7 +2604,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
<method name="_setupSingleState">
|
||||
<body><![CDATA[
|
||||
var action = this._items[0].action;
|
||||
var host = action.pluginPermissionHost;
|
||||
var prePath = action.pluginPermissionPrePath;
|
||||
|
||||
let label, linkLabel, linkUrl, button1, button2;
|
||||
|
||||
|
@ -2696,7 +2699,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
Cu.reportError(Error("Unexpected blocklist state"));
|
||||
}
|
||||
}
|
||||
this._setupDescription(label, action.pluginName, host);
|
||||
this._setupDescription(label, action.pluginName, prePath);
|
||||
this._setupLink(linkLabel, action.detailsLink);
|
||||
|
||||
this._primaryButton.label = gNavigatorBundle.getString(button1.label);
|
||||
|
@ -2717,7 +2720,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
<method name="_setupDescription">
|
||||
<parameter name="baseString" />
|
||||
<parameter name="pluginName" /> <!-- null for the multiple-plugin case -->
|
||||
<parameter name="host" />
|
||||
<parameter name="prePath" />
|
||||
<body><![CDATA[
|
||||
var bsn = this._brandShortName;
|
||||
var span = document.getAnonymousElementByAttribute(this, "anonid", "click-to-play-plugins-notification-description");
|
||||
|
@ -2725,17 +2728,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
span.removeChild(span.lastChild);
|
||||
}
|
||||
|
||||
var args = ["__host__", this._brandShortName];
|
||||
var args = ["__prepath__", this._brandShortName];
|
||||
if (pluginName) {
|
||||
args.unshift(pluginName);
|
||||
}
|
||||
var bases = gNavigatorBundle.getFormattedString(baseString, args).
|
||||
split("__host__", 2);
|
||||
split("__prepath__", 2);
|
||||
|
||||
span.appendChild(document.createTextNode(bases[0]));
|
||||
var hostSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em");
|
||||
hostSpan.appendChild(document.createTextNode(host));
|
||||
span.appendChild(hostSpan);
|
||||
var prePathSpan = document.createElementNS("http://www.w3.org/1999/xhtml", "em");
|
||||
prePathSpan.appendChild(document.createTextNode(prePath));
|
||||
span.appendChild(prePathSpan);
|
||||
span.appendChild(document.createTextNode(bases[1] + " "));
|
||||
]]></body>
|
||||
</method>
|
||||
|
|
|
@ -17,6 +17,9 @@ Cu.import("resource://gre/modules/ForgetAboutSite.jsm");
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
let gSecMan = Cc["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Ci.nsIScriptSecurityManager);
|
||||
|
||||
let gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"].
|
||||
getService(Ci.nsIFaviconService);
|
||||
|
||||
|
@ -26,7 +29,7 @@ let gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"].
|
|||
clone(true);
|
||||
|
||||
let gSitesStmt = gPlacesDatabase.createAsyncStatement(
|
||||
"SELECT get_unreversed_host(rev_host) AS host " +
|
||||
"SELECT url " +
|
||||
"FROM moz_places " +
|
||||
"WHERE rev_host > '.' " +
|
||||
"AND visit_count > 0 " +
|
||||
|
@ -46,14 +49,11 @@ let gVisitStmt = gPlacesDatabase.createAsyncStatement(
|
|||
let TEST_EXACT_PERM_TYPES = ["geo", "camera", "microphone"];
|
||||
|
||||
/**
|
||||
* Site object represents a single site, uniquely identified by a host.
|
||||
* Site object represents a single site, uniquely identified by a principal.
|
||||
*/
|
||||
function Site(host) {
|
||||
this.host = host;
|
||||
function Site(principal) {
|
||||
this.principal = principal;
|
||||
this.listitem = null;
|
||||
|
||||
this.httpURI = NetUtil.newURI("http://" + this.host);
|
||||
this.httpsURI = NetUtil.newURI("https://" + this.host);
|
||||
}
|
||||
|
||||
Site.prototype = {
|
||||
|
@ -75,16 +75,10 @@ Site.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
// Try to find favicon for both URIs, but always prefer the https favicon.
|
||||
gFaviconService.getFaviconURLForPage(this.httpsURI, function (aURI) {
|
||||
// Get the favicon for the origin
|
||||
gFaviconService.getFaviconURLForPage(this.principal.URI, function (aURI) {
|
||||
if (aURI) {
|
||||
invokeCallback(aURI);
|
||||
} else {
|
||||
gFaviconService.getFaviconURLForPage(this.httpURI, function (aURI) {
|
||||
if (aURI) {
|
||||
invokeCallback(aURI);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
@ -96,7 +90,9 @@ Site.prototype = {
|
|||
* A function that takes the visit count (a number) as a parameter.
|
||||
*/
|
||||
getVisitCount: function Site_getVisitCount(aCallback) {
|
||||
let rev_host = this.host.split("").reverse().join("") + ".";
|
||||
// XXX This won't be a very reliable system, as it will count both http: and https: visits
|
||||
// Unfortunately, I don't think that there is a much better way to do it right now.
|
||||
let rev_host = this.principal.URI.host.split("").reverse().join("") + ".";
|
||||
gVisitStmt.params.rev_host = rev_host;
|
||||
gVisitStmt.executeAsync({
|
||||
handleResult: function(aResults) {
|
||||
|
@ -139,9 +135,9 @@ Site.prototype = {
|
|||
|
||||
let permissionValue;
|
||||
if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) {
|
||||
permissionValue = Services.perms.testPermission(this.httpURI, aType);
|
||||
permissionValue = Services.perms.testPermissionFromPrincipal(this.principal, aType);
|
||||
} else {
|
||||
permissionValue = Services.perms.testExactPermission(this.httpURI, aType);
|
||||
permissionValue = Services.perms.testExactPermissionFromPrincipal(this.principal, aType);
|
||||
}
|
||||
aResultObj.value = permissionValue;
|
||||
|
||||
|
@ -166,9 +162,7 @@ Site.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Using httpURI is kind of bogus, but the permission manager stores the
|
||||
// permission for the host, so the right thing happens in the end.
|
||||
Services.perms.add(this.httpURI, aType, aPerm);
|
||||
Services.perms.addFromPrincipal(this.principal, aType, aPerm);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -179,7 +173,7 @@ Site.prototype = {
|
|||
* e.g. "cookie", "geo", "indexedDB", "popup", "image"
|
||||
*/
|
||||
clearPermission: function Site_clearPermission(aType) {
|
||||
Services.perms.remove(this.httpURI, aType);
|
||||
Services.perms.removeFromPrincipal(this.principal, aType);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -189,13 +183,14 @@ Site.prototype = {
|
|||
* @return An array of the cookies set for the site.
|
||||
*/
|
||||
get cookies() {
|
||||
let host = this.principal.URI.host;
|
||||
let cookies = [];
|
||||
let enumerator = Services.cookies.getCookiesFromHost(this.host);
|
||||
let enumerator = Services.cookies.getCookiesFromHost(host);
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
// getCookiesFromHost returns cookies for base domain, but we only want
|
||||
// the cookies for the exact domain.
|
||||
if (cookie.rawHost == this.host) {
|
||||
if (cookie.rawHost == host) {
|
||||
cookies.push(cookie);
|
||||
}
|
||||
}
|
||||
|
@ -217,27 +212,27 @@ Site.prototype = {
|
|||
* @return An array of the logins stored for the site.
|
||||
*/
|
||||
get logins() {
|
||||
let httpLogins = Services.logins.findLogins({}, this.httpURI.prePath, "", "");
|
||||
let httpsLogins = Services.logins.findLogins({}, this.httpsURI.prePath, "", "");
|
||||
return httpLogins.concat(httpsLogins);
|
||||
let logins = Services.logins.findLogins({}, this.principal.originNoSuffix, "", "");
|
||||
return logins;
|
||||
},
|
||||
|
||||
get loginSavingEnabled() {
|
||||
// Only say that login saving is blocked if it is blocked for both http and https.
|
||||
return Services.logins.getLoginSavingEnabled(this.httpURI.prePath) &&
|
||||
Services.logins.getLoginSavingEnabled(this.httpsURI.prePath);
|
||||
return Services.logins.getLoginSavingEnabled(this.principal.originNoSuffix);
|
||||
},
|
||||
|
||||
set loginSavingEnabled(isEnabled) {
|
||||
Services.logins.setLoginSavingEnabled(this.httpURI.prePath, isEnabled);
|
||||
Services.logins.setLoginSavingEnabled(this.httpsURI.prePath, isEnabled);
|
||||
Services.logins.setLoginSavingEnabled(this.principal.originNoSuffix, isEnabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all data from the browser corresponding to the site.
|
||||
*/
|
||||
forgetSite: function Site_forgetSite() {
|
||||
ForgetAboutSite.removeDataFromDomain(this.host);
|
||||
// XXX This removes data for an entire domain, rather than just
|
||||
// an origin. This may produce confusing results, as data will
|
||||
// be cleared for the http:// as well as the https:// domain
|
||||
// if you try to forget the https:// site.
|
||||
ForgetAboutSite.removeDataFromDomain(this.principal.URI.host);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +361,7 @@ let AboutPermissions = {
|
|||
LIST_BUILD_DELAY: 100, // delay between intervals
|
||||
|
||||
/**
|
||||
* Stores a mapping of host strings to Site objects.
|
||||
* Stores a mapping of origin strings to Site objects.
|
||||
*/
|
||||
_sites: {},
|
||||
|
||||
|
@ -472,9 +467,9 @@ let AboutPermissions = {
|
|||
break;
|
||||
}
|
||||
let permission = aSubject.QueryInterface(Ci.nsIPermission);
|
||||
// We can't compare selectedSite.host and permission.host here because
|
||||
// we need to handle the case where a parent domain was changed in a
|
||||
// way that affects the subdomain.
|
||||
// We can't compare selectedSite.principal and permission.principal here
|
||||
// because we need to handle the case where a parent domain was changed
|
||||
// in a way that affects the subdomain.
|
||||
if (this._supportedPermissions.indexOf(permission.type) != -1) {
|
||||
this.updatePermission(permission.type);
|
||||
}
|
||||
|
@ -512,8 +507,11 @@ let AboutPermissions = {
|
|||
AboutPermissions.startSitesListBatch();
|
||||
let row;
|
||||
while (row = aResults.getNextRow()) {
|
||||
let host = row.getResultByName("host");
|
||||
AboutPermissions.addHost(host);
|
||||
let spec = row.getResultByName("url");
|
||||
let uri = NetUtil.newURI(spec);
|
||||
let principal = gSecMan.getNoAppCodebasePrincipal(uri);
|
||||
|
||||
AboutPermissions.addPrincipal(principal);
|
||||
}
|
||||
AboutPermissions.endSitesListBatch();
|
||||
},
|
||||
|
@ -562,7 +560,8 @@ let AboutPermissions = {
|
|||
try {
|
||||
// aLogin.hostname is a string in origin URL format (e.g. "http://foo.com")
|
||||
let uri = NetUtil.newURI(aLogin.hostname);
|
||||
this.addHost(uri.host);
|
||||
let principal = gSecMan.getNoAppCodebasePrincipal(uri);
|
||||
this.addPrincipal(principal);
|
||||
} catch (e) {
|
||||
// newURI will throw for add-ons logins stored in chrome:// URIs
|
||||
}
|
||||
|
@ -577,7 +576,8 @@ let AboutPermissions = {
|
|||
try {
|
||||
// aHostname is a string in origin URL format (e.g. "http://foo.com")
|
||||
let uri = NetUtil.newURI(aHostname);
|
||||
this.addHost(uri.host);
|
||||
let principal = gSecMan.getNoAppCodebasePrincipal(uri);
|
||||
this.addPrincipal(principal);
|
||||
} catch (e) {
|
||||
// newURI will throw for add-ons logins stored in chrome:// URIs
|
||||
}
|
||||
|
@ -592,7 +592,7 @@ let AboutPermissions = {
|
|||
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
|
||||
// Only include sites with exceptions set for supported permission types.
|
||||
if (this._supportedPermissions.indexOf(permission.type) != -1) {
|
||||
this.addHost(permission.host);
|
||||
this.addPrincipal(permission.principal);
|
||||
}
|
||||
itemCnt++;
|
||||
}
|
||||
|
@ -603,15 +603,15 @@ let AboutPermissions = {
|
|||
/**
|
||||
* Creates a new Site and adds it to _sites if it's not already there.
|
||||
*
|
||||
* @param aHost
|
||||
* A host string.
|
||||
* @param aPrincipal
|
||||
* A principal.
|
||||
*/
|
||||
addHost: function(aHost) {
|
||||
if (aHost in this._sites) {
|
||||
addPrincipal: function(aPrincipal) {
|
||||
if (aPrincipal.origin in this._sites) {
|
||||
return;
|
||||
}
|
||||
let site = new Site(aHost);
|
||||
this._sites[aHost] = site;
|
||||
let site = new Site(aPrincipal);
|
||||
this._sites[aPrincipal.origin] = site;
|
||||
this.addToSitesList(site);
|
||||
},
|
||||
|
||||
|
@ -624,7 +624,7 @@ let AboutPermissions = {
|
|||
addToSitesList: function(aSite) {
|
||||
let item = document.createElement("richlistitem");
|
||||
item.setAttribute("class", "site");
|
||||
item.setAttribute("value", aSite.host);
|
||||
item.setAttribute("value", aSite.principal.origin);
|
||||
|
||||
aSite.getFavicon(function(aURL) {
|
||||
item.setAttribute("favicon", aURL);
|
||||
|
@ -633,7 +633,7 @@ let AboutPermissions = {
|
|||
|
||||
// Make sure to only display relevant items when list is filtered
|
||||
let filterValue = document.getElementById("sites-filter").value.toLowerCase();
|
||||
item.collapsed = aSite.host.toLowerCase().indexOf(filterValue) == -1;
|
||||
item.collapsed = aSite.principal.origin.toLowerCase().indexOf(filterValue) == -1;
|
||||
|
||||
(this._listFragment || this.sitesList).appendChild(item);
|
||||
},
|
||||
|
@ -686,16 +686,16 @@ let AboutPermissions = {
|
|||
* The host string corresponding to the site to delete.
|
||||
*/
|
||||
deleteFromSitesList: function(aHost) {
|
||||
for (let host in this._sites) {
|
||||
let site = this._sites[host];
|
||||
if (site.host.hasRootDomain(aHost)) {
|
||||
for (let origin in this._sites) {
|
||||
let site = this._sites[origin];
|
||||
if (site.principal.URI.host.hasRootDomain(aHost)) {
|
||||
if (site == this._selectedSite) {
|
||||
// Replace site-specific interface with "All Sites" interface.
|
||||
this.sitesList.selectedItem = document.getElementById("all-sites-item");
|
||||
}
|
||||
|
||||
this.sitesList.removeChild(site.listitem);
|
||||
delete this._sites[site.host];
|
||||
delete this._sites[site.principal.origin];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -711,9 +711,9 @@ let AboutPermissions = {
|
|||
return;
|
||||
}
|
||||
|
||||
let host = event.target.value;
|
||||
let site = this._selectedSite = this._sites[host];
|
||||
document.getElementById("site-label").value = host;
|
||||
let origin = event.target.value;
|
||||
let site = this._selectedSite = this._sites[origin];
|
||||
document.getElementById("site-label").value = origin;
|
||||
document.getElementById("header-deck").selectedPanel =
|
||||
document.getElementById("site-header");
|
||||
|
||||
|
@ -768,9 +768,9 @@ let AboutPermissions = {
|
|||
// If there is no selected site, we are updating the default permissions interface.
|
||||
permissionValue = PermissionDefaults[aType];
|
||||
if (aType == "cookie")
|
||||
// cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved
|
||||
// for site-specific preferences only.
|
||||
document.getElementById("cookie-9").hidden = true;
|
||||
// cookie-9 corresponds to ALLOW_FIRST_PARTY_ONLY, which is reserved
|
||||
// for site-specific preferences only.
|
||||
document.getElementById("cookie-9").hidden = true;
|
||||
} else {
|
||||
if (aType == "cookie")
|
||||
document.getElementById("cookie-9").hidden = false;
|
||||
|
@ -825,18 +825,18 @@ let AboutPermissions = {
|
|||
* Opens password manager dialog.
|
||||
*/
|
||||
managePasswords: function() {
|
||||
let selectedHost = "";
|
||||
let selectedOrigin = "";
|
||||
if (this._selectedSite) {
|
||||
selectedHost = this._selectedSite.host;
|
||||
selectedOrigin = this._selectedSite.principal.URI.prePath;
|
||||
}
|
||||
|
||||
let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager");
|
||||
if (win) {
|
||||
win.setFilter(selectedHost);
|
||||
win.setFilter(selectedOrigin);
|
||||
win.focus();
|
||||
} else {
|
||||
window.openDialog("chrome://passwordmgr/content/passwordManager.xul",
|
||||
"Toolkit:PasswordManager", "", {filterString : selectedHost});
|
||||
"Toolkit:PasswordManager", "", {filterString : selectedOrigin});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -877,9 +877,11 @@ let AboutPermissions = {
|
|||
* Opens cookie manager dialog.
|
||||
*/
|
||||
manageCookies: function() {
|
||||
// Cookies are stored by-host, and thus we filter the cookie window
|
||||
// using only the host of the selected principal's origin
|
||||
let selectedHost = "";
|
||||
if (this._selectedSite) {
|
||||
selectedHost = this._selectedSite.host;
|
||||
selectedHost = this._selectedSite.principal.URI.host;
|
||||
}
|
||||
|
||||
let win = Services.wm.getMostRecentWindow("Browser:Cookies");
|
||||
|
|
|
@ -9,6 +9,7 @@ Components.utils.import("resource://gre/modules/ctypes.jsm");
|
|||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
|
||||
|
||||
var gAdvancedPane = {
|
||||
_inited: false,
|
||||
|
@ -471,7 +472,7 @@ var gAdvancedPane = {
|
|||
var usage = 0;
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var uri = ios.newURI(groups[i], null, null);
|
||||
if (uri.asciiHost == perm.host) {
|
||||
if (perm.matchesURI(uri, true)) {
|
||||
var cache = cacheService.getActiveCache(groups[i]);
|
||||
usage += cache.usage;
|
||||
}
|
||||
|
@ -508,7 +509,7 @@ var gAdvancedPane = {
|
|||
var row = document.createElement("listitem");
|
||||
row.id = "";
|
||||
row.className = "offlineapp";
|
||||
row.setAttribute("host", perm.host);
|
||||
row.setAttribute("origin", perm.principal.origin);
|
||||
var converted = DownloadUtils.
|
||||
convertByteUnits(this._getOfflineAppUsage(perm, groups));
|
||||
row.setAttribute("usage",
|
||||
|
@ -534,7 +535,8 @@ var gAdvancedPane = {
|
|||
{
|
||||
var list = document.getElementById("offlineAppsList");
|
||||
var item = list.selectedItem;
|
||||
var host = item.getAttribute("host");
|
||||
var origin = item.getAttribute("origin");
|
||||
var principal = BrowserUtils.principalFromOrigin(origin);
|
||||
|
||||
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
@ -543,13 +545,18 @@ var gAdvancedPane = {
|
|||
|
||||
var bundle = document.getElementById("bundlePreferences");
|
||||
var title = bundle.getString("offlineAppRemoveTitle");
|
||||
var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]);
|
||||
var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [principal.URI.prePath]);
|
||||
var confirm = bundle.getString("offlineAppRemoveConfirm");
|
||||
var result = prompts.confirmEx(window, title, prompt, flags, confirm,
|
||||
null, null, null, {});
|
||||
if (result != 0)
|
||||
return;
|
||||
|
||||
// get the permission
|
||||
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager);
|
||||
var perm = pm.getPermissionObject(principal, "offline-app");
|
||||
|
||||
// clear offline cache entries
|
||||
var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
|
||||
getService(Components.interfaces.nsIApplicationCacheService);
|
||||
|
@ -557,25 +564,14 @@ var gAdvancedPane = {
|
|||
getService(Components.interfaces.nsIIOService);
|
||||
var groups = cacheService.getGroups();
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
let uri = ios.newURI(groups[i], null, null);
|
||||
if (uri.asciiHost == host) {
|
||||
var uri = ios.newURI(groups[i], null, null);
|
||||
if (perm.matchesURI(uri, true)) {
|
||||
var cache = cacheService.getActiveCache(groups[i]);
|
||||
cache.discard();
|
||||
}
|
||||
}
|
||||
|
||||
// remove the permission
|
||||
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager);
|
||||
let uri;
|
||||
try {
|
||||
// file:// URIs are stored with their scheme. We try to parse them first, as
|
||||
// URIs like http://file:///foo/bar/baz.html will parse as HTTP URIs.
|
||||
uri = ios.newURI(host, null, null);
|
||||
} catch (e) {
|
||||
uri = ios.newURI("http://" + host, null, null);
|
||||
}
|
||||
pm.remove(uri, "offline-app");
|
||||
pm.removePermission(perm);
|
||||
|
||||
list.removeChild(item);
|
||||
gAdvancedPane.offlineAppSelected();
|
||||
|
|
|
@ -502,7 +502,7 @@ var gAdvancedPane = {
|
|||
var usage = 0;
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
var uri = ios.newURI(groups[i], null, null);
|
||||
if (uri.asciiHost == perm.host) {
|
||||
if (perm.matchesURI(uri, true)) {
|
||||
var cache = cacheService.getActiveCache(groups[i]);
|
||||
usage += cache.usage;
|
||||
}
|
||||
|
@ -544,7 +544,7 @@ var gAdvancedPane = {
|
|||
var row = document.createElement("listitem");
|
||||
row.id = "";
|
||||
row.className = "offlineapp";
|
||||
row.setAttribute("host", perm.host);
|
||||
row.setAttribute("origin", perm.principal.origin);
|
||||
var converted = DownloadUtils.
|
||||
convertByteUnits(this._getOfflineAppUsage(perm, groups));
|
||||
row.setAttribute("usage",
|
||||
|
@ -570,7 +570,8 @@ var gAdvancedPane = {
|
|||
{
|
||||
var list = document.getElementById("offlineAppsList");
|
||||
var item = list.selectedItem;
|
||||
var host = item.getAttribute("host");
|
||||
var origin = item.getAttribute("origin");
|
||||
var principal = BrowserUtils.principalFromOrigin(origin);
|
||||
|
||||
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
@ -579,13 +580,18 @@ var gAdvancedPane = {
|
|||
|
||||
var bundle = document.getElementById("bundlePreferences");
|
||||
var title = bundle.getString("offlineAppRemoveTitle");
|
||||
var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]);
|
||||
var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [principal.URI.prePath]);
|
||||
var confirm = bundle.getString("offlineAppRemoveConfirm");
|
||||
var result = prompts.confirmEx(window, title, prompt, flags, confirm,
|
||||
null, null, null, {});
|
||||
if (result != 0)
|
||||
return;
|
||||
|
||||
// get the permission
|
||||
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager);
|
||||
var perm = pm.getPermissionObject(principal, "offline-app");
|
||||
|
||||
// clear offline cache entries
|
||||
try {
|
||||
var cacheService = Components.classes["@mozilla.org/network/application-cache-service;1"].
|
||||
|
@ -594,26 +600,15 @@ var gAdvancedPane = {
|
|||
getService(Components.interfaces.nsIIOService);
|
||||
var groups = cacheService.getGroups();
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
let uri = ios.newURI(groups[i], null, null);
|
||||
if (uri.asciiHost == host) {
|
||||
var uri = ios.newURI(groups[i], null, null);
|
||||
if (perm.matchesURI(uri, true)) {
|
||||
var cache = cacheService.getActiveCache(groups[i]);
|
||||
cache.discard();
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
// remove the permission
|
||||
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Components.interfaces.nsIPermissionManager);
|
||||
let uri;
|
||||
try {
|
||||
// file:// URIs are stored with their scheme. We try to parse them first, as
|
||||
// URIs like http://file:///foo/bar/baz.html will parse as HTTP URIs.
|
||||
uri = ios.newURI(host, null, null);
|
||||
} catch (e) {
|
||||
uri = ios.newURI("http://" + host, null, null);
|
||||
}
|
||||
pm.remove(uri, "offline-app");
|
||||
pm.removePermission(perm);
|
||||
|
||||
list.removeChild(item);
|
||||
gAdvancedPane.offlineAppSelected();
|
||||
|
|
|
@ -9,10 +9,10 @@ const nsICookiePermission = Components.interfaces.nsICookiePermission;
|
|||
|
||||
const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions";
|
||||
|
||||
function Permission(host, rawHost, type, capability)
|
||||
function Permission(principal, type, capability)
|
||||
{
|
||||
this.host = host;
|
||||
this.rawHost = rawHost;
|
||||
this.principal = principal;
|
||||
this.origin = principal.origin;
|
||||
this.type = type;
|
||||
this.capability = capability;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ var gPermissionManager = {
|
|||
getCellText: function (aRow, aColumn)
|
||||
{
|
||||
if (aColumn.id == "siteCol")
|
||||
return gPermissionManager._permissions[aRow].rawHost;
|
||||
return gPermissionManager._permissions[aRow].origin;
|
||||
else if (aColumn.id == "statusCol")
|
||||
return gPermissionManager._permissions[aRow].capability;
|
||||
return "";
|
||||
|
@ -82,10 +82,17 @@ var gPermissionManager = {
|
|||
addPermission: function (aCapability)
|
||||
{
|
||||
var textbox = document.getElementById("url");
|
||||
var host = textbox.value.replace(/^\s*([-\w]*:\/+)?/, ""); // trim any leading space and scheme
|
||||
var input_url = textbox.value.replace(/^\s*/, ""); // trim any leading space
|
||||
let principal;
|
||||
try {
|
||||
var uri = Services.io.newURI("http://"+host, null, null);
|
||||
host = uri.host;
|
||||
// If the uri doesn't successfully parse, try adding a http:// and parsing again
|
||||
let uri;
|
||||
try {
|
||||
let uri = Services.io.newURI(input_url, null, null);
|
||||
} catch(ex) {
|
||||
uri = Services.io.newURI("http://" + input_url, null, null);
|
||||
}
|
||||
principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
|
||||
} catch(ex) {
|
||||
var message = this._bundle.getString("invalidURI");
|
||||
var title = this._bundle.getString("invalidURITitle");
|
||||
|
@ -96,11 +103,11 @@ var gPermissionManager = {
|
|||
var capabilityString = this._getCapabilityString(aCapability);
|
||||
|
||||
// check whether the permission already exists, if not, add it
|
||||
let hostExists = false;
|
||||
let permissionExists = false;
|
||||
let capabilityExists = false;
|
||||
for (var i = 0; i < this._permissions.length; ++i) {
|
||||
if (this._permissions[i].rawHost == host) {
|
||||
hostExists = true;
|
||||
if (this._permissions[i].principal.equals(principal)) {
|
||||
permissionExists = true;
|
||||
capabilityExists = this._permissions[i].capability == capabilityString;
|
||||
if (!capabilityExists) {
|
||||
this._permissions[i].capability = capabilityString;
|
||||
|
@ -109,14 +116,14 @@ var gPermissionManager = {
|
|||
}
|
||||
}
|
||||
|
||||
let permissionParams = {host: host, type: this._type, capability: aCapability};
|
||||
if (!hostExists) {
|
||||
this._permissionsToAdd.set(host, permissionParams);
|
||||
let permissionParams = {principal: principal, type: this._type, capability: aCapability};
|
||||
if (!permissionExists) {
|
||||
this._permissionsToAdd.set(principal.origin, permissionParams);
|
||||
this._addPermission(permissionParams);
|
||||
}
|
||||
else if (!capabilityExists) {
|
||||
this._permissionsToAdd.set(host, permissionParams);
|
||||
this._handleCapabilityChange();
|
||||
this._permissionsToAdd.set(principal.origin, permissionParams);
|
||||
this._handleCapabilityChange();
|
||||
}
|
||||
|
||||
textbox.value = "";
|
||||
|
@ -131,15 +138,15 @@ var gPermissionManager = {
|
|||
|
||||
_removePermission: function(aPermission)
|
||||
{
|
||||
this._removePermissionFromList(aPermission.host);
|
||||
this._removePermissionFromList(aPermission.principal);
|
||||
|
||||
// If this permission was added during this session, let's remove
|
||||
// it from the pending adds list to prevent calls to the
|
||||
// permission manager.
|
||||
let isNewPermission = this._permissionsToAdd.delete(aPermission.host);
|
||||
let isNewPermission = this._permissionsToAdd.delete(aPermission.principal.origin);
|
||||
|
||||
if (!isNewPermission) {
|
||||
this._permissionsToDelete.set(aPermission.host, aPermission);
|
||||
this._permissionsToDelete.set(aPermission.principal.origin, aPermission);
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -276,7 +283,7 @@ var gPermissionManager = {
|
|||
}
|
||||
else if (aData == "changed") {
|
||||
for (var i = 0; i < this._permissions.length; ++i) {
|
||||
if (this._permissions[i].host == permission.host) {
|
||||
if (permission.matches(this._permissions[i].principal, true)) {
|
||||
this._permissions[i].capability = this._getCapabilityString(permission.capability);
|
||||
break;
|
||||
}
|
||||
|
@ -363,13 +370,11 @@ var gPermissionManager = {
|
|||
this.uninit();
|
||||
|
||||
for (let permissionParams of this._permissionsToAdd.values()) {
|
||||
let uri = Services.io.newURI("http://" + permissionParams.host, null, null);
|
||||
Services.perms.add(uri, permissionParams.type, permissionParams.capability);
|
||||
Services.perms.addFromPrincipal(permissionParams.principal, permissionParams.type, permissionParams.capability);
|
||||
}
|
||||
|
||||
for (let p of this._permissionsToDelete.values()) {
|
||||
let uri = Services.io.newURI("http://" + p.host, null, null);
|
||||
Services.perms.remove(uri, p.type);
|
||||
Services.perms.removeFromPrincipal(p.principal, p.type);
|
||||
}
|
||||
|
||||
window.close();
|
||||
|
@ -392,7 +397,7 @@ var gPermissionManager = {
|
|||
|
||||
// sort and display the table
|
||||
this._tree.view = this._view;
|
||||
this.onPermissionSort("rawHost");
|
||||
this.onPermissionSort("origin");
|
||||
|
||||
// disable "remove all" button if there are none
|
||||
document.getElementById("removeAllPermissions").disabled = this._permissions.length == 0;
|
||||
|
@ -404,20 +409,19 @@ var gPermissionManager = {
|
|||
(!this._manageCapability ||
|
||||
(aPermission.capability == this._manageCapability))) {
|
||||
|
||||
var host = aPermission.host;
|
||||
var principal = aPermission.principal;
|
||||
var capabilityString = this._getCapabilityString(aPermission.capability);
|
||||
var p = new Permission(host,
|
||||
(host.charAt(0) == ".") ? host.substring(1,host.length) : host,
|
||||
var p = new Permission(principal,
|
||||
aPermission.type,
|
||||
capabilityString);
|
||||
this._permissions.push(p);
|
||||
}
|
||||
},
|
||||
|
||||
_removePermissionFromList: function (aHost)
|
||||
_removePermissionFromList: function (aPrincipal)
|
||||
{
|
||||
for (let i = 0; i < this._permissions.length; ++i) {
|
||||
if (this._permissions[i].host == aHost) {
|
||||
if (this._permissions[i].principal.equals(aPrincipal)) {
|
||||
this._permissions.splice(i, 1);
|
||||
this._view._rowCount--;
|
||||
this._tree.treeBoxObject.rowCountChanged(this._view.rowCount - 1, -1);
|
||||
|
@ -427,15 +431,15 @@ var gPermissionManager = {
|
|||
}
|
||||
},
|
||||
|
||||
setHost: function (aHost)
|
||||
setOrigin: function (aOrigin)
|
||||
{
|
||||
document.getElementById("url").value = aHost;
|
||||
document.getElementById("url").value = aOrigin;
|
||||
}
|
||||
};
|
||||
|
||||
function setHost(aHost)
|
||||
function setOrigin(aOrigin)
|
||||
{
|
||||
gPermissionManager.setHost(aHost);
|
||||
gPermissionManager.setOrigin(aOrigin);
|
||||
}
|
||||
|
||||
function initWithParams(aParams)
|
||||
|
|
|
@ -103,11 +103,11 @@ var tests = [
|
|||
sitesFilter.doCommand();
|
||||
},
|
||||
run: function() {
|
||||
let testSite1 = getSiteItem(TEST_URI_1.host);
|
||||
let testSite1 = getSiteItem(TEST_URI_1.prePath);
|
||||
ok(testSite1.collapsed, "test site 1 is collapsed after early filtering");
|
||||
let testSite2 = getSiteItem(TEST_URI_2.host);
|
||||
let testSite2 = getSiteItem(TEST_URI_2.prePath);
|
||||
ok(!testSite2.collapsed, "test site 2 is not collapsed after early filtering");
|
||||
let testSite3 = getSiteItem(TEST_URI_3.host);
|
||||
let testSite3 = getSiteItem(TEST_URI_3.prePath);
|
||||
ok(testSite3.collapsed, "test site 3 is collapsed after early filtering");
|
||||
|
||||
runNextTest();
|
||||
|
@ -119,11 +119,11 @@ var tests = [
|
|||
ForgetAboutSite.removeDataFromDomain(TEST_URI_2.host);
|
||||
},
|
||||
run: function() {
|
||||
let testSite1 = getSiteItem(TEST_URI_1.host);
|
||||
let testSite1 = getSiteItem(TEST_URI_1.prePath);
|
||||
ok(testSite1, "test site 1 was not removed from sites list");
|
||||
let testSite2 = getSiteItem(TEST_URI_2.host);
|
||||
let testSite2 = getSiteItem(TEST_URI_2.prePath);
|
||||
ok(!testSite2, "test site 2 was pre-removed from sites list");
|
||||
let testSite3 = getSiteItem(TEST_URI_3.host);
|
||||
let testSite3 = getSiteItem(TEST_URI_3.prePath);
|
||||
ok(testSite3, "test site 3 was not removed from sites list");
|
||||
|
||||
runNextTest();
|
||||
|
@ -131,7 +131,7 @@ var tests = [
|
|||
}
|
||||
];
|
||||
|
||||
function getSiteItem(aHost) {
|
||||
function getSiteItem(aPrePath) {
|
||||
return gBrowser.contentDocument.
|
||||
querySelector(".site[value='" + aHost + "']");
|
||||
querySelector(".site[value='" + aPrePath + "']");
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ var testRunner = {
|
|||
"permission text should be set correctly");
|
||||
params.btnApplyChanges.doCommand();
|
||||
},
|
||||
observances: [{ type: "cookie", host: "test.com", data: "added",
|
||||
observances: [{ type: "cookie", origin: "http://test.com", data: "added",
|
||||
capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
|
||||
},
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ var testRunner = {
|
|||
"permission should change to deny in UI");
|
||||
params.btnApplyChanges.doCommand();
|
||||
},
|
||||
observances: [{ type: "cookie", host: "test.com", data: "changed",
|
||||
observances: [{ type: "cookie", origin: "http://test.com", data: "changed",
|
||||
capability: Ci.nsIPermissionManager.DENY_ACTION }],
|
||||
},
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ var testRunner = {
|
|||
"permission should revert back to allow");
|
||||
params.btnApplyChanges.doCommand();
|
||||
},
|
||||
observances: [{ type: "cookie", host: "test.com", data: "changed",
|
||||
observances: [{ type: "cookie", origin: "http://test.com", data: "changed",
|
||||
capability: Ci.nsIPermissionManager.ALLOW_ACTION }],
|
||||
},
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ var testRunner = {
|
|||
is(params.tree.view.rowCount, 0, "exception should be removed");
|
||||
params.btnApplyChanges.doCommand();
|
||||
},
|
||||
observances: [{ type: "cookie", host: "test.com", data: "deleted" }],
|
||||
observances: [{ type: "cookie", origin: "http://test.com", data: "deleted" }],
|
||||
},
|
||||
{
|
||||
test: function(params) {
|
||||
|
@ -61,7 +61,7 @@ var testRunner = {
|
|||
is(params.tree.view.rowCount, 0, "adding unrelated permission should not change display");
|
||||
params.btnApplyChanges.doCommand();
|
||||
},
|
||||
observances: [{ type: "popup", host: "test.com", data: "added",
|
||||
observances: [{ type: "popup", origin: "http://test.com", data: "added",
|
||||
capability: Ci.nsIPermissionManager.DENY_ACTION }],
|
||||
cleanUp: function(params) {
|
||||
let uri = params.ioService.newURI("http://test.com", null, null);
|
||||
|
@ -160,12 +160,17 @@ var testRunner = {
|
|||
let expected = testRunner.tests[testRunner._currentTest].observances.shift();
|
||||
|
||||
is(aData, expected.data, "type of message should be the same");
|
||||
for each (let prop in ["type", "host", "capability"]) {
|
||||
for each (let prop in ["type", "capability"]) {
|
||||
if (expected[prop])
|
||||
is(permission[prop], expected[prop],
|
||||
"property: \"" + prop + "\" should be equal");
|
||||
}
|
||||
|
||||
if (expected.origin) {
|
||||
is(permission.principal.origin, expected.origin,
|
||||
"property: \"origin\" should be equal");
|
||||
}
|
||||
|
||||
os.removeObserver(permObserver, "perm-changed");
|
||||
|
||||
if (testRunner.tests[testRunner._currentTest].cleanup) {
|
||||
|
|
|
@ -115,8 +115,8 @@ var tests = [
|
|||
is(gSitesList.firstChild.id, "all-sites-item",
|
||||
"all sites is the first item in the sites list");
|
||||
|
||||
ok(getSiteItem(TEST_URI_1.host), "site item from places db exists");
|
||||
ok(getSiteItem(TEST_URI_2.host), "site item from enumerating services exists");
|
||||
ok(getSiteItem(TEST_URI_1.prePath), "site item from places db exists");
|
||||
ok(getSiteItem(TEST_URI_2.prePath), "site item from enumerating services exists");
|
||||
|
||||
runNextTest();
|
||||
},
|
||||
|
@ -128,9 +128,9 @@ var tests = [
|
|||
sitesFilter.doCommand();
|
||||
|
||||
// make sure correct sites are collapsed/showing
|
||||
let testSite1 = getSiteItem(TEST_URI_1.host);
|
||||
let testSite1 = getSiteItem(TEST_URI_1.prePath);
|
||||
ok(!testSite1.collapsed, "test site 1 is not collapsed");
|
||||
let testSite2 = getSiteItem(TEST_URI_2.host);
|
||||
let testSite2 = getSiteItem(TEST_URI_2.prePath);
|
||||
ok(testSite2.collapsed, "test site 2 is collapsed");
|
||||
|
||||
// clear filter
|
||||
|
@ -202,13 +202,13 @@ var tests = [
|
|||
|
||||
function test_select_site() {
|
||||
// select the site that has the permissions we set at the beginning of the test
|
||||
let testSiteItem = getSiteItem(TEST_URI_2.host);
|
||||
let testSiteItem = getSiteItem(TEST_URI_2.prePath);
|
||||
gSitesList.selectedItem = testSiteItem;
|
||||
|
||||
let siteHeader = gBrowser.contentDocument.getElementById("site-header");
|
||||
is(siteHeader, gHeaderDeck.selectedPanel,
|
||||
"correct header shown for a specific site");
|
||||
is(gSiteLabel.value, TEST_URI_2.host, "header updated for selected site");
|
||||
is(gSiteLabel.value, TEST_URI_2.prePath, "header updated for selected site");
|
||||
|
||||
ok(!gBrowser.contentDocument.getElementById("passwords-count").hidden,
|
||||
"passwords count is not hidden");
|
||||
|
@ -283,7 +283,7 @@ var tests = [
|
|||
"all sites item selected after forgetting selected site");
|
||||
|
||||
// check to make sure site is gone from sites list
|
||||
let testSiteItem = getSiteItem(TEST_URI_2.host);
|
||||
let testSiteItem = getSiteItem(TEST_URI_2.prePath);
|
||||
ok(!testSiteItem, "site removed from sites list");
|
||||
|
||||
// check to make sure we forgot all permissions corresponding to site
|
||||
|
|
|
@ -9,6 +9,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gLangBundle", () =>
|
||||
Services.strings.createBundle("chrome://global/locale/languageNames.properties"));
|
||||
|
@ -83,7 +84,7 @@ let gTranslationExceptions = {
|
|||
|
||||
if (perm.type == kPermissionType &&
|
||||
perm.capability == Services.perms.DENY_ACTION) {
|
||||
this._sites.push(perm.host);
|
||||
this._sites.push(perm.principal.origin);
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(this, "perm-changed", false);
|
||||
|
@ -126,14 +127,14 @@ let gTranslationExceptions = {
|
|||
if (aData == "added") {
|
||||
if (perm.capability != Services.perms.DENY_ACTION)
|
||||
return;
|
||||
this._sites.push(perm.host);
|
||||
this._sites.push(perm.principal.origin);
|
||||
this._sites.sort();
|
||||
let boxObject = this._siteTree.boxObject;
|
||||
boxObject.rowCountChanged(0, 1);
|
||||
boxObject.invalidate();
|
||||
}
|
||||
else if (aData == "deleted") {
|
||||
let index = this._sites.indexOf(perm.host);
|
||||
let index = this._sites.indexOf(perm.principal.origin);
|
||||
if (index == -1)
|
||||
return;
|
||||
this._sites.splice(index, 1);
|
||||
|
@ -188,9 +189,9 @@ let gTranslationExceptions = {
|
|||
|
||||
onSiteDeleted: function() {
|
||||
let removedSites = this._siteTree.getSelectedItems();
|
||||
for (let host of removedSites) {
|
||||
let uri = Services.io.newURI("http://" + host, null, null);
|
||||
Services.perms.remove(uri, kPermissionType);
|
||||
for (let origin of removedSites) {
|
||||
let principal = BrowserUtils.principalFromOrigin(origin);
|
||||
Services.perms.removeFromPrincipal(principal, kPermissionType);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -201,9 +202,9 @@ let gTranslationExceptions = {
|
|||
let removedSites = this._sites.splice(0, this._sites.length);
|
||||
this._siteTree.boxObject.rowCountChanged(0, -removedSites.length);
|
||||
|
||||
for (let host of removedSites) {
|
||||
let uri = Services.io.newURI("http://" + host, null, null);
|
||||
Services.perms.remove(uri, kPermissionType);
|
||||
for (let origin of removedSites) {
|
||||
let principal = BrowserUtils.principalFromOrigin(origin);
|
||||
Services.perms.removeFromPrincipal(principal, kPermissionType);
|
||||
}
|
||||
|
||||
this.onSiteSelected();
|
||||
|
|
|
@ -51,7 +51,7 @@ function getDomainExceptions() {
|
|||
|
||||
if (perm.type == "translate" &&
|
||||
perm.capability == Services.perms.DENY_ACTION)
|
||||
results.push(perm.host);
|
||||
results.push(perm.principal);
|
||||
}
|
||||
|
||||
return results;
|
||||
|
@ -181,7 +181,7 @@ let gTests = [
|
|||
// Check this has been saved to the exceptions list.
|
||||
let sites = getDomainExceptions();
|
||||
is(sites.length, 1, "one site in the exception list");
|
||||
is(sites[0], "example.com", "correct site in the exception list");
|
||||
is(sites[0].origin, "http://example.com", "correct site in the exception list");
|
||||
ok(!ui.shouldShowInfoBar(uri, "fr"),
|
||||
"the infobar wouldn't be shown anymore");
|
||||
|
||||
|
|
|
@ -198,8 +198,10 @@ function loadUITourTestPage(callback, host = "https://example.com/") {
|
|||
|
||||
function UITourTest() {
|
||||
Services.prefs.setBoolPref("browser.uitour.enabled", true);
|
||||
let testUri = Services.io.newURI("http://example.com", null, null);
|
||||
Services.perms.add(testUri, "uitour", Services.perms.ALLOW_ACTION);
|
||||
let testHttpsUri = Services.io.newURI("https://example.com", null, null);
|
||||
let testHttpUri = Services.io.newURI("http://example.com", null, null);
|
||||
Services.perms.add(testHttpsUri, "uitour", Services.perms.ALLOW_ACTION);
|
||||
Services.perms.add(testHttpUri, "uitour", Services.perms.ALLOW_ACTION);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
|
@ -210,7 +212,8 @@ function UITourTest() {
|
|||
gBrowser.removeTab(gTestTab);
|
||||
delete window.gTestTab;
|
||||
Services.prefs.clearUserPref("browser.uitour.enabled", true);
|
||||
Services.perms.remove(testUri, "uitour");
|
||||
Services.perms.remove(testHttpsUri, "uitour");
|
||||
Services.perms.remove(testHttpUri, "uitour");
|
||||
});
|
||||
|
||||
function done() {
|
||||
|
|
|
@ -224,7 +224,7 @@ function test() {
|
|||
"The first source should be currently selected.");
|
||||
|
||||
let window = gEditor.container.contentWindow;
|
||||
executeSoon(() => window.mozRequestAnimationFrame(onReadyForClick));
|
||||
executeSoon(() => window.requestAnimationFrame(onReadyForClick));
|
||||
}
|
||||
|
||||
function onReadyForClick() {
|
||||
|
|
|
@ -453,6 +453,7 @@ TiltVisualizer.Presenter.prototype = {
|
|||
_loop: function TVP__loop()
|
||||
{
|
||||
let renderer = this._renderer;
|
||||
let frameStartTime = this.chromeWindow.performance.now();
|
||||
|
||||
// if the renderer was destroyed, don't continue rendering
|
||||
if (!renderer || !renderer.context) {
|
||||
|
@ -460,7 +461,7 @@ TiltVisualizer.Presenter.prototype = {
|
|||
}
|
||||
|
||||
// prepare for the next frame of the animation loop
|
||||
this.chromeWindow.mozRequestAnimationFrame(this._loop);
|
||||
this.chromeWindow.requestAnimationFrame(this._loop);
|
||||
|
||||
// only redraw if we really have to
|
||||
if (this._redraw) {
|
||||
|
@ -473,17 +474,17 @@ TiltVisualizer.Presenter.prototype = {
|
|||
this._controllerUpdate(this._time, this._delta);
|
||||
}
|
||||
|
||||
this._handleFrameDelta();
|
||||
this._handleFrameDelta(frameStartTime);
|
||||
this._handleKeyframeNotifications();
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates the current frame delta time.
|
||||
*/
|
||||
_handleFrameDelta: function TVP__handleFrameDelta()
|
||||
_handleFrameDelta: function TVP__handleFrameDelta(frameStartTime)
|
||||
{
|
||||
this._prevFrameTime = this._currFrameTime;
|
||||
this._currFrameTime = this.chromeWindow.mozAnimationStartTime;
|
||||
this._currFrameTime = frameStartTime;
|
||||
this._delta = this._currFrameTime - this._prevFrameTime;
|
||||
},
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ function test() {
|
|||
loadTab(TEST_URI2).then((tab) => {
|
||||
tabs.push(tab.tab);
|
||||
openConsole().then((hud) => {
|
||||
hud.iframeWindow.mozRequestAnimationFrame(startTest);
|
||||
hud.iframeWindow.requestAnimationFrame(startTest);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ function test() {
|
|||
loadTab(TEST_URI1).then((tab) => {
|
||||
tabs.push(tab.tab);
|
||||
openConsole().then((hud) => {
|
||||
hud.iframeWindow.mozRequestAnimationFrame(() => {
|
||||
hud.iframeWindow.requestAnimationFrame(() => {
|
||||
info("iframe1 root height " + hud.ui.rootElement.clientHeight);
|
||||
|
||||
openTab();
|
||||
|
|
|
@ -9,15 +9,13 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
MOZ_PKG_REMOVALS = $(srcdir)/removed-files.in
|
||||
|
||||
MOZ_PKG_MANIFEST_P = $(srcdir)/package-manifest.in
|
||||
|
||||
ifdef MOZ_MULET
|
||||
MOZ_PKG_MANIFEST_P += $(topsrcdir)/b2g/installer/package-manifest.in
|
||||
endif
|
||||
MOZ_PKG_MANIFEST = $(srcdir)/package-manifest.in
|
||||
|
||||
# Some files have been already bundled with xulrunner
|
||||
ifndef MOZ_MULET
|
||||
MOZ_PKG_FATAL_WARNINGS = 1
|
||||
else
|
||||
DEFINES += -DMOZ_MULET
|
||||
endif
|
||||
|
||||
DEFINES += -DMOZ_APP_NAME=$(MOZ_APP_NAME) -DPREF_DIR=$(PREF_DIR)
|
||||
|
@ -98,15 +96,6 @@ ifdef MAKENSISU
|
|||
DEFINES += -DHAVE_MAKENSISU=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
MOZ_PKG_MANIFEST = package-manifest
|
||||
|
||||
$(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P) $(GLOBAL_DEPS)
|
||||
$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) $(MOZ_PKG_MANIFEST_P) -o $@)
|
||||
|
||||
GARBAGE += $(MOZ_PKG_MANIFEST)
|
||||
endif
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
MOZ_PKG_MAC_DSSTORE=branding/dsstore
|
||||
MOZ_PKG_MAC_BACKGROUND=branding/background.png
|
||||
|
@ -180,13 +169,11 @@ else
|
|||
FINDPATH=bin
|
||||
endif
|
||||
|
||||
package-compare:: $(MOZ_PKG_MANIFEST)
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
package-compare::
|
||||
cd $(DIST); find $(PKGCOMP_FIND_OPTS) $(FINDPATH) -type f | sort > bin-list.txt
|
||||
grep '^$(BINPATH)' $(MOZ_PKG_MANIFEST) | sed -e 's/^\///' | sort > $(DIST)/pack-list.txt
|
||||
$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) $(MOZ_PKG_MANIFEST)) | grep '^$(BINPATH)' | sed -e 's/^\///' | sort > $(DIST)/pack-list.txt
|
||||
-diff -u $(DIST)/pack-list.txt $(DIST)/bin-list.txt
|
||||
rm -f $(DIST)/pack-list.txt $(DIST)/bin-list.txt
|
||||
endif
|
||||
|
||||
installer::
|
||||
ifdef INSTALLER_DIR
|
||||
|
|
|
@ -917,3 +917,7 @@ bin/libfreebl_32int64_3.so
|
|||
@RESPATH@/components/GfxSanityTest.manifest
|
||||
@RESPATH@/components/SanityTest.js
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_MULET
|
||||
#include ../../b2g/installer/package-manifest.in
|
||||
#endif
|
||||
|
|
|
@ -199,6 +199,9 @@ PluginContent.prototype = {
|
|||
*/
|
||||
setVisibility : function (plugin, overlay, shouldShow) {
|
||||
overlay.classList.toggle("visible", shouldShow);
|
||||
if (shouldShow) {
|
||||
overlay.removeAttribute("dismissed");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -434,8 +437,8 @@ PluginContent.prototype = {
|
|||
}
|
||||
|
||||
// Show the in-content UI if it's not too big. The crashed plugin handler already did this.
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (eventType != "PluginCrashed") {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (overlay != null) {
|
||||
this.setVisibility(plugin, overlay,
|
||||
this.shouldShowOverlay(plugin, overlay));
|
||||
|
@ -452,8 +455,10 @@ PluginContent.prototype = {
|
|||
let closeIcon = this.getPluginUI(plugin, "closeIcon");
|
||||
if (closeIcon) {
|
||||
closeIcon.addEventListener("click", event => {
|
||||
if (event.button == 0 && event.isTrusted)
|
||||
if (event.button == 0 && event.isTrusted) {
|
||||
this.hideClickToPlayOverlay(plugin);
|
||||
overlay.setAttribute("dismissed", "true");
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
@ -627,7 +632,7 @@ PluginContent.prototype = {
|
|||
// Have to check that the target is not the link to update the plugin
|
||||
if (!(event.originalTarget instanceof contentWindow.HTMLAnchorElement) &&
|
||||
(event.originalTarget.getAttribute('anonid') != 'closeIcon') &&
|
||||
overlay.classList.contains('visible') &&
|
||||
!overlay.hasAttribute('dismissed') &&
|
||||
event.button == 0 &&
|
||||
event.isTrusted) {
|
||||
this._showClickToPlayNotification(plugin, true);
|
||||
|
@ -695,20 +700,6 @@ PluginContent.prototype = {
|
|||
this._showClickToPlayNotification(null, false);
|
||||
},
|
||||
|
||||
// Match the behaviour of nsPermissionManager
|
||||
_getHostFromPrincipal: function (principal) {
|
||||
if (!principal.URI || principal.URI.schemeIs("moz-nullprincipal")) {
|
||||
return "(null)";
|
||||
}
|
||||
|
||||
try {
|
||||
if (principal.URI.host)
|
||||
return principal.URI.host;
|
||||
} catch (e) {}
|
||||
|
||||
return principal.origin;
|
||||
},
|
||||
|
||||
/**
|
||||
* Activate the plugins that the user has specified.
|
||||
*/
|
||||
|
@ -776,7 +767,6 @@ PluginContent.prototype = {
|
|||
let pluginData = this.pluginData;
|
||||
|
||||
let principal = this.content.document.nodePrincipal;
|
||||
let principalHost = this._getHostFromPrincipal(principal);
|
||||
let location = this.content.document.location.href;
|
||||
|
||||
for (let p of plugins) {
|
||||
|
@ -792,11 +782,11 @@ PluginContent.prototype = {
|
|||
let permissionObj = Services.perms.
|
||||
getPermissionObject(principal, pluginInfo.permissionString, false);
|
||||
if (permissionObj) {
|
||||
pluginInfo.pluginPermissionHost = permissionObj.host;
|
||||
pluginInfo.pluginPermissionPrePath = permissionObj.principal.originNoSuffix;
|
||||
pluginInfo.pluginPermissionType = permissionObj.expireType;
|
||||
}
|
||||
else {
|
||||
pluginInfo.pluginPermissionHost = principalHost;
|
||||
pluginInfo.pluginPermissionPrePath = principal.originNoSuffix;
|
||||
pluginInfo.pluginPermissionType = undefined;
|
||||
}
|
||||
|
||||
|
@ -806,7 +796,6 @@ PluginContent.prototype = {
|
|||
this.global.sendAsyncMessage("PluginContent:ShowClickToPlayNotification", {
|
||||
plugins: [... this.pluginData.values()],
|
||||
showNow: showNow,
|
||||
host: principalHost,
|
||||
location: location,
|
||||
}, null, principal);
|
||||
},
|
||||
|
@ -889,7 +878,6 @@ PluginContent.prototype = {
|
|||
this.global.sendAsyncMessage("PluginContent:UpdateHiddenPluginUI", {
|
||||
haveInsecure: haveInsecure,
|
||||
actions: [... actions.values()],
|
||||
host: this._getHostFromPrincipal(principal),
|
||||
location: location,
|
||||
}, null, principal);
|
||||
},
|
||||
|
|
|
@ -122,6 +122,13 @@ processor
|
|||
|
||||
Always defined.
|
||||
|
||||
release_build
|
||||
Whether this is a release build.
|
||||
|
||||
Values are ``true`` and ``false``.
|
||||
|
||||
Always defined.
|
||||
|
||||
tests_enabled
|
||||
Whether tests are enabled for this build.
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import traceback
|
|||
import zipfile
|
||||
|
||||
from automation import Automation
|
||||
from mozlog.structured import get_default_logger
|
||||
from mozlog import get_default_logger
|
||||
from mozprocess import ProcessHandlerMixin
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import sys
|
|||
|
||||
from automation import Automation
|
||||
from devicemanager import DMError, DeviceManager
|
||||
from mozlog.structured import get_default_logger
|
||||
from mozlog import get_default_logger
|
||||
import mozcrash
|
||||
|
||||
# signatures for logcat messages that we don't care about much
|
||||
|
|
|
@ -51,7 +51,7 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
|
|||
|
||||
params->Serialize(value);
|
||||
if (!value.IsEmpty()) {
|
||||
aStr.AppendLiteral("!");
|
||||
aStr.AppendLiteral("^");
|
||||
aStr.Append(NS_ConvertUTF16toUTF8(value));
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ OriginAttributes::PopulateFromSuffix(const nsACString& aStr)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (aStr[0] != '!') {
|
||||
if (aStr[0] != '^') {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin,
|
|||
{
|
||||
// RFindChar is only available on nsCString.
|
||||
nsCString origin(aOrigin);
|
||||
int32_t pos = origin.RFindChar('!');
|
||||
int32_t pos = origin.RFindChar('^');
|
||||
|
||||
if (pos == kNotFound) {
|
||||
aOriginNoSuffix = origin;
|
||||
|
@ -156,6 +156,15 @@ BasePrincipal::GetOrigin(nsACString& aOrigin)
|
|||
{
|
||||
nsresult rv = GetOriginInternal(aOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// OriginAttributes::CreateSuffix asserts against UNKNOWN_APP_ID. It's trivial
|
||||
// to trigger this getter from script on such a principal, so we handle it
|
||||
// here at the API entry point.
|
||||
if (mOriginAttributes.mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
NS_WARNING("Refusing to provide canonical origin string to principal with UNKNOWN_APP_ID");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString suffix;
|
||||
mOriginAttributes.CreateSuffix(suffix);
|
||||
aOrigin.Append(suffix);
|
||||
|
|
|
@ -62,7 +62,7 @@ DomainPolicy::~DomainPolicy()
|
|||
NS_IMETHODIMP
|
||||
DomainPolicy::GetBlacklist(nsIDomainSet** aSet)
|
||||
{
|
||||
nsCOMPtr<nsIDomainSet> set = mBlacklist;
|
||||
nsCOMPtr<nsIDomainSet> set = mBlacklist.get();
|
||||
set.forget(aSet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ DomainPolicy::GetBlacklist(nsIDomainSet** aSet)
|
|||
NS_IMETHODIMP
|
||||
DomainPolicy::GetSuperBlacklist(nsIDomainSet** aSet)
|
||||
{
|
||||
nsCOMPtr<nsIDomainSet> set = mSuperBlacklist;
|
||||
nsCOMPtr<nsIDomainSet> set = mSuperBlacklist.get();
|
||||
set.forget(aSet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ DomainPolicy::GetSuperBlacklist(nsIDomainSet** aSet)
|
|||
NS_IMETHODIMP
|
||||
DomainPolicy::GetWhitelist(nsIDomainSet** aSet)
|
||||
{
|
||||
nsCOMPtr<nsIDomainSet> set = mWhitelist;
|
||||
nsCOMPtr<nsIDomainSet> set = mWhitelist.get();
|
||||
set.forget(aSet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ DomainPolicy::GetWhitelist(nsIDomainSet** aSet)
|
|||
NS_IMETHODIMP
|
||||
DomainPolicy::GetSuperWhitelist(nsIDomainSet** aSet)
|
||||
{
|
||||
nsCOMPtr<nsIDomainSet> set = mSuperWhitelist;
|
||||
nsCOMPtr<nsIDomainSet> set = mSuperWhitelist.get();
|
||||
set.forget(aSet);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -122,10 +122,10 @@ void
|
|||
DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone)
|
||||
{
|
||||
aClone->active() = true;
|
||||
static_cast<DomainSet*>(mBlacklist.get())->CloneSet(&aClone->blacklist());
|
||||
static_cast<DomainSet*>(mSuperBlacklist.get())->CloneSet(&aClone->superBlacklist());
|
||||
static_cast<DomainSet*>(mWhitelist.get())->CloneSet(&aClone->whitelist());
|
||||
static_cast<DomainSet*>(mSuperWhitelist.get())->CloneSet(&aClone->superWhitelist());
|
||||
mBlacklist->CloneSet(&aClone->blacklist());
|
||||
mSuperBlacklist->CloneSet(&aClone->superBlacklist());
|
||||
mWhitelist->CloneSet(&aClone->whitelist());
|
||||
mSuperWhitelist->CloneSet(&aClone->superWhitelist());
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -246,24 +246,17 @@ DomainSet::GetType(uint32_t* aType)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static
|
||||
PLDHashOperator
|
||||
DomainEnumerator(nsURIHashKey* aEntry, void* aUserArg)
|
||||
{
|
||||
InfallibleTArray<URIParams>* uris = static_cast<InfallibleTArray<URIParams>*>(aUserArg);
|
||||
nsIURI* key = aEntry->GetKey();
|
||||
|
||||
URIParams uri;
|
||||
SerializeURI(key, uri);
|
||||
|
||||
uris->AppendElement(uri);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
DomainSet::CloneSet(InfallibleTArray<URIParams>* aDomains)
|
||||
{
|
||||
mHashTable.EnumerateEntries(DomainEnumerator, aDomains);
|
||||
for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsIURI* key = iter.Get()->GetKey();
|
||||
|
||||
URIParams uri;
|
||||
SerializeURI(key, uri);
|
||||
|
||||
aDomains->AppendElement(uri);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
|
|
@ -33,23 +33,7 @@ enum DomainSetType{
|
|||
SUPER_WHITELIST
|
||||
};
|
||||
|
||||
class DomainPolicy : public nsIDomainPolicy
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMAINPOLICY
|
||||
DomainPolicy();
|
||||
|
||||
private:
|
||||
virtual ~DomainPolicy();
|
||||
|
||||
nsCOMPtr<nsIDomainSet> mBlacklist;
|
||||
nsCOMPtr<nsIDomainSet> mSuperBlacklist;
|
||||
nsCOMPtr<nsIDomainSet> mWhitelist;
|
||||
nsCOMPtr<nsIDomainSet> mSuperWhitelist;
|
||||
};
|
||||
|
||||
class DomainSet : public nsIDomainSet
|
||||
class DomainSet final : public nsIDomainSet
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -67,6 +51,22 @@ protected:
|
|||
DomainSetType mType;
|
||||
};
|
||||
|
||||
class DomainPolicy final : public nsIDomainPolicy
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMAINPOLICY
|
||||
DomainPolicy();
|
||||
|
||||
private:
|
||||
virtual ~DomainPolicy();
|
||||
|
||||
nsRefPtr<DomainSet> mBlacklist;
|
||||
nsRefPtr<DomainSet> mSuperBlacklist;
|
||||
nsRefPtr<DomainSet> mWhitelist;
|
||||
nsRefPtr<DomainSet> mSuperWhitelist;
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* DomainPolicy_h__ */
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "pratom.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIStandardURL.h"
|
||||
#include "nsIURIWithPrincipal.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsIEffectiveTLDService.h"
|
||||
|
@ -127,6 +128,31 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
|
|||
}
|
||||
}
|
||||
|
||||
// We want the invariant that prinA.origin == prinB.origin i.f.f.
|
||||
// prinA.equals(prinB). However, this requires that we impose certain constraints
|
||||
// on the behavior and origin semantics of principals, and in particular, forbid
|
||||
// creating origin strings for principals whose equality constraints are not
|
||||
// expressible as strings (i.e. object equality). Moreover, we want to forbid URIs
|
||||
// containing the magic "^" we use as a separating character for origin
|
||||
// attributes.
|
||||
//
|
||||
// These constraints can generally be achieved by restricting .origin to
|
||||
// nsIStandardURL-based URIs, but there are a few other URI schemes that we need
|
||||
// to handle.
|
||||
bool isBehaved;
|
||||
if ((NS_SUCCEEDED(origin->SchemeIs("about", &isBehaved)) && isBehaved) ||
|
||||
(NS_SUCCEEDED(origin->SchemeIs("moz-safe-about", &isBehaved)) && isBehaved) ||
|
||||
(NS_SUCCEEDED(origin->SchemeIs("indexeddb", &isBehaved)) && isBehaved)) {
|
||||
rv = origin->GetAsciiSpec(aOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// These URIs could technically contain a '^', but they never should.
|
||||
if (NS_WARN_IF(aOrigin.FindChar('^', 0) != -1)) {
|
||||
aOrigin.Truncate();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t port;
|
||||
if (NS_SUCCEEDED(rv) && !isChrome) {
|
||||
rv = origin->GetPort(&port);
|
||||
|
@ -144,6 +170,14 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
|
|||
aOrigin.Append(hostPort);
|
||||
}
|
||||
else {
|
||||
// If we reached this branch, we can only create an origin if we have a nsIStandardURL.
|
||||
// So, we query to a nsIStandardURL, and fail if we aren't an instance of an nsIStandardURL
|
||||
// nsIStandardURLs have the good property of escaping the '^' character in their specs,
|
||||
// which means that we can be sure that the caret character (which is reserved for delimiting
|
||||
// the end of the spec, and the beginning of the origin attributes) is not present in the
|
||||
// origin string
|
||||
nsCOMPtr<nsIStandardURL> standardURL = do_QueryInterface(origin);
|
||||
NS_ENSURE_TRUE(standardURL, NS_ERROR_FAILURE);
|
||||
rv = origin->GetAsciiSpec(aOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
|
|
@ -65,33 +65,37 @@ function run_test() {
|
|||
// Just app.
|
||||
var exampleOrg_app = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 42});
|
||||
var nullPrin_app = ssm.createNullPrincipal({appId: 42});
|
||||
checkOriginAttributes(exampleOrg_app, {appId: 42}, '!appId=42');
|
||||
checkOriginAttributes(nullPrin_app, {appId: 42}, '!appId=42');
|
||||
do_check_eq(exampleOrg_app.origin, 'http://example.org!appId=42');
|
||||
checkOriginAttributes(exampleOrg_app, {appId: 42}, '^appId=42');
|
||||
checkOriginAttributes(nullPrin_app, {appId: 42}, '^appId=42');
|
||||
do_check_eq(exampleOrg_app.origin, 'http://example.org^appId=42');
|
||||
|
||||
// Just browser.
|
||||
var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true});
|
||||
var nullPrin_browser = ssm.createNullPrincipal({inBrowser: true});
|
||||
checkOriginAttributes(exampleOrg_browser, {inBrowser: true}, '!inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_browser, {inBrowser: true}, '!inBrowser=1');
|
||||
do_check_eq(exampleOrg_browser.origin, 'http://example.org!inBrowser=1');
|
||||
checkOriginAttributes(exampleOrg_browser, {inBrowser: true}, '^inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_browser, {inBrowser: true}, '^inBrowser=1');
|
||||
do_check_eq(exampleOrg_browser.origin, 'http://example.org^inBrowser=1');
|
||||
|
||||
// App and browser.
|
||||
var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true, appId: 42});
|
||||
var nullPrin_appBrowser = ssm.createNullPrincipal({inBrowser: true, appId: 42});
|
||||
checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1');
|
||||
do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org!appId=42&inBrowser=1');
|
||||
checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
|
||||
do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org^appId=42&inBrowser=1');
|
||||
|
||||
// App and browser, different domain.
|
||||
var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inBrowser: true});
|
||||
checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1');
|
||||
do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123!appId=42&inBrowser=1');
|
||||
checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inBrowser: true}, '^appId=42&inBrowser=1');
|
||||
do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123^appId=42&inBrowser=1');
|
||||
|
||||
// Addon.
|
||||
var exampleOrg_addon = ssm.createCodebasePrincipal(makeURI('http://example.org'), {addonId: 'dummy'});
|
||||
checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '!addonId=dummy');
|
||||
do_check_eq(exampleOrg_addon.origin, 'http://example.org!addonId=dummy');
|
||||
checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '^addonId=dummy');
|
||||
do_check_eq(exampleOrg_addon.origin, 'http://example.org^addonId=dummy');
|
||||
|
||||
// Make sure that we refuse to create .origin for principals with UNKNOWN_APP_ID.
|
||||
var simplePrin = ssm.getSimpleCodebasePrincipal(makeURI('http://example.com'));
|
||||
try { simplePrin.origin; do_check_true(false); } catch (e) { do_check_true(true); }
|
||||
|
||||
// Check that all of the above are cross-origin.
|
||||
checkCrossOrigin(exampleOrg_app, exampleOrg);
|
||||
|
|
|
@ -1607,12 +1607,20 @@ nsDocShell::LoadURI(nsIURI* aURI,
|
|||
|
||||
if (owner && mItemType != typeChrome) {
|
||||
nsCOMPtr<nsIPrincipal> ownerPrincipal = do_QueryInterface(owner);
|
||||
if (nsContentUtils::IsSystemOrExpandedPrincipal(ownerPrincipal)) {
|
||||
if (nsContentUtils::IsSystemPrincipal(ownerPrincipal)) {
|
||||
if (ownerIsExplicit) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
owner = nullptr;
|
||||
inheritOwner = true;
|
||||
} else if (nsContentUtils::IsExpandedPrincipal(ownerPrincipal)) {
|
||||
if (ownerIsExplicit) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
// Don't inherit from the current page. Just do the safe thing
|
||||
// and pretend that we were loaded by a nullprincipal.
|
||||
owner = nsNullPrincipal::Create();
|
||||
inheritOwner = false;
|
||||
}
|
||||
}
|
||||
if (!owner && !inheritOwner && !ownerIsExplicit) {
|
||||
|
@ -3711,12 +3719,10 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
|
|||
static bool
|
||||
ItemIsActive(nsIDocShellTreeItem* aItem)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> window = aItem->GetWindow();
|
||||
|
||||
if (window) {
|
||||
bool isClosed;
|
||||
|
||||
if (NS_SUCCEEDED(window->GetClosed(&isClosed)) && !isClosed) {
|
||||
if (nsCOMPtr<nsIDOMWindow> window = aItem->GetWindow()) {
|
||||
auto* win = static_cast<nsGlobalWindow*>(window.get());
|
||||
MOZ_ASSERT(win->IsOuterWindow());
|
||||
if (!win->GetClosedOuter()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,6 +143,12 @@ this.PermissionsTable = { geolocation: {
|
|||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
"browser:universalxss": {
|
||||
app: DENY_ACTION,
|
||||
trusted: DENY_ACTION,
|
||||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
bluetooth: {
|
||||
app: DENY_ACTION,
|
||||
trusted: DENY_ACTION,
|
||||
|
|
|
@ -51,7 +51,7 @@ add_test(() => {
|
|||
});
|
||||
|
||||
Assert.ok(mozapp.principal, "app principal should exist");
|
||||
let expectedPrincipalOrigin = app.origin + "!appId=" + app.localId;
|
||||
let expectedPrincipalOrigin = app.origin + "^appId=" + app.localId;
|
||||
Assert.equal(mozapp.principal.origin, expectedPrincipalOrigin,
|
||||
"app principal origin ok");
|
||||
Assert.equal(mozapp.principal.appId, app.localId, "app principal appId ok");
|
||||
|
|
|
@ -83,10 +83,8 @@ nsDOMWindowList::GetLength(uint32_t* aLength)
|
|||
}
|
||||
|
||||
already_AddRefed<nsIDOMWindow>
|
||||
nsDOMWindowList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
||||
nsDOMWindowList::IndexedGetter(uint32_t aIndex)
|
||||
{
|
||||
aFound = false;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> item = GetDocShellTreeItemAt(aIndex);
|
||||
if (!item) {
|
||||
return nullptr;
|
||||
|
@ -95,15 +93,13 @@ nsDOMWindowList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
|||
nsCOMPtr<nsIDOMWindow> window = item->GetWindow();
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
aFound = true;
|
||||
return window.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowList::Item(uint32_t aIndex, nsIDOMWindow** aReturn)
|
||||
{
|
||||
bool found;
|
||||
nsCOMPtr<nsIDOMWindow> window = IndexedGetter(aIndex, found);
|
||||
nsCOMPtr<nsIDOMWindow> window = IndexedGetter(aIndex);
|
||||
window.forget(aReturn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
NS_DECL_NSIDOMWINDOWCOLLECTION
|
||||
|
||||
uint32_t GetLength();
|
||||
already_AddRefed<nsIDOMWindow> IndexedGetter(uint32_t aIndex, bool& aFound);
|
||||
already_AddRefed<nsIDOMWindow> IndexedGetter(uint32_t aIndex);
|
||||
|
||||
//local methods
|
||||
NS_IMETHOD SetDocShell(nsIDocShell* aDocShell);
|
||||
|
|
|
@ -2343,6 +2343,19 @@ GK_ATOM(toolbarspring, "toolbarspring")
|
|||
GK_ATOM(treegrid, "treegrid")
|
||||
GK_ATOM(_undefined, "undefined")
|
||||
GK_ATOM(xmlroles, "xml-roles")
|
||||
|
||||
// MathML xml roles
|
||||
GK_ATOM(close_fence, "close-fence")
|
||||
GK_ATOM(denominator, "denominator")
|
||||
GK_ATOM(numerator, "numerator")
|
||||
GK_ATOM(open_fence, "open-fence")
|
||||
GK_ATOM(overscript, "overscript")
|
||||
GK_ATOM(presubscript, "presubscript")
|
||||
GK_ATOM(presuperscript, "presuperscript")
|
||||
GK_ATOM(root_index, "root-index")
|
||||
GK_ATOM(subscript, "subscript")
|
||||
GK_ATOM(superscript, "superscript")
|
||||
GK_ATOM(underscript, "underscript")
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -27,7 +27,6 @@
|
|||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIDOMJSWindow.h"
|
||||
#include "nsIDOMChromeWindow.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
|
@ -325,7 +324,6 @@ class nsGlobalWindow : public mozilla::dom::EventTarget,
|
|||
public nsPIDOMWindow,
|
||||
public nsIScriptGlobalObject,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIDOMJSWindow,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIInterfaceRequestor,
|
||||
public PRCListStr
|
||||
|
@ -385,8 +383,15 @@ public:
|
|||
// nsIDOMWindow
|
||||
NS_DECL_NSIDOMWINDOW
|
||||
|
||||
// nsIDOMJSWindow
|
||||
NS_DECL_NSIDOMJSWINDOW
|
||||
nsresult
|
||||
OpenJS(const nsAString& aUrl, const nsAString& aName,
|
||||
const nsAString& aOptions, nsIDOMWindow **_retval);
|
||||
void CaptureEvents();
|
||||
void ReleaseEvents();
|
||||
void Dump(const nsAString& aStr);
|
||||
void SetResizable(bool aResizable) const;
|
||||
nsresult GetScriptableContent(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aVal);
|
||||
|
||||
// nsIDOMEventTarget
|
||||
NS_DECL_NSIDOMEVENTTARGET
|
||||
|
@ -501,7 +506,8 @@ public:
|
|||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
// WebIDL interface.
|
||||
already_AddRefed<nsIDOMWindow> IndexedGetter(uint32_t aIndex, bool& aFound);
|
||||
already_AddRefed<nsIDOMWindow> IndexedGetterOuter(uint32_t aIndex);
|
||||
already_AddRefed<nsIDOMWindow> IndexedGetter(uint32_t aIndex);
|
||||
|
||||
void GetSupportedNames(nsTArray<nsString>& aNames);
|
||||
|
||||
|
@ -857,7 +863,9 @@ public:
|
|||
{
|
||||
return GetDoc();
|
||||
}
|
||||
void GetNameOuter(nsAString& aName);
|
||||
void GetName(nsAString& aName, mozilla::ErrorResult& aError);
|
||||
void SetNameOuter(const nsAString& aName, mozilla::ErrorResult& aError);
|
||||
void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
|
||||
nsLocation* GetLocation(mozilla::ErrorResult& aError);
|
||||
nsHistory* GetHistory(mozilla::ErrorResult& aError);
|
||||
|
@ -867,23 +875,28 @@ public:
|
|||
mozilla::dom::BarProp* GetScrollbars(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetStatusbar(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetToolbar(mozilla::ErrorResult& aError);
|
||||
void GetStatusOuter(nsAString& aStatus);
|
||||
void GetStatus(nsAString& aStatus, mozilla::ErrorResult& aError);
|
||||
void SetStatusOuter(const nsAString& aStatus);
|
||||
void SetStatus(const nsAString& aStatus, mozilla::ErrorResult& aError);
|
||||
void CloseOuter();
|
||||
void Close(mozilla::ErrorResult& aError);
|
||||
bool GetClosedOuter();
|
||||
bool GetClosed(mozilla::ErrorResult& aError);
|
||||
void StopOuter(mozilla::ErrorResult& aError);
|
||||
void Stop(mozilla::ErrorResult& aError);
|
||||
void FocusOuter(mozilla::ErrorResult& aError);
|
||||
void Focus(mozilla::ErrorResult& aError);
|
||||
void BlurOuter();
|
||||
void Blur(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> GetFramesOuter();
|
||||
already_AddRefed<nsIDOMWindow> GetFrames(mozilla::ErrorResult& aError);
|
||||
uint32_t Length();
|
||||
already_AddRefed<nsIDOMWindow> GetTop(mozilla::ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> top;
|
||||
aError = GetScriptableTop(getter_AddRefs(top));
|
||||
return top.forget();
|
||||
}
|
||||
already_AddRefed<nsIDOMWindow> GetTopOuter(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> GetTop(mozilla::ErrorResult& aError);
|
||||
protected:
|
||||
explicit nsGlobalWindow(nsGlobalWindow *aOuterWindow);
|
||||
nsIDOMWindow* GetOpenerWindowOuter();
|
||||
nsIDOMWindow* GetOpenerWindow(mozilla::ErrorResult& aError);
|
||||
// Initializes the mWasOffline member variable
|
||||
void InitWasOffline();
|
||||
|
@ -893,8 +906,14 @@ public:
|
|||
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
mozilla::ErrorResult& aError);
|
||||
using nsIDOMWindow::GetParent;
|
||||
already_AddRefed<nsIDOMWindow> GetParentOuter(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> GetParent(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Element* GetFrameElementOuter();
|
||||
mozilla::dom::Element* GetFrameElement(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> OpenOuter(const nsAString& aUrl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOptions,
|
||||
mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> Open(const nsAString& aUrl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOptions,
|
||||
|
@ -921,14 +940,19 @@ protected:
|
|||
|
||||
public:
|
||||
void Alert(mozilla::ErrorResult& aError);
|
||||
void AlertOuter(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
void Alert(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
already_AddRefed<mozilla::dom::cache::CacheStorage> GetCaches(mozilla::ErrorResult& aRv);
|
||||
bool ConfirmOuter(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
bool Confirm(const nsAString& aMessage, mozilla::ErrorResult& aError);
|
||||
already_AddRefed<mozilla::dom::Promise> Fetch(const mozilla::dom::RequestOrUSVString& aInput,
|
||||
const mozilla::dom::RequestInit& aInit,
|
||||
mozilla::ErrorResult& aRv);
|
||||
void PromptOuter(const nsAString& aMessage, const nsAString& aInitial,
|
||||
nsAString& aReturn, mozilla::ErrorResult& aError);
|
||||
void Prompt(const nsAString& aMessage, const nsAString& aInitial,
|
||||
nsAString& aReturn, mozilla::ErrorResult& aError);
|
||||
void PrintOuter(mozilla::ErrorResult& aError);
|
||||
void Print(mozilla::ErrorResult& aError);
|
||||
void ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
|
||||
JS::Handle<JS::Value> aArgument,
|
||||
|
@ -963,18 +987,24 @@ public:
|
|||
mozilla::ErrorResult& aError);
|
||||
mozilla::dom::DOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::DOMStorage* GetLocalStorage(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Selection* GetSelectionOuter();
|
||||
mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::indexedDB::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
|
||||
mozilla::ErrorResult& aError);
|
||||
already_AddRefed<mozilla::dom::MediaQueryList> MatchMediaOuter(const nsAString& aQuery);
|
||||
already_AddRefed<mozilla::dom::MediaQueryList> MatchMedia(const nsAString& aQuery,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsScreen* GetScreen(mozilla::ErrorResult& aError);
|
||||
void MoveToOuter(int32_t aXPos, int32_t aYPos, mozilla::ErrorResult& aError);
|
||||
void MoveTo(int32_t aXPos, int32_t aYPos, mozilla::ErrorResult& aError);
|
||||
void MoveByOuter(int32_t aXDif, int32_t aYDif, mozilla::ErrorResult& aError);
|
||||
void MoveBy(int32_t aXDif, int32_t aYDif, mozilla::ErrorResult& aError);
|
||||
void ResizeToOuter(int32_t aWidth, int32_t aHeight, mozilla::ErrorResult& aError);
|
||||
void ResizeTo(int32_t aWidth, int32_t aHeight,
|
||||
mozilla::ErrorResult& aError);
|
||||
void ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif, mozilla::ErrorResult& aError);
|
||||
void ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
|
||||
mozilla::ErrorResult& aError);
|
||||
void Scroll(double aXScroll, double aYScroll);
|
||||
|
@ -996,11 +1026,13 @@ public:
|
|||
mozilla::ErrorResult& aError);
|
||||
void SetInnerHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t GetScrollXOuter();
|
||||
int32_t GetScrollX(mozilla::ErrorResult& aError);
|
||||
int32_t GetPageXOffset(mozilla::ErrorResult& aError)
|
||||
{
|
||||
return GetScrollX(aError);
|
||||
}
|
||||
int32_t GetScrollYOuter();
|
||||
int32_t GetScrollY(mozilla::ErrorResult& aError);
|
||||
int32_t GetPageYOffset(mozilla::ErrorResult& aError)
|
||||
{
|
||||
|
@ -1026,7 +1058,6 @@ public:
|
|||
int32_t RequestAnimationFrame(mozilla::dom::FrameRequestCallback& aCallback,
|
||||
mozilla::ErrorResult& aError);
|
||||
void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError);
|
||||
nsPerformance* GetPerformance();
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
mozilla::dom::SpeechSynthesis*
|
||||
GetSpeechSynthesis(mozilla::ErrorResult& aError);
|
||||
|
@ -1047,35 +1078,59 @@ public:
|
|||
return CancelAnimationFrame(aHandle, aError);
|
||||
}
|
||||
int64_t GetMozAnimationStartTime(mozilla::ErrorResult& aError);
|
||||
void SizeToContentOuter(mozilla::ErrorResult& aError);
|
||||
void SizeToContent(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Crypto* GetCrypto(mozilla::ErrorResult& aError);
|
||||
nsIControllers* GetControllersOuter(mozilla::ErrorResult& aError);
|
||||
nsIControllers* GetControllers(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Element* GetRealFrameElementOuter();
|
||||
mozilla::dom::Element* GetRealFrameElement(mozilla::ErrorResult& aError);
|
||||
float GetMozInnerScreenXOuter();
|
||||
float GetMozInnerScreenX(mozilla::ErrorResult& aError);
|
||||
float GetMozInnerScreenYOuter();
|
||||
float GetMozInnerScreenY(mozilla::ErrorResult& aError);
|
||||
float GetDevicePixelRatioOuter();
|
||||
float GetDevicePixelRatio(mozilla::ErrorResult& aError);
|
||||
int32_t GetScrollMaxX(mozilla::ErrorResult& aError);
|
||||
int32_t GetScrollMaxY(mozilla::ErrorResult& aError);
|
||||
bool GetFullScreenOuter();
|
||||
bool GetFullScreen(mozilla::ErrorResult& aError);
|
||||
void SetFullScreenOuter(bool aFullScreen, mozilla::ErrorResult& aError);
|
||||
void SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError);
|
||||
void BackOuter(mozilla::ErrorResult& aError);
|
||||
void Back(mozilla::ErrorResult& aError);
|
||||
void ForwardOuter(mozilla::ErrorResult& aError);
|
||||
void Forward(mozilla::ErrorResult& aError);
|
||||
void HomeOuter(mozilla::ErrorResult& aError);
|
||||
void Home(mozilla::ErrorResult& aError);
|
||||
bool FindOuter(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
|
||||
bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
|
||||
bool aShowDialog, mozilla::ErrorResult& aError);
|
||||
bool Find(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
|
||||
bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
|
||||
bool aShowDialog, mozilla::ErrorResult& aError);
|
||||
uint64_t GetMozPaintCountOuter();
|
||||
uint64_t GetMozPaintCount(mozilla::ErrorResult& aError);
|
||||
|
||||
bool ShouldResistFingerprinting();
|
||||
|
||||
mozilla::dom::MozSelfSupport* GetMozSelfSupport(mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<nsIDOMWindow> OpenDialogOuter(JSContext* aCx,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOptions,
|
||||
const mozilla::dom::Sequence<JS::Value>& aExtraArgument,
|
||||
mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIDOMWindow> OpenDialog(JSContext* aCx,
|
||||
const nsAString& aUrl,
|
||||
const nsAString& aName,
|
||||
const nsAString& aOptions,
|
||||
const mozilla::dom::Sequence<JS::Value>& aExtraArgument,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetContentOuter(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetContent(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
@ -1092,12 +1147,15 @@ public:
|
|||
// ChromeWindow bits. Do NOT call these unless your window is in
|
||||
// fact an nsGlobalChromeWindow.
|
||||
uint16_t WindowState();
|
||||
nsIBrowserDOMWindow* GetBrowserDOMWindowOuter();
|
||||
nsIBrowserDOMWindow* GetBrowserDOMWindow(mozilla::ErrorResult& aError);
|
||||
void SetBrowserDOMWindowOuter(nsIBrowserDOMWindow* aBrowserWindow);
|
||||
void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserWindow,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetAttention(mozilla::ErrorResult& aError);
|
||||
void GetAttentionWithCycleCount(int32_t aCycleCount,
|
||||
mozilla::ErrorResult& aError);
|
||||
void SetCursorOuter(const nsAString& aCursor, mozilla::ErrorResult& aError);
|
||||
void SetCursor(const nsAString& aCursor, mozilla::ErrorResult& aError);
|
||||
void Maximize(mozilla::ErrorResult& aError);
|
||||
void Minimize(mozilla::ErrorResult& aError);
|
||||
|
@ -1111,10 +1169,16 @@ public:
|
|||
mozilla::dom::Element* aPanel,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
void GetDialogArgumentsOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetDialogArguments(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetReturnValueOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetReturnValue(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
|
||||
mozilla::ErrorResult& aError);
|
||||
void SetReturnValueOuter(JSContext* aCx, JS::Handle<JS::Value> aReturnValue,
|
||||
mozilla::ErrorResult& aError);
|
||||
void SetReturnValue(JSContext* aCx, JS::Handle<JS::Value> aReturnValue,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
|
@ -1122,6 +1186,7 @@ public:
|
|||
JS::MutableHandle<JS::Value> aRetval,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<nsWindowRoot> GetWindowRootOuter();
|
||||
already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
|
||||
|
||||
protected:
|
||||
|
@ -1147,17 +1212,29 @@ protected:
|
|||
const char* aPropName,
|
||||
mozilla::ErrorResult& aError);
|
||||
// And the implementations of WindowCoordGetter/WindowCoordSetter.
|
||||
int32_t GetInnerWidthOuter(mozilla::ErrorResult& aError);
|
||||
int32_t GetInnerWidth(mozilla::ErrorResult& aError);
|
||||
void SetInnerWidthOuter(int32_t aInnerWidth, mozilla::ErrorResult& aError);
|
||||
void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError);
|
||||
int32_t GetInnerHeightOuter(mozilla::ErrorResult& aError);
|
||||
int32_t GetInnerHeight(mozilla::ErrorResult& aError);
|
||||
void SetInnerHeightOuter(int32_t aInnerHeight, mozilla::ErrorResult& aError);
|
||||
void SetInnerHeight(int32_t aInnerHeight, mozilla::ErrorResult& aError);
|
||||
int32_t GetScreenXOuter(mozilla::ErrorResult& aError);
|
||||
int32_t GetScreenX(mozilla::ErrorResult& aError);
|
||||
void SetScreenXOuter(int32_t aScreenX, mozilla::ErrorResult& aError);
|
||||
void SetScreenX(int32_t aScreenX, mozilla::ErrorResult& aError);
|
||||
int32_t GetScreenYOuter(mozilla::ErrorResult& aError);
|
||||
int32_t GetScreenY(mozilla::ErrorResult& aError);
|
||||
void SetScreenYOuter(int32_t aScreenY, mozilla::ErrorResult& aError);
|
||||
void SetScreenY(int32_t aScreenY, mozilla::ErrorResult& aError);
|
||||
int32_t GetOuterWidthOuter(mozilla::ErrorResult& aError);
|
||||
int32_t GetOuterWidth(mozilla::ErrorResult& aError);
|
||||
void SetOuterWidthOuter(int32_t aOuterWidth, mozilla::ErrorResult& aError);
|
||||
void SetOuterWidth(int32_t aOuterWidth, mozilla::ErrorResult& aError);
|
||||
int32_t GetOuterHeightOuter(mozilla::ErrorResult& aError);
|
||||
int32_t GetOuterHeight(mozilla::ErrorResult& aError);
|
||||
void SetOuterHeightOuter(int32_t aOuterHeight, mozilla::ErrorResult& aError);
|
||||
void SetOuterHeight(int32_t aOuterHeight, mozilla::ErrorResult& aError);
|
||||
|
||||
// Array of idle observers that are notified of idle events.
|
||||
|
@ -1405,6 +1482,7 @@ public:
|
|||
// Outer windows only.
|
||||
mozilla::CSSIntPoint GetScrollXY(bool aDoFlush);
|
||||
|
||||
void GetScrollMaxXYOuter(int32_t* aScrollMaxX, int32_t* aScrollMaxY);
|
||||
void GetScrollMaxXY(int32_t* aScrollMaxX, int32_t* aScrollMaxY,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
|
@ -1500,6 +1578,10 @@ protected:
|
|||
nsDOMWindowList* GetWindowList();
|
||||
|
||||
// Helper for getComputedStyle and getDefaultComputedStyle
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetComputedStyleHelperOuter(mozilla::dom::Element& aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
bool aDefaultStylesOnly);
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetComputedStyleHelper(mozilla::dom::Element& aElt,
|
||||
const nsAString& aPseudoElt,
|
||||
|
@ -1521,11 +1603,19 @@ protected:
|
|||
|
||||
nsGlobalWindow* InnerForSetTimeoutOrInterval(mozilla::ErrorResult& aError);
|
||||
|
||||
void PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const nsAString& aTargetOrigin,
|
||||
JS::Handle<JS::Value> aTransfer,
|
||||
mozilla::ErrorResult& aError);
|
||||
void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const nsAString& aTargetOrigin,
|
||||
JS::Handle<JS::Value> aTransfer,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<nsIVariant>
|
||||
ShowModalDialogOuter(const nsAString& aUrl, nsIVariant* aArgument,
|
||||
const nsAString& aOptions, mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<nsIVariant>
|
||||
ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
|
||||
const nsAString& aOptions, mozilla::ErrorResult& aError);
|
||||
|
@ -1647,6 +1737,7 @@ protected:
|
|||
nsRefPtr<mozilla::dom::Navigator> mNavigator;
|
||||
nsRefPtr<nsScreen> mScreen;
|
||||
nsRefPtr<nsDOMWindowList> mFrames;
|
||||
// All BarProps are inner window only.
|
||||
nsRefPtr<mozilla::dom::BarProp> mMenubar;
|
||||
nsRefPtr<mozilla::dom::BarProp> mToolbar;
|
||||
nsRefPtr<mozilla::dom::BarProp> mLocationbar;
|
||||
|
|
|
@ -46,6 +46,7 @@ NS_INTERFACE_MAP_END
|
|||
nsHistory::nsHistory(nsPIDOMWindow* aInnerWindow)
|
||||
: mInnerWindow(do_GetWeakReference(aInnerWindow))
|
||||
{
|
||||
MOZ_ASSERT(aInnerWindow->IsInnerWindow());
|
||||
}
|
||||
|
||||
nsHistory::~nsHistory()
|
||||
|
|
|
@ -25,6 +25,7 @@ using namespace mozilla::dom;
|
|||
nsScreen::Create(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->IsInnerWindow());
|
||||
|
||||
if (!aWindow->GetDocShell()) {
|
||||
return nullptr;
|
||||
|
|
|
@ -2415,7 +2415,7 @@ EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj)
|
|||
}
|
||||
|
||||
bool
|
||||
CheckPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[])
|
||||
CheckAnyPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[])
|
||||
{
|
||||
JS::Rooted<JSObject*> rootedObj(aCx, aObj);
|
||||
nsPIDOMWindow* window = xpc::WindowGlobalOrNull(rootedObj);
|
||||
|
@ -2436,6 +2436,28 @@ CheckPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CheckAllPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[])
|
||||
{
|
||||
JS::Rooted<JSObject*> rootedObj(aCx, aObj);
|
||||
nsPIDOMWindow* window = xpc::WindowGlobalOrNull(rootedObj);
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||
NS_ENSURE_TRUE(permMgr, false);
|
||||
|
||||
do {
|
||||
uint32_t permission = nsIPermissionManager::DENY_ACTION;
|
||||
permMgr->TestPermissionFromWindow(window, *aPermissions, &permission);
|
||||
if (permission != nsIPermissionManager::ALLOW_ACTION) {
|
||||
return false;
|
||||
}
|
||||
} while (*(++aPermissions));
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HandlePrerenderingViolation(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
|
|
|
@ -3094,7 +3094,12 @@ AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitinfo,
|
|||
// Returns true if aObj's global has any of the permissions named in aPermissions
|
||||
// set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be null-terminated.
|
||||
bool
|
||||
CheckPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
|
||||
CheckAnyPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
|
||||
|
||||
// Returns true if aObj's global has all of the permissions named in aPermissions
|
||||
// set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be null-terminated.
|
||||
bool
|
||||
CheckAllPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
|
||||
|
||||
// This function is called by the bindings layer for methods/getters/setters
|
||||
// that are not safe to be called in prerendering mode. It checks to make sure
|
||||
|
|
|
@ -1895,11 +1895,12 @@ class MemberCondition:
|
|||
None, they should be strings that have the pref name (for "pref")
|
||||
or function name (for "func" and "available").
|
||||
"""
|
||||
def __init__(self, pref, func, available=None, checkPermissions=None):
|
||||
def __init__(self, pref, func, available=None, checkAnyPermissions=None, checkAllPermissions=None):
|
||||
assert pref is None or isinstance(pref, str)
|
||||
assert func is None or isinstance(func, str)
|
||||
assert available is None or isinstance(available, str)
|
||||
assert checkPermissions is None or isinstance(checkPermissions, int)
|
||||
assert checkAnyPermissions is None or isinstance(checkAnyPermissions, int)
|
||||
assert checkAllPermissions is None or isinstance(checkAllPermissions, int)
|
||||
self.pref = pref
|
||||
|
||||
def toFuncPtr(val):
|
||||
|
@ -1908,15 +1909,20 @@ class MemberCondition:
|
|||
return "&" + val
|
||||
self.func = toFuncPtr(func)
|
||||
self.available = toFuncPtr(available)
|
||||
if checkPermissions is None:
|
||||
self.checkPermissions = "nullptr"
|
||||
if checkAnyPermissions is None:
|
||||
self.checkAnyPermissions = "nullptr"
|
||||
else:
|
||||
self.checkPermissions = "permissions_%i" % checkPermissions
|
||||
self.checkAnyPermissions = "anypermissions_%i" % checkAnyPermissions
|
||||
if checkAllPermissions is None:
|
||||
self.checkAllPermissions = "nullptr"
|
||||
else:
|
||||
self.checkAllPermissions = "allpermissions_%i" % checkAllPermissions
|
||||
|
||||
def __eq__(self, other):
|
||||
return (self.pref == other.pref and self.func == other.func and
|
||||
self.available == other.available and
|
||||
self.checkPermissions == other.checkPermissions)
|
||||
self.checkAnyPermissions == other.checkAnyPermissions and
|
||||
self.checkAllPermissions == other.checkAllPermissions)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
@ -1984,7 +1990,8 @@ class PropertyDefiner:
|
|||
PropertyDefiner.getStringAttr(interfaceMember,
|
||||
"Func"),
|
||||
getAvailableInTestFunc(interfaceMember),
|
||||
descriptor.checkPermissionsIndicesForMembers.get(interfaceMember.identifier.name))
|
||||
descriptor.checkAnyPermissionsIndicesForMembers.get(interfaceMember.identifier.name),
|
||||
descriptor.checkAllPermissionsIndicesForMembers.get(interfaceMember.identifier.name))
|
||||
|
||||
def generatePrefableArray(self, array, name, specFormatter, specTerminator,
|
||||
specType, getCondition, getDataTuple, doIdArrays):
|
||||
|
@ -2022,7 +2029,7 @@ class PropertyDefiner:
|
|||
specs = []
|
||||
prefableSpecs = []
|
||||
|
||||
prefableTemplate = ' { true, %s, %s, %s, &%s[%d] }'
|
||||
prefableTemplate = ' { true, %s, %s, %s, %s, &%s[%d] }'
|
||||
prefCacheTemplate = '&%s[%d].enabled'
|
||||
|
||||
def switchToCondition(props, condition):
|
||||
|
@ -2036,7 +2043,8 @@ class PropertyDefiner:
|
|||
prefableSpecs.append(prefableTemplate %
|
||||
(condition.func,
|
||||
condition.available,
|
||||
condition.checkPermissions,
|
||||
condition.checkAnyPermissions,
|
||||
condition.checkAllPermissions,
|
||||
name + "_specs", len(specs)))
|
||||
|
||||
switchToCondition(self, lastCondition)
|
||||
|
@ -3167,9 +3175,12 @@ class CGConstructorEnabled(CGAbstractMethod):
|
|||
availableIn = getAvailableInTestFunc(iface)
|
||||
if availableIn:
|
||||
conditions.append("%s(aCx, aObj)" % availableIn)
|
||||
checkPermissions = self.descriptor.checkPermissionsIndex
|
||||
if checkPermissions is not None:
|
||||
conditions.append("CheckPermissions(aCx, aObj, permissions_%i)" % checkPermissions)
|
||||
checkAnyPermissions = self.descriptor.checkAnyPermissionsIndex
|
||||
if checkAnyPermissions is not None:
|
||||
conditions.append("CheckAnyPermissions(aCx, aObj, anypermissions_%i)" % checkAnyPermissions)
|
||||
checkAllPermissions = self.descriptor.checkAllPermissionsIndex
|
||||
if checkAllPermissions is not None:
|
||||
conditions.append("CheckAllPermissions(aCx, aObj, allpermissions_%i)" % checkAllPermissions)
|
||||
# We should really have some conditions
|
||||
assert len(body) or len(conditions)
|
||||
|
||||
|
@ -5575,13 +5586,13 @@ def convertConstIDLValueToJSVal(value):
|
|||
IDLType.Tags.uint16, IDLType.Tags.int32]:
|
||||
return "JS::Int32Value(%s)" % (value.value)
|
||||
if tag == IDLType.Tags.uint32:
|
||||
return "UINT_TO_JSVAL(%sU)" % (value.value)
|
||||
return "JS::NumberValue(%sU)" % (value.value)
|
||||
if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
|
||||
return "DOUBLE_TO_JSVAL(%s)" % numericValue(tag, value.value)
|
||||
return "JS::CanonicalizedDoubleValue(%s)" % numericValue(tag, value.value)
|
||||
if tag == IDLType.Tags.bool:
|
||||
return "JSVAL_TRUE" if value.value else "JSVAL_FALSE"
|
||||
if tag in [IDLType.Tags.float, IDLType.Tags.double]:
|
||||
return "DOUBLE_TO_JSVAL(%s)" % (value.value)
|
||||
return "JS::CanonicalizedDoubleValue(%s)" % (value.value)
|
||||
raise TypeError("Const value of unhandled type: %s" % value.type)
|
||||
|
||||
|
||||
|
@ -11436,14 +11447,16 @@ class CGDescriptor(CGThing):
|
|||
if descriptor.concrete and descriptor.wrapperCache:
|
||||
cgThings.append(CGClassObjectMovedHook(descriptor))
|
||||
|
||||
if len(descriptor.permissions):
|
||||
for (k, v) in sorted(descriptor.permissions.items()):
|
||||
perms = CGList((CGGeneric('"%s",' % p) for p in k), joiner="\n")
|
||||
perms.append(CGGeneric("nullptr"))
|
||||
cgThings.append(CGWrapper(CGIndenter(perms),
|
||||
pre="static const char* const permissions_%i[] = {\n" % v,
|
||||
post="\n};\n",
|
||||
defineOnly=True))
|
||||
for name in ["anypermissions", "allpermissions"]:
|
||||
permissions = getattr(descriptor, name)
|
||||
if len(permissions):
|
||||
for (k, v) in sorted(permissions.items()):
|
||||
perms = CGList((CGGeneric('"%s",' % p) for p in k), joiner="\n")
|
||||
perms.append(CGGeneric("nullptr"))
|
||||
cgThings.append(CGWrapper(CGIndenter(perms),
|
||||
pre="static const char* const %s_%i[] = {\n" % (name, v),
|
||||
post="\n};\n",
|
||||
defineOnly=True))
|
||||
|
||||
# Generate the _ClearCachedFooValue methods before the property arrays that use them.
|
||||
if descriptor.interface.isJSImplemented():
|
||||
|
|
|
@ -546,11 +546,17 @@ class Descriptor(DescriptorProvider):
|
|||
self._binaryNames.setdefault('__stringifier', 'Stringify')
|
||||
|
||||
if not self.interface.isExternal():
|
||||
self.permissions = dict()
|
||||
self.anypermissions = dict()
|
||||
self.allpermissions = dict()
|
||||
|
||||
# Adds a permission list to this descriptor and returns the index to use.
|
||||
def addPermissions(ifaceOrMember):
|
||||
checkPermissions = ifaceOrMember.getExtendedAttribute("CheckPermissions")
|
||||
def addPermissions(ifaceOrMember, attribute):
|
||||
if attribute == "CheckAllPermissions":
|
||||
permissions = self.allpermissions
|
||||
else:
|
||||
permissions = self.anypermissions
|
||||
|
||||
checkPermissions = ifaceOrMember.getExtendedAttribute(attribute)
|
||||
if checkPermissions is None:
|
||||
return None
|
||||
|
||||
|
@ -560,17 +566,22 @@ class Descriptor(DescriptorProvider):
|
|||
checkPermissions = checkPermissions[0]
|
||||
permissionsList = checkPermissions.split()
|
||||
if len(permissionsList) == 0:
|
||||
raise TypeError("Need at least one permission name for CheckPermissions")
|
||||
raise TypeError("Need at least one permission name for %s" % attribute)
|
||||
|
||||
permissionsList = tuple(sorted(set(permissionsList)))
|
||||
return self.permissions.setdefault(permissionsList, len(self.permissions))
|
||||
return permissions.setdefault(permissionsList, len(permissions))
|
||||
|
||||
self.checkPermissionsIndex = addPermissions(self.interface)
|
||||
self.checkPermissionsIndicesForMembers = dict()
|
||||
self.checkAnyPermissionsIndex = addPermissions(self.interface, "CheckAnyPermissions")
|
||||
self.checkAnyPermissionsIndicesForMembers = dict()
|
||||
self.checkAllPermissionsIndex = addPermissions(self.interface, "CheckAllPermissions")
|
||||
self.checkAllPermissionsIndicesForMembers = dict()
|
||||
for m in self.interface.members:
|
||||
permissionsIndex = addPermissions(m)
|
||||
permissionsIndex = addPermissions(m, "CheckAnyPermissions")
|
||||
if permissionsIndex is not None:
|
||||
self.checkPermissionsIndicesForMembers[m.identifier.name] = permissionsIndex
|
||||
self.checkAnyPermissionsIndicesForMembers[m.identifier.name] = permissionsIndex
|
||||
allpermissionsIndex = addPermissions(m, "CheckAllPermissions")
|
||||
if allpermissionsIndex is not None:
|
||||
self.checkAllPermissionsIndicesForMembers[m.identifier.name] = allpermissionsIndex
|
||||
|
||||
def isTestInterface(iface):
|
||||
return (iface.identifier.name in ["TestInterface",
|
||||
|
@ -579,7 +590,8 @@ class Descriptor(DescriptorProvider):
|
|||
|
||||
self.featureDetectibleThings = set()
|
||||
if not isTestInterface(self.interface):
|
||||
if (self.interface.getExtendedAttribute("CheckPermissions") or
|
||||
if (self.interface.getExtendedAttribute("CheckAnyPermissions") or
|
||||
self.interface.getExtendedAttribute("CheckAllPermissions") or
|
||||
self.interface.getExtendedAttribute("AvailableIn") == "PrivilegedApps"):
|
||||
if self.interface.getNavigatorProperty():
|
||||
self.featureDetectibleThings.add("Navigator.%s" % self.interface.getNavigatorProperty())
|
||||
|
@ -590,7 +602,8 @@ class Descriptor(DescriptorProvider):
|
|||
self.featureDetectibleThings.add("%s.%s" % (iface, m.identifier.name))
|
||||
|
||||
for m in self.interface.members:
|
||||
if (m.getExtendedAttribute("CheckPermissions") or
|
||||
if (m.getExtendedAttribute("CheckAnyPermissions") or
|
||||
m.getExtendedAttribute("CheckAllPermissions") or
|
||||
m.getExtendedAttribute("AvailableIn") == "PrivilegedApps"):
|
||||
self.featureDetectibleThings.add("%s.%s" % (self.interface.identifier.name, m.identifier.name))
|
||||
|
||||
|
|
|
@ -40,7 +40,10 @@ typedef bool
|
|||
JS::AutoIdVector& props);
|
||||
|
||||
bool
|
||||
CheckPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
|
||||
CheckAnyPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
|
||||
|
||||
bool
|
||||
CheckAllPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
|
||||
|
||||
struct ConstantSpec
|
||||
{
|
||||
|
@ -56,7 +59,7 @@ struct Prefable {
|
|||
if (!enabled) {
|
||||
return false;
|
||||
}
|
||||
if (!enabledFunc && !availableFunc && !checkPermissions) {
|
||||
if (!enabledFunc && !availableFunc && !checkAnyPermissions && !checkAllPermissions) {
|
||||
return true;
|
||||
}
|
||||
if (enabledFunc &&
|
||||
|
@ -67,9 +70,14 @@ struct Prefable {
|
|||
!availableFunc(cx, js::GetGlobalForObjectCrossCompartment(obj))) {
|
||||
return false;
|
||||
}
|
||||
if (checkPermissions &&
|
||||
!CheckPermissions(cx, js::GetGlobalForObjectCrossCompartment(obj),
|
||||
checkPermissions)) {
|
||||
if (checkAnyPermissions &&
|
||||
!CheckAnyPermissions(cx, js::GetGlobalForObjectCrossCompartment(obj),
|
||||
checkAnyPermissions)) {
|
||||
return false;
|
||||
}
|
||||
if (checkAllPermissions &&
|
||||
!CheckAllPermissions(cx, js::GetGlobalForObjectCrossCompartment(obj),
|
||||
checkAllPermissions)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -86,7 +94,8 @@ struct Prefable {
|
|||
// is basically a hack to avoid having to codegen PropertyEnabled
|
||||
// implementations in case when we need to do two separate checks.
|
||||
PropertyEnabled availableFunc;
|
||||
const char* const* checkPermissions;
|
||||
const char* const* checkAnyPermissions;
|
||||
const char* const* checkAllPermissions;
|
||||
// Array of specs, terminated in whatever way is customary for T.
|
||||
// Null to indicate a end-of-array for Prefable, when such an
|
||||
// indicator is needed.
|
||||
|
|
|
@ -1134,7 +1134,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
member.getExtendedAttribute("Pref") or
|
||||
member.getExtendedAttribute("Func") or
|
||||
member.getExtendedAttribute("AvailableIn") or
|
||||
member.getExtendedAttribute("CheckPermissions")):
|
||||
member.getExtendedAttribute("CheckAnyPermissions") or
|
||||
member.getExtendedAttribute("CheckAllPermissions")):
|
||||
raise WebIDLError("[Alias] must not be used on a "
|
||||
"conditionally exposed operation",
|
||||
[member.location])
|
||||
|
@ -1166,12 +1167,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
self.parentScope.primaryGlobalName,
|
||||
[self.location])
|
||||
|
||||
if (self.getExtendedAttribute("CheckPermissions") and
|
||||
self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
|
||||
raise WebIDLError("[CheckPermissions] used on an interface that is "
|
||||
"not %s-only" %
|
||||
self.parentScope.primaryGlobalName,
|
||||
[self.location])
|
||||
for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]:
|
||||
if (self.getExtendedAttribute(attribute) and
|
||||
self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
|
||||
raise WebIDLError("[%s] used on an interface that is "
|
||||
"not %s-only" %
|
||||
(attribute, self.parentScope.primaryGlobalName),
|
||||
[self.location])
|
||||
|
||||
# Conditional exposure makes no sense for interfaces with no
|
||||
# interface object, unless they're navigator properties.
|
||||
|
@ -1385,7 +1387,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
identifier == "NavigatorProperty" or
|
||||
identifier == "AvailableIn" or
|
||||
identifier == "Func" or
|
||||
identifier == "CheckPermissions"):
|
||||
identifier == "CheckAnyPermissions" or
|
||||
identifier == "CheckAllPermissions"):
|
||||
# Known extended attributes that take a string value
|
||||
if not attr.hasValue():
|
||||
raise WebIDLError("[%s] must have a value" % identifier,
|
||||
|
@ -1513,7 +1516,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
|||
self.getExtendedAttribute("ChromeOnly") or
|
||||
self.getExtendedAttribute("Func") or
|
||||
self.getExtendedAttribute("AvailableIn") or
|
||||
self.getExtendedAttribute("CheckPermissions"))
|
||||
self.getExtendedAttribute("CheckAnyPermissions") or
|
||||
self.getExtendedAttribute("CheckAllPermissions"))
|
||||
|
||||
class IDLDictionary(IDLObjectWithScope):
|
||||
def __init__(self, location, parentScope, name, parent, members):
|
||||
|
@ -3361,12 +3365,13 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
|||
"%s-only" % self._globalScope.primaryGlobalName,
|
||||
[self.location])
|
||||
|
||||
if (self.getExtendedAttribute("CheckPermissions") and
|
||||
self.exposureSet != set([self._globalScope.primaryGlobalName])):
|
||||
raise WebIDLError("[CheckPermissions] used on an interface member "
|
||||
"that is not %s-only" %
|
||||
self._globalScope.primaryGlobalName,
|
||||
[self.location])
|
||||
for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]:
|
||||
if (self.getExtendedAttribute(attribute) and
|
||||
self.exposureSet != set([self._globalScope.primaryGlobalName])):
|
||||
raise WebIDLError("[%s] used on an interface member that is "
|
||||
"not %s-only" %
|
||||
(attribute, self.parentScope.primaryGlobalName),
|
||||
[self.location])
|
||||
|
||||
if self.isAttr() or self.isMethod():
|
||||
if self.affects == "Everything" and self.dependsOn != "Everything":
|
||||
|
@ -3707,7 +3712,8 @@ class IDLConst(IDLInterfaceMember):
|
|||
identifier == "ChromeOnly" or
|
||||
identifier == "Func" or
|
||||
identifier == "AvailableIn" or
|
||||
identifier == "CheckPermissions"):
|
||||
identifier == "CheckAnyPermissions" or
|
||||
identifier == "CheckAllPermissions"):
|
||||
# Known attributes that we don't need to do anything with here
|
||||
pass
|
||||
else:
|
||||
|
@ -3974,7 +3980,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
identifier == "AvailableIn" or
|
||||
identifier == "NewObject" or
|
||||
identifier == "UnsafeInPrerendering" or
|
||||
identifier == "CheckPermissions" or
|
||||
identifier == "CheckAnyPermissions" or
|
||||
identifier == "CheckAllPermissions" or
|
||||
identifier == "BinaryName"):
|
||||
# Known attributes that we don't need to do anything with here
|
||||
pass
|
||||
|
@ -4649,7 +4656,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
identifier == "Deprecated" or
|
||||
identifier == "Func" or
|
||||
identifier == "AvailableIn" or
|
||||
identifier == "CheckPermissions" or
|
||||
identifier == "CheckAnyPermissions" or
|
||||
identifier == "CheckAllPermissions" or
|
||||
identifier == "BinaryName" or
|
||||
identifier == "MethodIdentityTestable" or
|
||||
identifier == "StaticClassOverride"):
|
||||
|
|
|
@ -77,77 +77,6 @@ BroadcastChannelService::UnregisterActor(BroadcastChannelParent* aParent)
|
|||
mAgents.RemoveEntry(aParent);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct MOZ_STACK_CLASS PostMessageData final
|
||||
{
|
||||
PostMessageData(BroadcastChannelParent* aParent,
|
||||
const ClonedMessageData& aData,
|
||||
const nsACString& aOrigin,
|
||||
uint64_t aAppId,
|
||||
bool aIsInBrowserElement,
|
||||
const nsAString& aChannel,
|
||||
bool aPrivateBrowsing)
|
||||
: mParent(aParent)
|
||||
, mData(aData)
|
||||
, mOrigin(aOrigin)
|
||||
, mChannel(aChannel)
|
||||
, mAppId(aAppId)
|
||||
, mIsInBrowserElement(aIsInBrowserElement)
|
||||
, mPrivateBrowsing(aPrivateBrowsing)
|
||||
{
|
||||
MOZ_ASSERT(aParent);
|
||||
MOZ_COUNT_CTOR(PostMessageData);
|
||||
|
||||
// We need to keep the array alive for the life-time of this
|
||||
// PostMessageData.
|
||||
if (!aData.blobsParent().IsEmpty()) {
|
||||
mBlobs.SetCapacity(aData.blobsParent().Length());
|
||||
|
||||
for (uint32_t i = 0, len = aData.blobsParent().Length(); i < len; ++i) {
|
||||
nsRefPtr<BlobImpl> impl =
|
||||
static_cast<BlobParent*>(aData.blobsParent()[i])->GetBlobImpl();
|
||||
MOZ_ASSERT(impl);
|
||||
mBlobs.AppendElement(impl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~PostMessageData()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PostMessageData);
|
||||
}
|
||||
|
||||
BroadcastChannelParent* mParent;
|
||||
const ClonedMessageData& mData;
|
||||
nsTArray<nsRefPtr<BlobImpl>> mBlobs;
|
||||
const nsCString mOrigin;
|
||||
const nsString mChannel;
|
||||
uint64_t mAppId;
|
||||
bool mIsInBrowserElement;
|
||||
bool mPrivateBrowsing;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
PostMessageEnumerator(nsPtrHashKey<BroadcastChannelParent>* aKey, void* aPtr)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
auto* data = static_cast<PostMessageData*>(aPtr);
|
||||
BroadcastChannelParent* parent = aKey->GetKey();
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
if (parent != data->mParent) {
|
||||
parent->CheckAndDeliver(data->mData, data->mOrigin, data->mAppId,
|
||||
data->mIsInBrowserElement, data->mChannel,
|
||||
data->mPrivateBrowsing);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
|
||||
const ClonedMessageData& aData,
|
||||
|
@ -161,9 +90,29 @@ BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
|
|||
MOZ_ASSERT(aParent);
|
||||
MOZ_ASSERT(mAgents.Contains(aParent));
|
||||
|
||||
PostMessageData data(aParent, aData, aOrigin, aAppId, aIsInBrowserElement,
|
||||
aChannel, aPrivateBrowsing);
|
||||
mAgents.EnumerateEntries(PostMessageEnumerator, &data);
|
||||
// We need to keep the array alive for the life-time of this operation.
|
||||
nsTArray<nsRefPtr<BlobImpl>> blobs;
|
||||
if (!aData.blobsParent().IsEmpty()) {
|
||||
blobs.SetCapacity(aData.blobsParent().Length());
|
||||
|
||||
for (uint32_t i = 0, len = aData.blobsParent().Length(); i < len; ++i) {
|
||||
nsRefPtr<BlobImpl> impl =
|
||||
static_cast<BlobParent*>(aData.blobsParent()[i])->GetBlobImpl();
|
||||
MOZ_ASSERT(impl);
|
||||
blobs.AppendElement(impl);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
|
||||
BroadcastChannelParent* parent = iter.Get()->GetKey();
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
if (parent != aParent) {
|
||||
parent->CheckAndDeliver(aData, PromiseFlatCString(aOrigin),
|
||||
aAppId, aIsInBrowserElement,
|
||||
PromiseFlatString(aChannel), aPrivateBrowsing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -238,6 +238,7 @@ BrowserElementChild.prototype = {
|
|||
"find-all": this._recvFindAll.bind(this),
|
||||
"find-next": this._recvFindNext.bind(this),
|
||||
"clear-match": this._recvClearMatch.bind(this),
|
||||
"execute-script": this._recvExecuteScript,
|
||||
"get-audio-channel-volume": this._recvGetAudioChannelVolume,
|
||||
"set-audio-channel-volume": this._recvSetAudioChannelVolume,
|
||||
"get-audio-channel-muted": this._recvGetAudioChannelMuted,
|
||||
|
@ -984,6 +985,90 @@ BrowserElementChild.prototype = {
|
|||
takeScreenshotClosure, maxDelayMS);
|
||||
},
|
||||
|
||||
_recvExecuteScript: function(data) {
|
||||
debug("Received executeScript message: (" + data.json.id + ")");
|
||||
|
||||
let domRequestID = data.json.id;
|
||||
|
||||
let sendError = errorMsg => sendAsyncMsg("execute-script-done", {
|
||||
errorMsg,
|
||||
id: domRequestID
|
||||
});
|
||||
|
||||
let sendSuccess = successRv => sendAsyncMsg("execute-script-done", {
|
||||
successRv,
|
||||
id: domRequestID
|
||||
});
|
||||
|
||||
let isJSON = obj => {
|
||||
try {
|
||||
JSON.stringify(obj);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
let expectedOrigin = data.json.args.options.origin;
|
||||
let expectedUrl = data.json.args.options.url;
|
||||
|
||||
if (expectedOrigin) {
|
||||
if (expectedOrigin != content.location.origin) {
|
||||
sendError("Origin mismatches");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedUrl) {
|
||||
let expectedURI
|
||||
try {
|
||||
expectedURI = Services.io.newURI(expectedUrl, null, null);
|
||||
} catch(e) {
|
||||
sendError("Malformed URL");
|
||||
return;
|
||||
}
|
||||
let currentURI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
|
||||
if (!currentURI.equalsExceptRef(expectedURI)) {
|
||||
sendError("URL mismatches");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let sandbox = new Cu.Sandbox([content], {
|
||||
sandboxPrototype: content,
|
||||
sandboxName: "browser-api-execute-script",
|
||||
allowWaivers: false,
|
||||
sameZoneAs: content
|
||||
});
|
||||
|
||||
try {
|
||||
let sandboxRv = Cu.evalInSandbox(data.json.args.script, sandbox, "1.8");
|
||||
if (sandboxRv instanceof Promise) {
|
||||
sandboxRv.then(rv => {
|
||||
if (isJSON(rv)) {
|
||||
sendSuccess(rv);
|
||||
} else {
|
||||
sendError("Value returned (resolve) by promise is not a valid JSON object");
|
||||
}
|
||||
}, error => {
|
||||
if (isJSON(error)) {
|
||||
sendError(error);
|
||||
} else {
|
||||
sendError("Value returned (reject) by promise is not a valid JSON object");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (isJSON(sandboxRv)) {
|
||||
sendSuccess(sandboxRv);
|
||||
} else {
|
||||
sendError("Script last expression must be a promise or a JSON object");
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
sendError(e.toString());
|
||||
}
|
||||
},
|
||||
|
||||
_recvGetContentDimensions: function(data) {
|
||||
debug("Received getContentDimensions message: (" + data.json.id + ")");
|
||||
sendAsyncMsg('got-contentdimensions', {
|
||||
|
|
|
@ -207,6 +207,7 @@ BrowserElementParent.prototype = {
|
|||
"scrollviewchange": this._handleScrollViewChange,
|
||||
"caretstatechanged": this._handleCaretStateChanged,
|
||||
"findchange": this._handleFindChange,
|
||||
"execute-script-done": this._gotDOMRequestResult,
|
||||
"got-audio-channel-volume": this._gotDOMRequestResult,
|
||||
"got-set-audio-channel-volume": this._gotDOMRequestResult,
|
||||
"got-audio-channel-muted": this._gotDOMRequestResult,
|
||||
|
@ -692,6 +693,19 @@ BrowserElementParent.prototype = {
|
|||
this._sendAsyncMsg('stop');
|
||||
}),
|
||||
|
||||
executeScript: function(script, options) {
|
||||
if (!this._isAlive()) {
|
||||
throw Components.Exception("Dead content process",
|
||||
Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// Enforcing options.url or options.origin
|
||||
if (!options.url && !options.origin) {
|
||||
throw Components.Exception("Invalid argument", Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
return this._sendDOMRequest('execute-script', {script, options});
|
||||
},
|
||||
|
||||
/*
|
||||
* The valid range of zoom scale is defined in preference "zoom.maxPercent" and "zoom.minPercent".
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Bug 1174733 - Browser API: iframe.executeScript
|
||||
|
||||
'use strict';
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
|
||||
function runTest() {
|
||||
|
||||
const origin = 'http://example.org';
|
||||
const url = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_ExecuteScript.html';
|
||||
|
||||
// Test if all key=>value pairs in o1 are present in o2.
|
||||
const c = (o1, o2) => Object.keys(o1).every(k => o1[k] == o2[k]);
|
||||
|
||||
let scriptId = 0;
|
||||
|
||||
const bail = () => {
|
||||
ok(false, `scriptId: ${scriptId++}`);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPermissions([
|
||||
{type: 'browser', allow: 1, context: document},
|
||||
{type: 'browser:universalxss', allow: 1, context: document}
|
||||
], function() {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.addEventListener('mozbrowserloadend', function onload() {
|
||||
iframe.removeEventListener('mozbrowserloadend', onload);
|
||||
onReady(iframe);
|
||||
});
|
||||
iframe.src = url;
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
|
||||
|
||||
function onReady(iframe) {
|
||||
iframe.executeScript('4 + 4', {url}).then(rv => {
|
||||
is(rv, 8, `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('(() => {return {a:42}})()', {url})
|
||||
}, bail).then(rv => {
|
||||
ok(c(rv, {a:42}), `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('(() => {return {a:42}})()', {origin})
|
||||
}, bail).then(rv => {
|
||||
ok(c(rv, {a:42}), `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('(() => {return {a:42}})()', {origin, url})
|
||||
}, bail).then(rv => {
|
||||
ok(c(rv, {a:42}), `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript(`
|
||||
new Promise((resolve, reject) => {
|
||||
resolve(document.body.textContent.trim());
|
||||
});
|
||||
`, {url})
|
||||
}, bail).then(rv => {
|
||||
is(rv, 'foo', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript(`
|
||||
new Promise((resolve, reject) => {
|
||||
resolve({a:43,b:34});
|
||||
});
|
||||
`, {url})
|
||||
}, bail).then(rv => {
|
||||
ok(c(rv, {a:43,b:34}), `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript(`
|
||||
… syntax error
|
||||
`, {url});
|
||||
}, bail).then(bail, (error) => {
|
||||
is(error.name, 'SyntaxError: illegal character', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript(`
|
||||
window
|
||||
`, {url});
|
||||
}).then(bail, (error) => {
|
||||
is(error.name, 'Script last expression must be a promise or a JSON object', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript(`
|
||||
new Promise((resolve, reject) => {
|
||||
reject('BOOM');
|
||||
});
|
||||
`, {url});
|
||||
}).then(bail, (error) => {
|
||||
is(error.name, 'BOOM', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript(`
|
||||
new Promise((resolve, reject) => {
|
||||
resolve(window);
|
||||
});
|
||||
`, {url});
|
||||
}).then(bail, (error) => {
|
||||
is(error.name, 'Value returned (resolve) by promise is not a valid JSON object', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('window.btoa("a")', {url})
|
||||
}, bail).then(rv => {
|
||||
ok(c(rv, 'YQ=='), `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('window.wrappedJSObject.btoa("a")', {url})
|
||||
}, bail).then(bail, (error) => {
|
||||
is(error.name, 'TypeError: window.wrappedJSObject is undefined', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('42', {})
|
||||
}).then(bail, error => {
|
||||
is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('42');
|
||||
}).then(bail, error => {
|
||||
is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('43', { url: 'http://foo.com' });
|
||||
}).then(bail, (error) => {
|
||||
is(error.name, 'URL mismatches', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('43', { url: '_' });
|
||||
}, bail).then(bail, (error) => {
|
||||
is(error.name, 'Malformed URL', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('43', { origin: 'http://foo.com' });
|
||||
}, bail).then(bail, (error) => {
|
||||
is(error.name, 'Origin mismatches', `scriptId: ${scriptId++}`);
|
||||
return iframe.executeScript('43', { origin: 'https://example.org' });
|
||||
}, bail).then(bail, (error) => {
|
||||
is(error.name, 'Origin mismatches', `scriptId: ${scriptId++}`);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener('testready', runTest);
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<script>
|
||||
window.btoa = () => "fake btoa";
|
||||
</script>
|
||||
</head>
|
||||
<body>foo</body>
|
||||
</html>
|
|
@ -6,7 +6,9 @@
|
|||
skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
|
||||
support-files =
|
||||
browserElement_OpenMixedProcess.js
|
||||
file_browserElement_ExecuteScript.html
|
||||
file_browserElement_OpenMixedProcess.html
|
||||
browserElement_ExecuteScript.js
|
||||
browserElement_Find.js
|
||||
browserElement_OpenTab.js
|
||||
|
||||
|
@ -42,6 +44,7 @@ skip-if = (toolkit == 'gonk' && !debug)
|
|||
disabled = bug 1022281
|
||||
[test_browserElement_oop_ErrorSecurity.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_oop_ExecuteScript.html]
|
||||
[test_browserElement_oop_Find.html]
|
||||
[test_browserElement_oop_FirstPaint.html]
|
||||
[test_browserElement_oop_ForwardName.html]
|
||||
|
|
|
@ -28,6 +28,7 @@ support-files =
|
|||
browserElement_DocumentFirstPaint.js
|
||||
browserElement_Download.js
|
||||
browserElement_ErrorSecurity.js
|
||||
browserElement_ExecuteScript.js
|
||||
browserElement_ExposableURI.js
|
||||
browserElement_Find.js
|
||||
browserElement_FirstPaint.js
|
||||
|
@ -88,6 +89,7 @@ support-files =
|
|||
file_browserElement_CloseFromOpener.html
|
||||
file_browserElement_CookiesNotThirdParty.html
|
||||
file_browserElement_DisallowEmbedAppsInOOP.html
|
||||
file_browserElement_ExecuteScript.html
|
||||
file_browserElement_ForwardName.html
|
||||
file_browserElement_FrameWrongURI.html
|
||||
file_browserElement_LoadEvents.html
|
||||
|
@ -163,6 +165,7 @@ skip-if = os == "android" || toolkit == 'gonk' # embed-apps doesn't work in the
|
|||
[test_browserElement_inproc_DocumentFirstPaint.html]
|
||||
[test_browserElement_inproc_Download.html]
|
||||
disabled = bug 1022281
|
||||
[test_browserElement_inproc_ExecuteScript.html]
|
||||
[test_browserElement_inproc_ExposableURI.html]
|
||||
[test_browserElement_inproc_Find.html]
|
||||
[test_browserElement_inproc_FirstPaint.html]
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1174733
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1163961</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1174733">Mozilla Bug 1174733</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_ExecuteScript.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1174733
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1163961</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1174733">Mozilla Bug 1174733</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="browserElement_ExecuteScript.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports
|
|||
* Interface to the BrowserElementParent implementation. All methods
|
||||
* but setFrameLoader throw when the remote process is dead.
|
||||
*/
|
||||
[scriptable, uuid(daa264b2-54df-4fc7-89b7-c9d02167c5d4)]
|
||||
[scriptable, uuid(26a832d1-9d71-43ef-9d46-9d7c8ec33f00)]
|
||||
interface nsIBrowserElementAPI : nsISupports
|
||||
{
|
||||
const long FIND_CASE_SENSITIVE = 0;
|
||||
|
@ -91,4 +91,6 @@ interface nsIBrowserElementAPI : nsISupports
|
|||
nsIDOMDOMRequest isAudioChannelActive(in uint32_t audioChannel);
|
||||
|
||||
void setNFCFocus(in boolean isFocus);
|
||||
|
||||
nsIDOMDOMRequest executeScript(in DOMString script, in jsval options);
|
||||
};
|
||||
|
|
|
@ -805,18 +805,8 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
break;
|
||||
case NS_SELECTION_SET:
|
||||
{
|
||||
WidgetSelectionEvent* selectionEvent = aEvent->AsSelectionEvent();
|
||||
if (IsTargetCrossProcess(selectionEvent)) {
|
||||
// Will not be handled locally, remote the event
|
||||
if (GetCrossProcessTarget()->SendSelectionEvent(*selectionEvent)) {
|
||||
selectionEvent->mSucceeded = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ContentEventHandler handler(mPresContext);
|
||||
handler.OnSelectionEvent(selectionEvent);
|
||||
}
|
||||
IMEStateManager::HandleSelectionEvent(aPresContext, GetFocusedContent(),
|
||||
aEvent->AsSelectionEvent());
|
||||
break;
|
||||
case NS_CONTENT_COMMAND_CUT:
|
||||
case NS_CONTENT_COMMAND_COPY:
|
||||
|
|
|
@ -95,6 +95,7 @@ IMEContentObserver::IMEContentObserver()
|
|||
, mIsFocusEventPending(false)
|
||||
, mIsSelectionChangeEventPending(false)
|
||||
, mSelectionChangeCausedOnlyByComposition(false)
|
||||
, mSelectionChangeCausedOnlyBySelectionEvent(false)
|
||||
, mIsPositionChangeEventPending(false)
|
||||
, mIsFlushingPendingNotifications(false)
|
||||
{
|
||||
|
@ -418,7 +419,9 @@ IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
|
|||
nsresult rv = aSelection->GetRangeCount(&count);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (count > 0 && mWidget) {
|
||||
MaybeNotifyIMEOfSelectionChange(causedByComposition);
|
||||
bool causedBySelectionEvent = TextComposition::IsHandlingSelectionEvent();
|
||||
MaybeNotifyIMEOfSelectionChange(causedByComposition,
|
||||
causedBySelectionEvent);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -828,7 +831,9 @@ IMEContentObserver::PostTextChangeNotification(
|
|||
}
|
||||
|
||||
void
|
||||
IMEContentObserver::PostSelectionChangeNotification(bool aCausedByComposition)
|
||||
IMEContentObserver::PostSelectionChangeNotification(
|
||||
bool aCausedByComposition,
|
||||
bool aCausedBySelectionEvent)
|
||||
{
|
||||
if (!mIsSelectionChangeEventPending) {
|
||||
mSelectionChangeCausedOnlyByComposition = aCausedByComposition;
|
||||
|
@ -836,6 +841,12 @@ IMEContentObserver::PostSelectionChangeNotification(bool aCausedByComposition)
|
|||
mSelectionChangeCausedOnlyByComposition =
|
||||
mSelectionChangeCausedOnlyByComposition && aCausedByComposition;
|
||||
}
|
||||
if (!mSelectionChangeCausedOnlyBySelectionEvent) {
|
||||
mSelectionChangeCausedOnlyBySelectionEvent = aCausedBySelectionEvent;
|
||||
} else {
|
||||
mSelectionChangeCausedOnlyBySelectionEvent =
|
||||
mSelectionChangeCausedOnlyBySelectionEvent && aCausedBySelectionEvent;
|
||||
}
|
||||
mIsSelectionChangeEventPending = true;
|
||||
}
|
||||
|
||||
|
@ -939,7 +950,8 @@ IMEContentObserver::FlushMergeableNotifications()
|
|||
if (mIsSelectionChangeEventPending) {
|
||||
mIsSelectionChangeEventPending = false;
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new SelectionChangeEvent(this, mSelectionChangeCausedOnlyByComposition));
|
||||
new SelectionChangeEvent(this, mSelectionChangeCausedOnlyByComposition,
|
||||
mSelectionChangeCausedOnlyBySelectionEvent));
|
||||
}
|
||||
|
||||
if (mIsPositionChangeEventPending) {
|
||||
|
@ -1041,7 +1053,8 @@ IMEContentObserver::SelectionChangeEvent::Run()
|
|||
}
|
||||
|
||||
if (!IsSafeToNotifyIME()) {
|
||||
mIMEContentObserver->PostSelectionChangeNotification(mCausedByComposition);
|
||||
mIMEContentObserver->PostSelectionChangeNotification(
|
||||
mCausedByComposition, mCausedBySelectionEvent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1070,6 +1083,8 @@ IMEContentObserver::SelectionChangeEvent::Run()
|
|||
notification.mSelectionChangeData.mReversed = selection.mReply.mReversed;
|
||||
notification.mSelectionChangeData.mCausedByComposition =
|
||||
mCausedByComposition;
|
||||
notification.mSelectionChangeData.mCausedBySelectionEvent =
|
||||
mCausedBySelectionEvent;
|
||||
IMEStateManager::NotifyIME(notification, mIMEContentObserver->mWidget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -132,10 +132,13 @@ private:
|
|||
PostTextChangeNotification(aTextChangeData);
|
||||
FlushMergeableNotifications();
|
||||
}
|
||||
void PostSelectionChangeNotification(bool aCausedByComposition);
|
||||
void MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition)
|
||||
void PostSelectionChangeNotification(bool aCausedByComposition,
|
||||
bool aCausedBySelectionEvent);
|
||||
void MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition,
|
||||
bool aCausedBySelectionEvent)
|
||||
{
|
||||
PostSelectionChangeNotification(aCausedByComposition);
|
||||
PostSelectionChangeNotification(aCausedByComposition,
|
||||
aCausedBySelectionEvent);
|
||||
FlushMergeableNotifications();
|
||||
}
|
||||
void PostPositionChangeNotification();
|
||||
|
@ -239,6 +242,7 @@ private:
|
|||
bool mIsFocusEventPending;
|
||||
bool mIsSelectionChangeEventPending;
|
||||
bool mSelectionChangeCausedOnlyByComposition;
|
||||
bool mSelectionChangeCausedOnlyBySelectionEvent;
|
||||
bool mIsPositionChangeEventPending;
|
||||
bool mIsFlushingPendingNotifications;
|
||||
|
||||
|
@ -295,15 +299,20 @@ private:
|
|||
{
|
||||
public:
|
||||
SelectionChangeEvent(IMEContentObserver* aIMEContentObserver,
|
||||
bool aCausedByComposition)
|
||||
bool aCausedByComposition,
|
||||
bool aCausedBySelectionEvent)
|
||||
: AChangeEvent(eChangeEventType_Selection, aIMEContentObserver)
|
||||
, mCausedByComposition(aCausedByComposition)
|
||||
, mCausedBySelectionEvent(aCausedBySelectionEvent)
|
||||
{
|
||||
aIMEContentObserver->mSelectionChangeCausedOnlyByComposition = false;
|
||||
aIMEContentObserver->mSelectionChangeCausedOnlyBySelectionEvent = false;
|
||||
}
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
bool mCausedByComposition;
|
||||
bool mCausedBySelectionEvent;
|
||||
};
|
||||
|
||||
class TextChangeEvent : public AChangeEvent
|
||||
|
|
|
@ -149,6 +149,8 @@ GetEventMessageName(uint32_t aMessage)
|
|||
return "NS_COMPOSITION_COMMIT_AS_IS";
|
||||
case NS_COMPOSITION_COMMIT:
|
||||
return "NS_COMPOSITION_COMMIT";
|
||||
case NS_SELECTION_SET:
|
||||
return "NS_SELECTION_SET";
|
||||
default:
|
||||
return "unacceptable event message";
|
||||
}
|
||||
|
@ -1205,6 +1207,56 @@ IMEStateManager::DispatchCompositionEvent(
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent*
|
||||
IMEStateManager::GetRootContent(nsPresContext* aPresContext)
|
||||
{
|
||||
nsIDocument* doc = aPresContext->Document();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
return nullptr;
|
||||
}
|
||||
return doc->GetRootElement();
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
IMEStateManager::HandleSelectionEvent(nsPresContext* aPresContext,
|
||||
nsIContent* aEventTargetContent,
|
||||
WidgetSelectionEvent* aSelectionEvent)
|
||||
{
|
||||
nsIContent* eventTargetContent =
|
||||
aEventTargetContent ? aEventTargetContent :
|
||||
GetRootContent(aPresContext);
|
||||
nsRefPtr<TabParent> tabParent =
|
||||
eventTargetContent ? TabParent::GetFrom(eventTargetContent) : nullptr;
|
||||
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("ISM: IMEStateManager::HandleSelectionEvent(aPresContext=0x%p, "
|
||||
"aEventTargetContent=0x%p, aSelectionEvent={ message=%s, "
|
||||
"mFlags={ mIsTrusted=%s } }), tabParent=%p",
|
||||
aPresContext, aEventTargetContent,
|
||||
GetEventMessageName(aSelectionEvent->message),
|
||||
GetBoolName(aSelectionEvent->mFlags.mIsTrusted),
|
||||
tabParent.get()));
|
||||
|
||||
if (!aSelectionEvent->mFlags.mIsTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<TextComposition> composition = sTextCompositions ?
|
||||
sTextCompositions->GetCompositionFor(aSelectionEvent->widget) : nullptr;
|
||||
if (composition) {
|
||||
// When there is a composition, TextComposition should guarantee that the
|
||||
// selection event will be handled in same target as composition events.
|
||||
composition->HandleSelectionEvent(aSelectionEvent);
|
||||
} else {
|
||||
// When there is no composition, the selection event should be handled
|
||||
// in the aPresContext or tabParent.
|
||||
TextComposition::HandleSelectionEvent(aPresContext, tabParent,
|
||||
aSelectionEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
IMEStateManager::OnCompositionEventDiscarded(
|
||||
|
|
|
@ -152,6 +152,15 @@ public:
|
|||
EventDispatchingCallback* aCallBack,
|
||||
bool aIsSynthesized = false);
|
||||
|
||||
/**
|
||||
* All selection events must be handled via HandleSelectionEvent()
|
||||
* because they must be handled by same target as composition events when
|
||||
* there is a composition.
|
||||
*/
|
||||
static void HandleSelectionEvent(nsPresContext* aPresContext,
|
||||
nsIContent* aEventTargetContent,
|
||||
WidgetSelectionEvent* aSelectionEvent);
|
||||
|
||||
/**
|
||||
* This is called when PresShell ignores a composition event due to not safe
|
||||
* to dispatch events.
|
||||
|
@ -212,6 +221,8 @@ protected:
|
|||
|
||||
static bool IsIMEObserverNeeded(const IMEState& aState);
|
||||
|
||||
static nsIContent* GetRootContent(nsPresContext* aPresContext);
|
||||
|
||||
static StaticRefPtr<nsIContent> sContent;
|
||||
static nsPresContext* sPresContext;
|
||||
static StaticRefPtr<nsIWidget> sFocusedIMEWidget;
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace mozilla {
|
|||
* TextComposition
|
||||
******************************************************************************/
|
||||
|
||||
bool TextComposition::sHandlingSelectionEvent = false;
|
||||
|
||||
TextComposition::TextComposition(nsPresContext* aPresContext,
|
||||
nsINode* aNode,
|
||||
TabParent* aTabParent,
|
||||
|
@ -374,6 +376,30 @@ TextComposition::DispatchCompositionEvent(
|
|||
NotityUpdateComposition(aCompositionEvent);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
TextComposition::HandleSelectionEvent(nsPresContext* aPresContext,
|
||||
TabParent* aTabParent,
|
||||
WidgetSelectionEvent* aSelectionEvent)
|
||||
{
|
||||
// If the content is a container of TabParent, composition should be in the
|
||||
// remote process.
|
||||
if (aTabParent) {
|
||||
unused << aTabParent->SendSelectionEvent(*aSelectionEvent);
|
||||
aSelectionEvent->mFlags.mPropagationStopped = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ContentEventHandler handler(aPresContext);
|
||||
AutoRestore<bool> saveHandlingSelectionEvent(sHandlingSelectionEvent);
|
||||
sHandlingSelectionEvent = true;
|
||||
// XXX During setting selection, a selection listener may change selection
|
||||
// again. In such case, sHandlingSelectionEvent doesn't indicate if
|
||||
// the selection change is caused by a selection event. However, it
|
||||
// must be non-realistic scenario.
|
||||
handler.OnSelectionEvent(aSelectionEvent);
|
||||
}
|
||||
|
||||
void
|
||||
TextComposition::NotityUpdateComposition(
|
||||
const WidgetCompositionEvent* aCompositionEvent)
|
||||
|
|
|
@ -41,6 +41,8 @@ class TextComposition final
|
|||
public:
|
||||
typedef dom::TabParent TabParent;
|
||||
|
||||
static bool IsHandlingSelectionEvent() { return sHandlingSelectionEvent; }
|
||||
|
||||
TextComposition(nsPresContext* aPresContext,
|
||||
nsINode* aNode,
|
||||
TabParent* aTabParent,
|
||||
|
@ -171,6 +173,10 @@ private:
|
|||
// WARNING: mPresContext may be destroying, so, be careful if you touch it.
|
||||
}
|
||||
|
||||
// sHandlingSelectionEvent is true while TextComposition sends a selection
|
||||
// event to ContentEventHandler.
|
||||
static bool sHandlingSelectionEvent;
|
||||
|
||||
// This class holds nsPresContext weak. This instance shouldn't block
|
||||
// destroying it. When the presContext is being destroyed, it's notified to
|
||||
// IMEStateManager::OnDestroyPresContext(), and then, it destroy
|
||||
|
@ -284,6 +290,18 @@ private:
|
|||
EventDispatchingCallback* aCallBack,
|
||||
bool aIsSynthesized);
|
||||
|
||||
/**
|
||||
* HandleSelectionEvent() sends the selection event to ContentEventHandler
|
||||
* or dispatches it to the focused child process.
|
||||
*/
|
||||
void HandleSelectionEvent(WidgetSelectionEvent* aSelectionEvent)
|
||||
{
|
||||
HandleSelectionEvent(mPresContext, mTabParent, aSelectionEvent);
|
||||
}
|
||||
static void HandleSelectionEvent(nsPresContext* aPresContext,
|
||||
TabParent* aTabParent,
|
||||
WidgetSelectionEvent* aSelectionEvent);
|
||||
|
||||
/**
|
||||
* MaybeDispatchCompositionUpdate() may dispatch a compositionupdate event
|
||||
* if aCompositionEvent changes composition string.
|
||||
|
|
|
@ -1831,7 +1831,7 @@ void HTMLMediaElement::SetMutedInternal(uint32_t aMuted)
|
|||
|
||||
void HTMLMediaElement::SetVolumeInternal()
|
||||
{
|
||||
float effectiveVolume = mMuted ? 0.0f : float(mVolume * mAudioChannelVolume);
|
||||
float effectiveVolume = ComputedVolume();
|
||||
|
||||
if (mDecoder) {
|
||||
mDecoder->SetVolume(effectiveVolume);
|
||||
|
@ -3569,6 +3569,12 @@ HTMLMediaElement::UpdateReadyStateInternal()
|
|||
// We are playing a stream that has video and a video frame is now set.
|
||||
// This means we have all metadata needed to change ready state.
|
||||
MediaInfo mediaInfo = mMediaInfo;
|
||||
if (hasAudio) {
|
||||
mediaInfo.EnableAudio();
|
||||
}
|
||||
if (hasVideo) {
|
||||
mediaInfo.EnableVideo();
|
||||
}
|
||||
MetadataLoaded(&mediaInfo, nsAutoPtr<const MetadataTags>(nullptr));
|
||||
}
|
||||
|
||||
|
@ -4040,7 +4046,7 @@ HTMLMediaElement::NotifyOwnerDocumentActivityChangedInternal()
|
|||
mDecoder->NotifyOwnerActivityChanged();
|
||||
}
|
||||
|
||||
bool pauseElement = !IsActive() || (mMuted & MUTED_BY_AUDIO_CHANNEL);
|
||||
bool pauseElement = !IsActive() || ComputedMuted();
|
||||
|
||||
SuspendOrResumeElement(pauseElement, !IsActive());
|
||||
|
||||
|
@ -4470,19 +4476,21 @@ nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
|
|||
}
|
||||
|
||||
// We have to mute this channel.
|
||||
if (aMuted && !(mMuted & MUTED_BY_AUDIO_CHANNEL)) {
|
||||
if (aMuted && !ComputedMuted()) {
|
||||
SetMutedInternal(mMuted | MUTED_BY_AUDIO_CHANNEL);
|
||||
if (UseAudioChannelAPI()) {
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
|
||||
}
|
||||
} else if (!aMuted && (mMuted & MUTED_BY_AUDIO_CHANNEL)) {
|
||||
} else if (!aMuted && ComputedMuted()) {
|
||||
SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_CHANNEL);
|
||||
if (UseAudioChannelAPI()) {
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
|
||||
}
|
||||
}
|
||||
|
||||
SuspendOrResumeElement(mMuted & MUTED_BY_AUDIO_CHANNEL, false);
|
||||
#ifdef MOZ_B2G
|
||||
SuspendOrResumeElement(ComputedMuted(), false);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4546,7 +4554,11 @@ NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged(float aVolume, bool aMuted)
|
|||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
UpdateChannelMuteState(aVolume, aMuted);
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
mPaused.SetCanPlay(!aMuted);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4768,5 +4780,17 @@ HTMLMediaElement::NextFrameStatus()
|
|||
return NEXT_FRAME_UNINITIALIZED;
|
||||
}
|
||||
|
||||
float
|
||||
HTMLMediaElement::ComputedVolume() const
|
||||
{
|
||||
return mMuted ? 0.0f : float(mVolume * mAudioChannelVolume);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::ComputedMuted() const
|
||||
{
|
||||
return (mMuted & MUTED_BY_AUDIO_CHANNEL);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#ifdef MOZ_EME
|
||||
#include "mozilla/dom/MediaKeys.h"
|
||||
#endif
|
||||
#include "StateWatching.h"
|
||||
#include "mozilla/StateWatching.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
// X.h on Linux #defines CurrentTime as 0L, so we have to #undef it here.
|
||||
|
@ -646,6 +646,13 @@ public:
|
|||
// that will soon be gone.
|
||||
bool IsBeingDestroyed();
|
||||
|
||||
IMPL_EVENT_HANDLER(mozinterruptbegin)
|
||||
IMPL_EVENT_HANDLER(mozinterruptend)
|
||||
|
||||
// This is for testing only
|
||||
float ComputedVolume() const;
|
||||
bool ComputedMuted() const;
|
||||
|
||||
protected:
|
||||
virtual ~HTMLMediaElement();
|
||||
|
||||
|
|
|
@ -478,29 +478,9 @@ nsBrowserElement::SetInputMethodActive(bool aIsActive,
|
|||
{
|
||||
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (!frameLoader) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> ownerElement;
|
||||
nsresult rv = frameLoader->GetOwnerElement(getter_AddRefs(ownerElement));
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(ownerElement);
|
||||
nsCOMPtr<nsIPrincipal> principal = node->NodePrincipal();
|
||||
if (!nsContentUtils::IsExactSitePermAllow(principal, "input-manage")) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDOMRequest> req;
|
||||
rv = mBrowserElementAPI->SetInputMethodActive(aIsActive,
|
||||
getter_AddRefs(req));
|
||||
nsresult rv = mBrowserElementAPI->SetInputMethodActive(aIsActive,
|
||||
getter_AddRefs(req));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (rv == NS_ERROR_INVALID_ARG) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
|
@ -652,30 +632,44 @@ nsBrowserElement::SetNFCFocus(bool aIsFocus,
|
|||
{
|
||||
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
|
||||
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (!frameLoader) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> ownerElement;
|
||||
nsresult rv = frameLoader->GetOwnerElement(getter_AddRefs(ownerElement));
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(ownerElement);
|
||||
nsCOMPtr<nsIPrincipal> principal = node->NodePrincipal();
|
||||
if (!nsContentUtils::IsExactSitePermAllow(principal, "nfc-manager")) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
rv = mBrowserElementAPI->SetNFCFocus(aIsFocus);
|
||||
nsresult rv = mBrowserElementAPI->SetNFCFocus(aIsFocus);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
nsBrowserElement::ExecuteScript(const nsAString& aScript,
|
||||
const BrowserElementExecuteScriptOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
|
||||
NS_ENSURE_TRUE(IsNotWidgetOrThrow(aRv), nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMDOMRequest> req;
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
|
||||
MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init(wrappedObj->GetJSObject());
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JS::Value> options(cx);
|
||||
if (!ToJSValue(cx, aOptions, &options)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult rv = mBrowserElementAPI->ExecuteScript(aScript, options, getter_AddRefs(req));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_INVALID_ARG) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return req.forget().downcast<DOMRequest>();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace mozilla {
|
|||
|
||||
namespace dom {
|
||||
struct BrowserElementDownloadOptions;
|
||||
struct BrowserElementExecuteScriptOptions;
|
||||
class BrowserElementNextPaintEventCallback;
|
||||
class DOMRequest;
|
||||
enum class BrowserFindCaseSensitivity: uint32_t;
|
||||
|
@ -100,6 +101,10 @@ public:
|
|||
already_AddRefed<dom::DOMRequest> SetInputMethodActive(bool isActive,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<dom::DOMRequest> ExecuteScript(const nsAString& aScript,
|
||||
const dom::BrowserElementExecuteScriptOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void SetNFCFocus(bool isFocus,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@
|
|||
#include "nsIRequest.h"
|
||||
#include "nsHtml5TreeOpExecutor.h"
|
||||
#include "nsHtml5Parser.h"
|
||||
#include "nsIDOMJSWindow.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsIImageDocument.h"
|
||||
#include "mozilla/dom/HTMLBodyElement.h"
|
||||
|
@ -1376,12 +1375,17 @@ nsHTMLDocument::Open(JSContext* /* unused */,
|
|||
NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
|
||||
"XOW should have caught this!");
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window = GetInnerWindow();
|
||||
nsCOMPtr<nsPIDOMWindow> window = GetInnerWindow();
|
||||
if (!window) {
|
||||
rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
nsCOMPtr<nsIDOMJSWindow> win = do_QueryInterface(window);
|
||||
window = nsPIDOMWindow::GetOuterFromCurrentInner(window);
|
||||
if (!window) {
|
||||
rv.Throw(NS_ERROR_NOT_INITIALIZED);
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<nsGlobalWindow> win = static_cast<nsGlobalWindow*>(window.get());
|
||||
nsCOMPtr<nsIDOMWindow> newWindow;
|
||||
// XXXbz We ignore aReplace for now.
|
||||
rv = win->OpenJS(aURL, aName, aFeatures, getter_AddRefs(newWindow));
|
||||
|
@ -2319,21 +2323,16 @@ nsHTMLDocument::NameIsEnumerable(const nsAString& aName)
|
|||
return true;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
IdentifierMapEntryAddNames(nsIdentifierMapEntry* aEntry, void* aArg)
|
||||
{
|
||||
nsTArray<nsString>* aNames = static_cast<nsTArray<nsString>*>(aArg);
|
||||
if (aEntry->HasNameElement() ||
|
||||
aEntry->HasIdElementExposedAsHTMLDocumentProperty()) {
|
||||
aNames->AppendElement(aEntry->GetKey());
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::GetSupportedNames(unsigned, nsTArray<nsString>& aNames)
|
||||
{
|
||||
mIdentifierMap.EnumerateEntries(IdentifierMapEntryAddNames, &aNames);
|
||||
for (auto iter = mIdentifierMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsIdentifierMapEntry* entry = iter.Get();
|
||||
if (entry->HasNameElement() ||
|
||||
entry->HasIdElementExposedAsHTMLDocumentProperty()) {
|
||||
aNames.AppendElement(entry->GetKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<div id="content" style="display: none">
|
||||
<audio id="audio1" />
|
||||
<audio id="audio2" mozaudiochannel="foo" />
|
||||
<audio id="audio3" mozaudiochannel="content" />
|
||||
</div>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
function is(a, b, msg) {
|
||||
parent.postMessage({ status: a === b, msg: msg }, '*');
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
parent.postMessage({ status: !!a, msg: msg }, '*');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
parent.postMessage({ finish: true }, '*');
|
||||
}
|
||||
|
||||
function test_basic() {
|
||||
var audio1 = document.getElementById("audio1");
|
||||
ok(audio1, "Audio Element exists");
|
||||
is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
|
||||
try {
|
||||
audio1.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
|
||||
audio1.mozAudioChannelType = "alarm";
|
||||
is(audio1.mozAudioChannelType, "alarm", "Default audio1 channel == 'alarm'");
|
||||
|
||||
var audio2 = document.getElementById("audio2");
|
||||
ok(audio2, "Audio Element exists");
|
||||
is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
|
||||
try {
|
||||
audio2.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
|
||||
audio2.mozAudioChannelType = "alarm";
|
||||
is(audio2.mozAudioChannelType, "alarm", "Default audio2 channel == 'alarm'");
|
||||
|
||||
var audio3 = document.getElementById("audio3");
|
||||
ok(audio3, "Audio Element exists");
|
||||
is(audio3.mozAudioChannelType, "content", "Default audio3 channel == 'content'");
|
||||
try {
|
||||
audio3.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
is(audio3.mozAudioChannelType, "content", "audio3 channel == 'content'");
|
||||
audio3.mozAudioChannelType = "alarm";
|
||||
is(audio3.mozAudioChannelType, "alarm", "audio3 channel == 'alarm'");
|
||||
|
||||
runTest();
|
||||
}
|
||||
|
||||
function test_preferences(aChannel) {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", aChannel ]]},
|
||||
function() {
|
||||
var audio = document.createElement('audio');
|
||||
ok(audio, "Audio Element created");
|
||||
is(audio.mozAudioChannelType, aChannel, "Default audio channel == '" + aChannel + "'");
|
||||
runTest();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_wrong_preferences() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", 'foobar' ]]},
|
||||
function() {
|
||||
var audio = document.createElement('audio');
|
||||
ok(audio, "Audio Element created");
|
||||
is(audio.mozAudioChannelType, 'normal', "Default audio channel == 'normal'");
|
||||
runTest();
|
||||
}
|
||||
);
|
||||
}
|
||||
var tests = [
|
||||
test_basic,
|
||||
|
||||
function() { test_preferences("content"); },
|
||||
function() { test_preferences("notification"); },
|
||||
function() { test_preferences("alarm"); },
|
||||
function() { test_preferences("telephony"); },
|
||||
function() { test_preferences("ringer"); },
|
||||
function() { test_preferences("publicnotification"); },
|
||||
|
||||
test_wrong_preferences,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -193,6 +193,7 @@ support-files =
|
|||
wakelock.ogv
|
||||
file_ignoreuserfocus.html
|
||||
simpleFileOpener.js
|
||||
file_mozaudiochannel.html
|
||||
|
||||
[test_a_text.html]
|
||||
[test_anchor_href_cache_invalidation.html]
|
||||
|
|
|
@ -7,96 +7,24 @@
|
|||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<audio id="audio1" />
|
||||
<audio id="audio2" mozaudiochannel="foo" />
|
||||
<audio id="audio3" mozaudiochannel="content" />
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
function test_basic() {
|
||||
var audio1 = document.getElementById("audio1");
|
||||
ok(audio1, "Audio Element exists");
|
||||
is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
|
||||
try {
|
||||
audio1.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
|
||||
audio1.mozAudioChannelType = "alarm";
|
||||
is(audio1.mozAudioChannelType, "alarm", "Default audio1 channel == 'alarm'");
|
||||
|
||||
var audio2 = document.getElementById("audio2");
|
||||
ok(audio2, "Audio Element exists");
|
||||
is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
|
||||
try {
|
||||
audio2.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
|
||||
audio2.mozAudioChannelType = "alarm";
|
||||
is(audio2.mozAudioChannelType, "alarm", "Default audio2 channel == 'alarm'");
|
||||
|
||||
var audio3 = document.getElementById("audio3");
|
||||
ok(audio3, "Audio Element exists");
|
||||
is(audio3.mozAudioChannelType, "content", "Default audio3 channel == 'content'");
|
||||
try {
|
||||
audio3.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
is(audio3.mozAudioChannelType, "content", "audio3 channel == 'content'");
|
||||
audio3.mozAudioChannelType = "alarm";
|
||||
is(audio3.mozAudioChannelType, "alarm", "audio3 channel == 'alarm'");
|
||||
|
||||
runTest();
|
||||
}
|
||||
|
||||
function test_preferences(aChannel) {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", aChannel ]]},
|
||||
function() {
|
||||
var audio = document.createElement('audio');
|
||||
ok(audio, "Audio Element created");
|
||||
is(audio.mozAudioChannelType, aChannel, "Default audio channel == '" + aChannel + "'");
|
||||
runTest();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true]]}, function() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.src = 'file_mozaudiochannel.html';
|
||||
onmessage = function(e) {
|
||||
if ("finish" in e.data) {
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
ok(e.data.status, e.data.msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_wrong_preferences() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", 'foobar' ]]},
|
||||
function() {
|
||||
var audio = document.createElement('audio');
|
||||
ok(audio, "Audio Element created");
|
||||
is(audio.mozAudioChannelType, 'normal', "Default audio channel == 'normal'");
|
||||
runTest();
|
||||
}
|
||||
);
|
||||
}
|
||||
var tests = [
|
||||
test_basic,
|
||||
|
||||
function() { test_preferences("content"); },
|
||||
function() { test_preferences("notification"); },
|
||||
function() { test_preferences("alarm"); },
|
||||
function() { test_preferences("telephony"); },
|
||||
function() { test_preferences("ringer"); },
|
||||
function() { test_preferences("publicnotification"); },
|
||||
|
||||
test_wrong_preferences,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
runTest();
|
||||
document.body.appendChild(ifr);
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -6025,6 +6025,7 @@ private:
|
|||
Atomic<bool> mInvalidatedOnAnyThread;
|
||||
const Mode mMode;
|
||||
bool mHasBeenActive;
|
||||
bool mHasBeenActiveOnConnectionThread;
|
||||
bool mActorDestroyed;
|
||||
bool mInvalidated;
|
||||
|
||||
|
@ -6077,6 +6078,13 @@ public:
|
|||
mHasBeenActive = true;
|
||||
}
|
||||
|
||||
void
|
||||
SetActiveOnConnectionThread()
|
||||
{
|
||||
AssertIsOnConnectionThread();
|
||||
mHasBeenActiveOnConnectionThread = true;
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(
|
||||
mozilla::dom::indexedDB::TransactionBase)
|
||||
|
||||
|
@ -12913,6 +12921,8 @@ StartTransactionOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
|||
MOZ_ASSERT(aConnection);
|
||||
aConnection->AssertIsOnConnectionThread();
|
||||
|
||||
Transaction()->SetActiveOnConnectionThread();
|
||||
|
||||
if (Transaction()->GetMode() != IDBTransaction::READ_ONLY) {
|
||||
nsresult rv = aConnection->BeginWriteTransaction();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -12967,6 +12977,7 @@ TransactionBase::TransactionBase(Database* aDatabase, Mode aMode)
|
|||
, mInvalidatedOnAnyThread(false)
|
||||
, mMode(aMode)
|
||||
, mHasBeenActive(false)
|
||||
, mHasBeenActiveOnConnectionThread(false)
|
||||
, mActorDestroyed(false)
|
||||
, mInvalidated(false)
|
||||
, mResultCode(NS_OK)
|
||||
|
@ -20069,6 +20080,8 @@ VersionChangeOp::DoDatabaseWork(DatabaseConnection* aConnection)
|
|||
IDB_LOG_ID_STRING(mBackgroundChildLoggingId),
|
||||
mLoggingSerialNumber);
|
||||
|
||||
Transaction()->SetActiveOnConnectionThread();
|
||||
|
||||
nsresult rv = aConnection->BeginWriteTransaction();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -21180,7 +21193,8 @@ CommitOp::Run()
|
|||
mTransaction->LoggingSerialNumber(),
|
||||
mLoggingSerialNumber);
|
||||
|
||||
if (mTransaction->GetMode() != IDBTransaction::READ_ONLY) {
|
||||
if (mTransaction->GetMode() != IDBTransaction::READ_ONLY &&
|
||||
mTransaction->mHasBeenActiveOnConnectionThread) {
|
||||
Database* database = mTransaction->GetDatabase();
|
||||
MOZ_ASSERT(database);
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ XPIDL_SOURCES += [
|
|||
'nsIDOMCrypto.idl',
|
||||
'nsIDOMGlobalPropertyInitializer.idl',
|
||||
'nsIDOMHistory.idl',
|
||||
'nsIDOMJSWindow.idl',
|
||||
'nsIDOMLocation.idl',
|
||||
'nsIDOMModalContentWindow.idl',
|
||||
'nsIDOMNavigator.idl',
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; 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 "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(e0f739e3-47e2-4007-af30-181939e97a51)]
|
||||
interface nsIDOMJSWindow : nsISupports
|
||||
{
|
||||
void dump(in DOMString str);
|
||||
|
||||
/**
|
||||
* These methods take one optional argument that's the timer ID to
|
||||
* clear. Often in existing code these methods are passed undefined,
|
||||
* which is a nop so we need to support that as well.
|
||||
*/
|
||||
void clearTimeout([optional] in long handle);
|
||||
void clearInterval([optional] in long handle);
|
||||
|
||||
/**
|
||||
* This method is here for backwards compatibility with 4.x only,
|
||||
* its implementation is a no-op
|
||||
*/
|
||||
void setResizable(in boolean resizable);
|
||||
|
||||
/**
|
||||
* @deprecated These are old Netscape 4 methods. Do not use,
|
||||
* the implementation is no-op.
|
||||
*/
|
||||
void captureEvents();
|
||||
void releaseEvents();
|
||||
|
||||
/**
|
||||
* This is the scriptable version of nsIDOMWindow::open()
|
||||
* that takes 3 optional arguments. Its binary name is OpenJS to
|
||||
* avoid colliding with nsIDOMWindow::open(), which has the
|
||||
* same signature. The reason we can't have that collision is that
|
||||
* the implementation needs to know whether it was called from JS or
|
||||
* not.
|
||||
*
|
||||
* IOW, DO NOT CALL THIS FROM C++
|
||||
*/
|
||||
[binaryname(OpenJS)] nsIDOMWindow open([optional] in DOMString url,
|
||||
[optional] in DOMString name,
|
||||
[optional] in DOMString options);
|
||||
|
||||
/**
|
||||
* This is the scriptable version of
|
||||
* nsIDOMWindow::openDialog() that takes 3 optional
|
||||
* arguments, plus any additional arguments are passed on as
|
||||
* arguments on the dialog's window object (window.arguments).
|
||||
*/
|
||||
nsIDOMWindow openDialog([optional] in DOMString url,
|
||||
[optional] in DOMString name,
|
||||
[optional] in DOMString options);
|
||||
|
||||
/**
|
||||
* window.frames in Netscape 4.x and IE is just a reference to the
|
||||
* window itself (i.e. window.frames === window), but this doesn't
|
||||
* make sense from a generic API point of view so that's why this is
|
||||
* JS specific.
|
||||
*
|
||||
* This property is "replaceable" in JavaScript.
|
||||
*/
|
||||
readonly attribute nsIDOMWindow frames;
|
||||
|
||||
[implicit_jscontext, binaryname(ScriptableContent)]
|
||||
readonly attribute jsval content;
|
||||
};
|
|
@ -53,6 +53,7 @@
|
|||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
#include "mozilla/widget/WidgetMessageUtils.h"
|
||||
#include "mozilla/media/MediaChild.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
|
@ -2112,19 +2113,16 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission)
|
|||
MOZ_ASSERT(permissionManager,
|
||||
"We have no permissionManager in the Content process !");
|
||||
|
||||
nsAutoCString originNoSuffix;
|
||||
OriginAttributes attrs;
|
||||
attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));
|
||||
NS_ENSURE_TRUE(uri, true);
|
||||
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
MOZ_ASSERT(secMan);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsresult rv = secMan->GetAppCodebasePrincipal(uri, permission.appId,
|
||||
permission.isInBrowserElement,
|
||||
getter_AddRefs(principal));
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
|
||||
|
||||
// child processes don't care about modification time.
|
||||
int64_t modificationTime = 0;
|
||||
|
||||
|
|
|
@ -2559,12 +2559,12 @@ ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissio
|
|||
enumerator->GetNext(getter_AddRefs(supp));
|
||||
nsCOMPtr<nsIPermission> perm = do_QueryInterface(supp);
|
||||
|
||||
nsCString host;
|
||||
perm->GetHost(host);
|
||||
uint32_t appId;
|
||||
perm->GetAppId(&appId);
|
||||
bool isInBrowserElement;
|
||||
perm->GetIsInBrowserElement(&isInBrowserElement);
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
perm->GetPrincipal(getter_AddRefs(principal));
|
||||
nsCString origin;
|
||||
if (principal) {
|
||||
principal->GetOrigin(origin);
|
||||
}
|
||||
nsCString type;
|
||||
perm->GetType(type);
|
||||
uint32_t capability;
|
||||
|
@ -2574,8 +2574,7 @@ ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissio
|
|||
int64_t expireTime;
|
||||
perm->GetExpireTime(&expireTime);
|
||||
|
||||
aPermissions->AppendElement(IPC::Permission(host, appId,
|
||||
isInBrowserElement, type,
|
||||
aPermissions->AppendElement(IPC::Permission(origin, type,
|
||||
capability, expireType,
|
||||
expireTime));
|
||||
}
|
||||
|
|
|
@ -182,12 +182,12 @@ parent:
|
|||
* Notifies chrome that there is a focus change involving an editable
|
||||
* object (input, textarea, document, contentEditable. etc.)
|
||||
*
|
||||
* focus PR_TRUE if editable object is receiving focus
|
||||
* PR_FALSE if losing focus
|
||||
* contentCache Cache of content
|
||||
* notification Whole data of the notification
|
||||
* preference Native widget preference for IME updates
|
||||
*/
|
||||
prio(urgent) sync NotifyIMEFocus(bool focus, ContentCache contentCache)
|
||||
prio(urgent) sync NotifyIMEFocus(ContentCache contentCache,
|
||||
IMENotification notification)
|
||||
returns (nsIMEUpdatePreference preference);
|
||||
|
||||
/**
|
||||
|
@ -196,35 +196,28 @@ parent:
|
|||
* Only called when NotifyIMEFocus returns PR_TRUE for mWantUpdates
|
||||
*
|
||||
* contentCache Cache of content
|
||||
* offset Starting offset of the change
|
||||
* removedEnd Ending offset of the range deleted
|
||||
* addedEnd New ending offset after insertion
|
||||
* causedByComposition true if the change is caused by composition
|
||||
*
|
||||
* for insertion, offset == end
|
||||
* for deletion, offset == newEnd
|
||||
* notification Whole data of the notification
|
||||
*/
|
||||
prio(urgent) async NotifyIMETextChange(ContentCache contentCache,
|
||||
uint32_t offset, uint32_t removedEnd,
|
||||
uint32_t addedEnd,
|
||||
bool causedByComposition);
|
||||
IMENotification notification);
|
||||
|
||||
/**
|
||||
* Notifies chrome that there is a IME compostion rect updated
|
||||
*
|
||||
* contentCache Cache of content
|
||||
*/
|
||||
prio(urgent) async NotifyIMESelectedCompositionRect(ContentCache contentCache);
|
||||
prio(urgent) async NotifyIMECompositionUpdate(ContentCache contentCache,
|
||||
IMENotification notification);
|
||||
|
||||
/**
|
||||
* Notifies chrome that there has been a change in selection
|
||||
* Only called when NotifyIMEFocus returns PR_TRUE for mWantUpdates
|
||||
*
|
||||
* contentCache Cache of content
|
||||
* causedByComposition true if the change is caused by composition
|
||||
* notification Whole data of the notification
|
||||
*/
|
||||
prio(urgent) async NotifyIMESelection(ContentCache contentCache,
|
||||
bool causedByComposition);
|
||||
IMENotification notification);
|
||||
|
||||
/**
|
||||
* Notifies chrome of updating its content cache.
|
||||
|
@ -247,7 +240,8 @@ parent:
|
|||
*
|
||||
* contentCache Cache of content
|
||||
*/
|
||||
prio(urgent) async NotifyIMEPositionChange(ContentCache contentCache);
|
||||
prio(urgent) async NotifyIMEPositionChange(ContentCache contentCache,
|
||||
IMENotification notification);
|
||||
|
||||
/**
|
||||
* Instructs chrome to end any pending composition
|
||||
|
|
|
@ -1952,8 +1952,8 @@ TabParent::RecvHideTooltip()
|
|||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvNotifyIMEFocus(const bool& aFocus,
|
||||
const ContentCache& aContentCache,
|
||||
TabParent::RecvNotifyIMEFocus(const ContentCache& aContentCache,
|
||||
const IMENotification& aIMENotification,
|
||||
nsIMEUpdatePreference* aPreference)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
|
@ -1962,12 +1962,10 @@ TabParent::RecvNotifyIMEFocus(const bool& aFocus,
|
|||
return true;
|
||||
}
|
||||
|
||||
IMENotification notification(aFocus ? NOTIFY_IME_OF_FOCUS :
|
||||
NOTIFY_IME_OF_BLUR);
|
||||
mContentCache.AssignContent(aContentCache, ¬ification);
|
||||
IMEStateManager::NotifyIME(notification, widget, true);
|
||||
mContentCache.AssignContent(aContentCache, &aIMENotification);
|
||||
IMEStateManager::NotifyIME(aIMENotification, widget, true);
|
||||
|
||||
if (aFocus) {
|
||||
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
|
||||
*aPreference = widget->GetIMEUpdatePreference();
|
||||
}
|
||||
return true;
|
||||
|
@ -1975,10 +1973,7 @@ TabParent::RecvNotifyIMEFocus(const bool& aFocus,
|
|||
|
||||
bool
|
||||
TabParent::RecvNotifyIMETextChange(const ContentCache& aContentCache,
|
||||
const uint32_t& aStart,
|
||||
const uint32_t& aRemovedEnd,
|
||||
const uint32_t& aAddedEnd,
|
||||
const bool& aCausedByComposition)
|
||||
const IMENotification& aIMENotification)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
|
@ -1988,56 +1983,47 @@ TabParent::RecvNotifyIMETextChange(const ContentCache& aContentCache,
|
|||
nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference();
|
||||
NS_ASSERTION(updatePreference.WantTextChange(),
|
||||
"Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
|
||||
MOZ_ASSERT(!aCausedByComposition ||
|
||||
MOZ_ASSERT(!aIMENotification.mTextChangeData.mCausedByComposition ||
|
||||
updatePreference.WantChangesCausedByComposition(),
|
||||
"The widget doesn't want text change notification caused by composition");
|
||||
#endif
|
||||
|
||||
IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
|
||||
notification.mTextChangeData.mStartOffset = aStart;
|
||||
notification.mTextChangeData.mRemovedEndOffset = aRemovedEnd;
|
||||
notification.mTextChangeData.mAddedEndOffset = aAddedEnd;
|
||||
notification.mTextChangeData.mCausedByComposition = aCausedByComposition;
|
||||
|
||||
mContentCache.AssignContent(aContentCache, ¬ification);
|
||||
mContentCache.MaybeNotifyIME(widget, notification);
|
||||
mContentCache.AssignContent(aContentCache, &aIMENotification);
|
||||
mContentCache.MaybeNotifyIME(widget, aIMENotification);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvNotifyIMESelectedCompositionRect(
|
||||
const ContentCache& aContentCache)
|
||||
TabParent::RecvNotifyIMECompositionUpdate(
|
||||
const ContentCache& aContentCache,
|
||||
const IMENotification& aIMENotification)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget) {
|
||||
return true;
|
||||
}
|
||||
|
||||
IMENotification notification(NOTIFY_IME_OF_COMPOSITION_UPDATE);
|
||||
mContentCache.AssignContent(aContentCache, ¬ification);
|
||||
mContentCache.MaybeNotifyIME(widget, notification);
|
||||
mContentCache.AssignContent(aContentCache, &aIMENotification);
|
||||
mContentCache.MaybeNotifyIME(widget, aIMENotification);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvNotifyIMESelection(const ContentCache& aContentCache,
|
||||
const bool& aCausedByComposition)
|
||||
const IMENotification& aIMENotification)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
return true;
|
||||
|
||||
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||
mContentCache.AssignContent(aContentCache, ¬ification);
|
||||
mContentCache.AssignContent(aContentCache, &aIMENotification);
|
||||
|
||||
const nsIMEUpdatePreference updatePreference =
|
||||
widget->GetIMEUpdatePreference();
|
||||
if (updatePreference.WantSelectionChange() &&
|
||||
(updatePreference.WantChangesCausedByComposition() ||
|
||||
!aCausedByComposition)) {
|
||||
notification.mSelectionChangeData.mCausedByComposition =
|
||||
aCausedByComposition;
|
||||
mContentCache.MaybeNotifyIME(widget, notification);
|
||||
!aIMENotification.mSelectionChangeData.mCausedByComposition)) {
|
||||
mContentCache.MaybeNotifyIME(widget, aIMENotification);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2071,20 +2057,20 @@ TabParent::RecvNotifyIMEMouseButtonEvent(
|
|||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache)
|
||||
TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
|
||||
const IMENotification& aIMENotification)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget) {
|
||||
return true;
|
||||
}
|
||||
|
||||
IMENotification notification(NOTIFY_IME_OF_POSITION_CHANGE);
|
||||
mContentCache.AssignContent(aContentCache, ¬ification);
|
||||
mContentCache.AssignContent(aContentCache, &aIMENotification);
|
||||
|
||||
const nsIMEUpdatePreference updatePreference =
|
||||
widget->GetIMEUpdatePreference();
|
||||
if (updatePreference.WantPositionChanged()) {
|
||||
IMEStateManager::NotifyIME(notification, widget, true);
|
||||
IMEStateManager::NotifyIME(aIMENotification, widget, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2298,7 +2284,11 @@ TabParent::SendSelectionEvent(WidgetSelectionEvent& event)
|
|||
return true;
|
||||
}
|
||||
mContentCache.OnSelectionEvent(event);
|
||||
return PBrowserParent::SendSelectionEvent(event);
|
||||
if (NS_WARN_IF(!PBrowserParent::SendSelectionEvent(event))) {
|
||||
return false;
|
||||
}
|
||||
event.mSucceeded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
|
|
|
@ -162,22 +162,21 @@ public:
|
|||
const ClonedMessageData& aData,
|
||||
InfallibleTArray<CpowEntry>&& aCpows,
|
||||
const IPC::Principal& aPrincipal) override;
|
||||
virtual bool RecvNotifyIMEFocus(const bool& aFocus,
|
||||
const ContentCache& aContentCache,
|
||||
virtual bool RecvNotifyIMEFocus(const ContentCache& aContentCache,
|
||||
const widget::IMENotification& aEventMessage,
|
||||
nsIMEUpdatePreference* aPreference)
|
||||
override;
|
||||
virtual bool RecvNotifyIMETextChange(const ContentCache& aContentCache,
|
||||
const uint32_t& aStart,
|
||||
const uint32_t& aRemovedEnd,
|
||||
const uint32_t& aAddedEnd,
|
||||
const bool& aCausedByComposition) override;
|
||||
virtual bool RecvNotifyIMESelectedCompositionRect(const ContentCache& aContentCache) override;
|
||||
const widget::IMENotification& aEventMessage) override;
|
||||
virtual bool RecvNotifyIMECompositionUpdate(const ContentCache& aContentCache,
|
||||
const widget::IMENotification& aEventMessage) override;
|
||||
virtual bool RecvNotifyIMESelection(const ContentCache& aContentCache,
|
||||
const bool& aCausedByComposition) override;
|
||||
const widget::IMENotification& aEventMessage) override;
|
||||
virtual bool RecvUpdateContentCache(const ContentCache& aContentCache) override;
|
||||
virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
|
||||
bool* aConsumedByIME) override;
|
||||
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache) override;
|
||||
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
|
||||
const widget::IMENotification& aEventMessage) override;
|
||||
virtual bool RecvOnEventNeedingAckReceived(const uint32_t& aMessage) override;
|
||||
virtual bool RecvEndIMEComposition(const bool& aCancel,
|
||||
bool* aNoCompositionEvent,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче