зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
ba2f5fcd61
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 870366 - Blacklisting PREF_JS_EXPORTS in Makefile.ins (because of 852814)
|
||||
bug 832837 removes nsISecurityWarningDialogs.idl, which requires a clobber according to bug 1114669
|
||||
|
|
|
@ -711,7 +711,7 @@ static const AttrCharacteristics gWAIUnivAttrMap[] = {
|
|||
{&nsGkAtoms::aria_flowto, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
||||
{&nsGkAtoms::aria_grabbed, ATTR_VALTOKEN | ATTR_GLOBAL },
|
||||
{&nsGkAtoms::aria_haspopup, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
|
||||
{&nsGkAtoms::aria_hidden, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
|
||||
{&nsGkAtoms::aria_hidden, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL }, /* handled special way */
|
||||
{&nsGkAtoms::aria_invalid, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
|
||||
{&nsGkAtoms::aria_label, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
||||
{&nsGkAtoms::aria_labelledby, ATTR_BYPASSOBJ | ATTR_GLOBAL },
|
||||
|
@ -798,6 +798,15 @@ aria::AttrCharacteristicsFor(nsIAtom* aAtom)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
aria::HasDefinedARIAHidden(nsIContent* aContent)
|
||||
{
|
||||
return aContent &&
|
||||
nsAccUtils::HasDefinedARIAToken(aContent, nsGkAtoms::aria_hidden) &&
|
||||
!aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_hidden,
|
||||
nsGkAtoms::_false, eCaseMatters);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AttrIterator class
|
||||
|
||||
|
|
|
@ -227,6 +227,11 @@ uint64_t UniversalStatesFor(mozilla::dom::Element* aElement);
|
|||
*/
|
||||
uint8_t AttrCharacteristicsFor(nsIAtom* aAtom);
|
||||
|
||||
/**
|
||||
* Return true if the element has defined aria-hidden.
|
||||
*/
|
||||
bool HasDefinedARIAHidden(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Represents a simple enumerator for iterating through ARIA attributes
|
||||
* exposed as object attributes on a given accessible.
|
||||
|
|
|
@ -892,11 +892,7 @@ RuleCache::ApplyFilter(Accessible* aAccessible, uint16_t* aResult)
|
|||
return NS_OK;
|
||||
|
||||
if (nsIAccessibleTraversalRule::PREFILTER_ARIA_HIDDEN & mPreFilter) {
|
||||
nsIContent* content = aAccessible->GetContent();
|
||||
if (content &&
|
||||
nsAccUtils::HasDefinedARIAToken(content, nsGkAtoms::aria_hidden) &&
|
||||
!content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_hidden,
|
||||
nsGkAtoms::_false, eCaseMatters)) {
|
||||
if (aAccessible->IsARIAHidden()) {
|
||||
*aResult |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -873,6 +873,11 @@ Accessible::Attributes()
|
|||
while(attribIter.Next(name, value))
|
||||
attributes->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
|
||||
|
||||
if (IsARIAHidden()) {
|
||||
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::hidden,
|
||||
NS_LITERAL_STRING("true"));
|
||||
}
|
||||
|
||||
// If there is no aria-live attribute then expose default value of 'live'
|
||||
// object attribute used for ARIA role of this accessible.
|
||||
if (mRoleMapEntry) {
|
||||
|
@ -1920,6 +1925,9 @@ Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
|
|||
mContextFlags |= eHasNameDependentParent;
|
||||
else
|
||||
mContextFlags &= ~eHasNameDependentParent;
|
||||
|
||||
if (mParent->IsARIAHidden() || aria::HasDefinedARIAHidden(mContent))
|
||||
SetARIAHidden(true);
|
||||
}
|
||||
|
||||
// Accessible protected
|
||||
|
@ -2377,6 +2385,20 @@ Accessible::ContainerWidget() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Accessible::SetARIAHidden(bool aIsDefined)
|
||||
{
|
||||
if (aIsDefined)
|
||||
mContextFlags |= eARIAHidden;
|
||||
else
|
||||
mContextFlags &= ~eARIAHidden;
|
||||
|
||||
uint32_t length = mChildren.Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
mChildren[i]->SetARIAHidden(aIsDefined);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible protected methods
|
||||
|
||||
|
|
|
@ -889,6 +889,13 @@ public:
|
|||
bool HasNameDependentParent() const
|
||||
{ return mContextFlags & eHasNameDependentParent; }
|
||||
|
||||
/**
|
||||
* Return true if aria-hidden="true" is applied to the accessible or inherited
|
||||
* from the parent.
|
||||
*/
|
||||
bool IsARIAHidden() const { return mContextFlags & eARIAHidden; }
|
||||
void SetARIAHidden(bool aIsDefined);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~Accessible();
|
||||
|
@ -975,8 +982,9 @@ protected:
|
|||
*/
|
||||
enum ContextFlags {
|
||||
eHasNameDependentParent = 1 << 0, // Parent's name depends on this accessible.
|
||||
eARIAHidden = 1 << 1,
|
||||
|
||||
eLastContextFlag = eHasNameDependentParent
|
||||
eLastContextFlag = eARIAHidden
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -1082,7 +1090,7 @@ protected:
|
|||
|
||||
static const uint8_t kChildrenFlagsBits = 2;
|
||||
static const uint8_t kStateFlagsBits = 9;
|
||||
static const uint8_t kContextFlagsBits = 1;
|
||||
static const uint8_t kContextFlagsBits = 2;
|
||||
static const uint8_t kTypeBits = 6;
|
||||
static const uint8_t kGenericTypesBits = 13;
|
||||
|
||||
|
|
|
@ -955,6 +955,22 @@ DocAccessible::ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute
|
|||
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
|
||||
// Update aria-hidden flag for the whole subtree iff aria-hidden is changed
|
||||
// on the root, i.e. ignore any affiliated aria-hidden changes in the subtree
|
||||
// of top aria-hidden.
|
||||
if (aAttribute == nsGkAtoms::aria_hidden) {
|
||||
bool isDefined = aria::HasDefinedARIAHidden(elm);
|
||||
if (isDefined != aAccessible->IsARIAHidden() &&
|
||||
!aAccessible->Parent()->IsARIAHidden()) {
|
||||
aAccessible->SetARIAHidden(isDefined);
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccObjectAttrChangedEvent(aAccessible, aAttribute);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_checked ||
|
||||
(aAccessible->IsButton() &&
|
||||
aAttribute == nsGkAtoms::aria_pressed)) {
|
||||
|
|
|
@ -1344,7 +1344,7 @@ HyperTextAccessible::GetCaretRect(nsIWidget** aWidget)
|
|||
nsIntRect caretRect;
|
||||
caretRect = rect.ToOutsidePixels(frame->PresContext()->AppUnitsPerDevPixel());
|
||||
// ((content screen origin) - (content offset in the widget)) = widget origin on the screen
|
||||
caretRect.MoveBy((*aWidget)->WidgetToScreenOffset() - (*aWidget)->GetClientOffset());
|
||||
caretRect.MoveBy((*aWidget)->WidgetToScreenOffsetUntyped() - (*aWidget)->GetClientOffset());
|
||||
|
||||
// Correct for character size, so that caret always matches the size of
|
||||
// the character. This is important for font size transitions, and is
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../attributes.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
|
@ -40,6 +42,23 @@
|
|||
};
|
||||
}
|
||||
|
||||
function updateARIAHidden(aID, aIsDefined, aChildId)
|
||||
{
|
||||
this.__proto__ = new updateAttribute(aID, "aria-hidden",
|
||||
aIsDefined ? "true" : "false");
|
||||
|
||||
this.finalCheck = function updateARIAHidden()
|
||||
{
|
||||
if (aIsDefined) {
|
||||
testAttrs(aID, {"hidden" : "true"}, true);
|
||||
testAttrs(aChildId, {"hidden" : "true"}, true);
|
||||
} else {
|
||||
testAbsentAttrs(aID, { "hidden": "true"});
|
||||
testAbsentAttrs(aChildId, { "hidden": "true"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug stuff.
|
||||
// gA11yEventDumpID = "eventdump";
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
@ -48,7 +67,8 @@
|
|||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new updateAttribute("hideable", "aria-hidden", "true"));
|
||||
gQueue.push(new updateARIAHidden("hideable", true, "hideable_child"));
|
||||
gQueue.push(new updateARIAHidden("hideable", false, "hideable_child"));
|
||||
|
||||
gQueue.push(new updateAttribute("sortable", "aria-sort", "ascending"));
|
||||
|
||||
|
@ -89,7 +109,7 @@
|
|||
</pre>
|
||||
<div id="eventdump"></div>
|
||||
|
||||
<div id="hideable"><div>Hi</div><div>there</div></div>
|
||||
<div id="hideable"><div id="hideable_child">Hi</div><div>there</div></div>
|
||||
|
||||
<div id="sortable" role="columnheader" aria-sort="none">aria-sort</div>
|
||||
|
||||
|
|
|
@ -319,7 +319,7 @@ pref("media.fragmented-mp4.gonk.enabled", true);
|
|||
pref("media.video-queue.default-size", 3);
|
||||
|
||||
// optimize images' memory usage
|
||||
pref("image.mem.decodeondraw", false);
|
||||
pref("image.mem.decodeondraw", true);
|
||||
pref("image.mem.allow_locking_in_content_processes", false); /* don't allow image locking */
|
||||
// Limit the surface cache to 1/8 of main memory or 128MB, whichever is smaller.
|
||||
// Almost everything that was factored into 'max_decoded_image_kb' is now stored
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -118,7 +118,7 @@ public:
|
|||
int32_t mDelay;
|
||||
bool mRepeat;
|
||||
bool mMetaRefresh;
|
||||
|
||||
|
||||
protected:
|
||||
virtual ~nsRefreshTimer();
|
||||
};
|
||||
|
@ -283,15 +283,15 @@ protected:
|
|||
nsresult CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
|
||||
nsIURI* aBaseURI,
|
||||
bool aTryToSaveOldPresentation = true);
|
||||
nsresult CreateContentViewer(const char * aContentType,
|
||||
nsresult CreateContentViewer(const char * aContentType,
|
||||
nsIRequest * request, nsIStreamListener ** aContentHandler);
|
||||
nsresult NewContentViewerObj(const char * aContentType,
|
||||
nsIRequest * request, nsILoadGroup * aLoadGroup,
|
||||
nsresult NewContentViewerObj(const char * aContentType,
|
||||
nsIRequest * request, nsILoadGroup * aLoadGroup,
|
||||
nsIStreamListener ** aContentHandler, nsIContentViewer ** aViewer);
|
||||
nsresult SetupNewViewer(nsIContentViewer * aNewViewer);
|
||||
|
||||
void SetupReferrerFromChannel(nsIChannel * aChannel);
|
||||
|
||||
|
||||
nsresult GetEldestPresContext(nsPresContext** aPresContext);
|
||||
|
||||
// Get the principal that we'll set on the channel if we're inheriting. If
|
||||
|
@ -325,7 +325,7 @@ protected:
|
|||
const nsAString &aSrcdoc,
|
||||
nsIURI * baseURI,
|
||||
nsContentPolicyType aContentPolicyType);
|
||||
nsresult AddHeadersToChannel(nsIInputStream * aHeadersData,
|
||||
nsresult AddHeadersToChannel(nsIInputStream * aHeadersData,
|
||||
nsIChannel * aChannel);
|
||||
nsresult DoChannelLoad(nsIChannel * aChannel,
|
||||
nsIURILoader * aURILoader,
|
||||
|
@ -650,12 +650,12 @@ protected:
|
|||
// Method to get our current position and size without flushing
|
||||
void DoGetPositionAndSize(int32_t * x, int32_t * y, int32_t * cx,
|
||||
int32_t * cy);
|
||||
|
||||
|
||||
// Call this when a URI load is handed to us (via OnLinkClick or
|
||||
// InternalLoad). This makes sure that we're not inside unload, or that if
|
||||
// we are it's still OK to load this URI.
|
||||
bool IsOKToLoadURI(nsIURI* aURI);
|
||||
|
||||
|
||||
void ReattachEditorToWindow(nsISHEntry *aSHEntry);
|
||||
|
||||
nsCOMPtr<nsIDOMStorageManager> mSessionStorageManager;
|
||||
|
@ -916,7 +916,7 @@ protected:
|
|||
// presentation of the page, and to SetupNewViewer() that the old viewer
|
||||
// should be passed a SHEntry to save itself into.
|
||||
bool mSavingOldViewer;
|
||||
|
||||
|
||||
// @see nsIDocShellHistory::createdDynamically
|
||||
bool mDynamicallyCreated;
|
||||
#ifdef DEBUG
|
||||
|
@ -998,7 +998,7 @@ public:
|
|||
explicit InterfaceRequestorProxy(nsIInterfaceRequestor* p);
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
|
||||
protected:
|
||||
virtual ~InterfaceRequestorProxy();
|
||||
InterfaceRequestorProxy() {}
|
||||
|
|
|
@ -224,7 +224,7 @@ NS_GetContentList(nsINode* aRootNode,
|
|||
// First we look in our hashtable. Then we create a content list if needed
|
||||
if (gContentListHashTable.IsInitialized()) {
|
||||
entry = static_cast<ContentListHashEntry *>
|
||||
(PL_DHashTableAdd(&gContentListHashTable, &hashKey));
|
||||
(PL_DHashTableAdd(&gContentListHashTable, &hashKey, fallible));
|
||||
if (entry)
|
||||
list = entry->mContentList;
|
||||
}
|
||||
|
@ -332,8 +332,7 @@ GetFuncStringContentList(nsINode* aRootNode,
|
|||
nsFuncStringCacheKey hashKey(aRootNode, aFunc, aString);
|
||||
|
||||
entry = static_cast<FuncStringContentListHashEntry *>
|
||||
(PL_DHashTableAdd(&gFuncStringContentListHashTable,
|
||||
&hashKey));
|
||||
(PL_DHashTableAdd(&gFuncStringContentListHashTable, &hashKey, fallible));
|
||||
if (entry) {
|
||||
list = entry->mContentList;
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -92,7 +92,7 @@ ContentPermissionRequestParent::IsBeingDestroyed()
|
|||
{
|
||||
// When TabParent::Destroy() is called, we are being destroyed. It's unsafe
|
||||
// to send out any message now.
|
||||
TabParent* tabParent = static_cast<TabParent*>(Manager());
|
||||
TabParent* tabParent = TabParent::GetFrom(Manager());
|
||||
return tabParent->IsDestroyed();
|
||||
}
|
||||
|
||||
|
@ -397,14 +397,12 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
|||
if (mPermissionRequests[i].type().EqualsLiteral("audio-capture")) {
|
||||
GonkPermissionService::GetInstance()->addGrantInfo(
|
||||
"android.permission.RECORD_AUDIO",
|
||||
static_cast<TabParent*>(
|
||||
mParent->Manager())->Manager()->AsContentParent()->Pid());
|
||||
TabParent::GetFrom(mParent->Manager())->Manager()->AsContentParent()->Pid());
|
||||
}
|
||||
if (mPermissionRequests[i].type().EqualsLiteral("video-capture")) {
|
||||
GonkPermissionService::GetInstance()->addGrantInfo(
|
||||
"android.permission.CAMERA",
|
||||
static_cast<TabParent*>(
|
||||
mParent->Manager())->Manager()->AsContentParent()->Pid());
|
||||
TabParent::GetFrom(mParent->Manager())->Manager()->AsContentParent()->Pid());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1241,18 +1241,36 @@ nsContentUtils::GetParserService()
|
|||
return sParserService;
|
||||
}
|
||||
|
||||
static nsIAtom** sSandboxFlagAttrs[] = {
|
||||
&nsGkAtoms::allowsameorigin, // SANDBOXED_ORIGIN
|
||||
&nsGkAtoms::allowforms, // SANDBOXED_FORMS
|
||||
&nsGkAtoms::allowscripts, // SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES
|
||||
&nsGkAtoms::allowtopnavigation, // SANDBOXED_TOPLEVEL_NAVIGATION
|
||||
&nsGkAtoms::allowpointerlock, // SANDBOXED_POINTER_LOCK
|
||||
&nsGkAtoms::allowpopups // SANDBOXED_AUXILIARY_NAVIGATION
|
||||
};
|
||||
|
||||
static const uint32_t sSandboxFlagValues[] = {
|
||||
SANDBOXED_ORIGIN, // allow-same-origin
|
||||
SANDBOXED_FORMS, // allow-forms
|
||||
SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES, // allow-scripts
|
||||
SANDBOXED_TOPLEVEL_NAVIGATION, // allow-top-navigation
|
||||
SANDBOXED_POINTER_LOCK, // allow-pointer-lock
|
||||
SANDBOXED_AUXILIARY_NAVIGATION // allow-popups
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper function that parses a sandbox attribute (of an <iframe> or
|
||||
* a CSP directive) and converts it to the set of flags used internally.
|
||||
*
|
||||
* @param sandboxAttr the sandbox attribute
|
||||
* @return the set of flags (0 if sandboxAttr is null)
|
||||
* @param aSandboxAttr the sandbox attribute
|
||||
* @return the set of flags (SANDBOXED_NONE if aSandboxAttr is null)
|
||||
*/
|
||||
uint32_t
|
||||
nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr)
|
||||
nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* aSandboxAttr)
|
||||
{
|
||||
// No sandbox attribute, no sandbox flags.
|
||||
if (!sandboxAttr) { return 0; }
|
||||
if (!aSandboxAttr) { return SANDBOXED_NONE; }
|
||||
|
||||
// Start off by setting all the restriction flags.
|
||||
uint32_t out = SANDBOXED_NAVIGATION
|
||||
|
@ -1266,19 +1284,70 @@ nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr)
|
|||
| SANDBOXED_POINTER_LOCK
|
||||
| SANDBOXED_DOMAIN;
|
||||
|
||||
// Macro for updating the flag according to the keywords
|
||||
#define IF_KEYWORD(atom, flags) \
|
||||
if (sandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { out &= ~(flags); }
|
||||
MOZ_ASSERT(ArrayLength(sSandboxFlagAttrs) == ArrayLength(sSandboxFlagValues),
|
||||
"Lengths of SandboxFlagAttrs and SandboxFlagvalues do not match");
|
||||
|
||||
IF_KEYWORD(allowsameorigin, SANDBOXED_ORIGIN)
|
||||
IF_KEYWORD(allowforms, SANDBOXED_FORMS)
|
||||
IF_KEYWORD(allowscripts, SANDBOXED_SCRIPTS | SANDBOXED_AUTOMATIC_FEATURES)
|
||||
IF_KEYWORD(allowtopnavigation, SANDBOXED_TOPLEVEL_NAVIGATION)
|
||||
IF_KEYWORD(allowpointerlock, SANDBOXED_POINTER_LOCK)
|
||||
IF_KEYWORD(allowpopups, SANDBOXED_AUXILIARY_NAVIGATION)
|
||||
// For each flag: if it's in the attribute, update the (out) flag
|
||||
for (uint32_t i = 0; i < ArrayLength(sSandboxFlagAttrs); i++) {
|
||||
if (aSandboxAttr->Contains(*sSandboxFlagAttrs[i], eIgnoreCase)) {
|
||||
out &= ~(sSandboxFlagValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
#undef IF_KEYWORD
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that checks if a string matches (case-insensitive) a valid
|
||||
* sandbox flag.
|
||||
*
|
||||
* @param aFlag the potential sandbox flag
|
||||
* @return true if the flag is a sandbox flag
|
||||
*/
|
||||
bool
|
||||
nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag)
|
||||
{
|
||||
for (uint32_t i = 0; i < ArrayLength(sSandboxFlagAttrs); i++) {
|
||||
if (EqualsIgnoreASCIICase(nsDependentAtomString(*sSandboxFlagAttrs[i]), aFlag)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that returns a string attribute corresponding to the
|
||||
* sandbox flags.
|
||||
*
|
||||
* @param aFlags the sandbox flags
|
||||
* @param aString the attribute corresponding to the flags (null if flags is 0)
|
||||
*/
|
||||
void
|
||||
nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString)
|
||||
{
|
||||
if (!aFlags) {
|
||||
SetDOMStringToNull(aString);
|
||||
return;
|
||||
}
|
||||
|
||||
aString.Truncate();
|
||||
|
||||
// Macro for updating the string according to set flags
|
||||
#define IF_FLAG(flag, atom) \
|
||||
if (!(aFlags & flag)) { \
|
||||
if (!aString.IsEmpty()) { \
|
||||
aString.Append(NS_LITERAL_STRING(" ")); \
|
||||
} \
|
||||
aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
|
||||
}
|
||||
|
||||
IF_FLAG(SANDBOXED_ORIGIN, allowsameorigin)
|
||||
IF_FLAG(SANDBOXED_FORMS, allowforms)
|
||||
IF_FLAG(SANDBOXED_SCRIPTS, allowscripts)
|
||||
IF_FLAG(SANDBOXED_TOPLEVEL_NAVIGATION, allowtopnavigation)
|
||||
IF_FLAG(SANDBOXED_POINTER_LOCK, allowpointerlock)
|
||||
IF_FLAG(SANDBOXED_AUXILIARY_NAVIGATION, allowpopups)
|
||||
#undef IF_FLAG
|
||||
}
|
||||
|
||||
nsIBidiKeyboard*
|
||||
|
@ -3960,7 +4029,7 @@ nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
|
|||
|
||||
EventListenerManagerMapEntry *entry =
|
||||
static_cast<EventListenerManagerMapEntry *>
|
||||
(PL_DHashTableAdd(&sEventListenerManagersHash, aNode));
|
||||
(PL_DHashTableAdd(&sEventListenerManagersHash, aNode, fallible));
|
||||
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
|
@ -7095,8 +7164,7 @@ nsContentUtils::CallOnAllRemoteChildren(nsIMessageBroadcaster* aManager,
|
|||
static_cast<nsFrameMessageManager*>(tabMM.get())->GetCallback();
|
||||
if (cb) {
|
||||
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
|
||||
PBrowserParent* remoteBrowser = fl->GetRemoteBrowser();
|
||||
TabParent* remote = static_cast<TabParent*>(remoteBrowser);
|
||||
TabParent* remote = TabParent::GetFrom(fl);
|
||||
if (remote && aCallback) {
|
||||
aCallback(remote, aArg);
|
||||
}
|
||||
|
|
|
@ -832,11 +832,28 @@ public:
|
|||
* A helper function that parses a sandbox attribute (of an <iframe> or
|
||||
* a CSP directive) and converts it to the set of flags used internally.
|
||||
*
|
||||
* @param sandboxAttr the sandbox attribute
|
||||
* @return the set of flags (0 if sandboxAttr is null)
|
||||
* @param aSandboxAttr the sandbox attribute
|
||||
* @return the set of flags (SANDBOXED_NONE if aSandboxAttr is null)
|
||||
*/
|
||||
static uint32_t ParseSandboxAttributeToFlags(const nsAttrValue* sandboxAttr);
|
||||
static uint32_t ParseSandboxAttributeToFlags(const nsAttrValue* aSandboxAttr);
|
||||
|
||||
/**
|
||||
* A helper function that checks if a string matches a valid sandbox
|
||||
* flag.
|
||||
*
|
||||
* @param aFlag the potential sandbox flag
|
||||
* @return true if the flag is a sandbox flag
|
||||
*/
|
||||
static bool IsValidSandboxFlag(const nsAString& aFlag);
|
||||
|
||||
/**
|
||||
* A helper function that returns a string attribute corresponding to the
|
||||
* sandbox flags.
|
||||
*
|
||||
* @param aFlags the sandbox flags
|
||||
* @param aString the attribute corresponding to the flags (null if flags is 0)
|
||||
*/
|
||||
static void SandboxFlagsToString(uint32_t aFlags, nsAString& aString);
|
||||
|
||||
/**
|
||||
* Fill (with the parameters given) the localized string named |aKey| in
|
||||
|
|
|
@ -2195,8 +2195,7 @@ nsDOMWindowUtils::SendQueryContentEvent(uint32_t aType,
|
|||
}
|
||||
}
|
||||
|
||||
pt += LayoutDeviceIntPoint::FromUntyped(
|
||||
widget->WidgetToScreenOffset() - targetWidget->WidgetToScreenOffset());
|
||||
pt += widget->WidgetToScreenOffset() - targetWidget->WidgetToScreenOffset();
|
||||
|
||||
WidgetQueryContentEvent queryEvent(true, aType, targetWidget);
|
||||
InitEvent(queryEvent, &pt);
|
||||
|
|
|
@ -1715,8 +1715,8 @@ nsDocument::~nsDocument()
|
|||
// Kill the subdocument map, doing this will release its strong
|
||||
// references, if any.
|
||||
if (mSubDocuments) {
|
||||
PL_DHashTableDestroy(mSubDocuments);
|
||||
|
||||
PL_DHashTableFinish(mSubDocuments);
|
||||
delete mSubDocuments;
|
||||
mSubDocuments = nullptr;
|
||||
}
|
||||
|
||||
|
@ -2126,7 +2126,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
|||
}
|
||||
|
||||
if (tmp->mSubDocuments) {
|
||||
PL_DHashTableDestroy(tmp->mSubDocuments);
|
||||
PL_DHashTableFinish(tmp->mSubDocuments);
|
||||
delete tmp->mSubDocuments;
|
||||
tmp->mSubDocuments = nullptr;
|
||||
}
|
||||
|
||||
|
@ -2331,8 +2332,8 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
|
|||
// Delete references to sub-documents and kill the subdocument map,
|
||||
// if any. It holds strong references
|
||||
if (mSubDocuments) {
|
||||
PL_DHashTableDestroy(mSubDocuments);
|
||||
|
||||
PL_DHashTableFinish(mSubDocuments);
|
||||
delete mSubDocuments;
|
||||
mSubDocuments = nullptr;
|
||||
}
|
||||
|
||||
|
@ -2863,7 +2864,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||
NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
|
||||
|
||||
// Figure out if we need to apply an app default CSP or a CSP from an app manifest
|
||||
nsIPrincipal* principal = NodePrincipal();
|
||||
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
|
||||
|
||||
uint16_t appStatus = principal->GetAppStatus();
|
||||
bool applyAppDefaultCSP = false;
|
||||
|
@ -3035,11 +3036,30 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||
// speculative loads.
|
||||
}
|
||||
|
||||
// ----- Set sandbox flags according to CSP header
|
||||
// The document may already have some sandbox flags set (e.g., if the
|
||||
// document is an iframe with the sandbox attribute set). If we have a CSP
|
||||
// sandbox directive, intersect the CSP sandbox flags with the existing
|
||||
// flags. This corresponds to the _least_ permissive policy.
|
||||
uint32_t cspSandboxFlags = SANDBOXED_NONE;
|
||||
rv = csp->GetCSPSandboxFlags(&cspSandboxFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mSandboxFlags |= cspSandboxFlags;
|
||||
|
||||
if (cspSandboxFlags & SANDBOXED_ORIGIN) {
|
||||
// If the new CSP sandbox flags do not have the allow-same-origin flag
|
||||
// reset the document principal to a null principal
|
||||
principal = do_CreateInstance("@mozilla.org/nullprincipal;1");
|
||||
SetPrincipal(principal);
|
||||
}
|
||||
|
||||
|
||||
rv = principal->SetCsp(csp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef PR_LOGGING
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Inserted CSP into principal %p", principal));
|
||||
("Inserted CSP into principal %p", principal.get()));
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
|
@ -3103,15 +3123,32 @@ nsDocument::GetLastModified(nsAString& aLastModified)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
GetFormattedTimeString(PRTime aTime, nsAString& aFormattedTimeString)
|
||||
{
|
||||
PRExplodedTime prtime;
|
||||
PR_ExplodeTime(aTime, PR_LocalTimeParameters, &prtime);
|
||||
// "MM/DD/YYYY hh:mm:ss"
|
||||
char formatedTime[24];
|
||||
if (PR_snprintf(formatedTime, sizeof(formatedTime),
|
||||
"%02ld/%02ld/%04hd %02ld:%02ld:%02ld",
|
||||
prtime.tm_month + 1, prtime.tm_mday, prtime.tm_year,
|
||||
prtime.tm_hour , prtime.tm_min, prtime.tm_sec)) {
|
||||
CopyASCIItoUTF16(nsDependentCString(formatedTime), aFormattedTimeString);
|
||||
} else {
|
||||
// If we for whatever reason failed to find the last modified time
|
||||
// (or even the current time), fall back to what NS4.x returned.
|
||||
aFormattedTimeString.AssignLiteral(MOZ_UTF16("01/01/1970 00:00:00"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::GetLastModified(nsAString& aLastModified) const
|
||||
{
|
||||
if (!mLastModified.IsEmpty()) {
|
||||
aLastModified.Assign(mLastModified);
|
||||
} else {
|
||||
// If we for whatever reason failed to find the last modified time
|
||||
// (or even the current time), fall back to what NS4.x returned.
|
||||
aLastModified.AssignLiteral(MOZ_UTF16("01/01/1970 00:00:00"));
|
||||
GetFormattedTimeString(PR_Now(), aLastModified);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3692,6 +3729,12 @@ nsDocument::RemoveCharSetObserver(nsIObserver* aObserver)
|
|||
mCharSetObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::GetSandboxFlagsAsString(nsAString& aFlags)
|
||||
{
|
||||
nsContentUtils::SandboxFlagsToString(mSandboxFlags, aFlags);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const
|
||||
{
|
||||
|
@ -3984,16 +4027,13 @@ nsDocument::SetSubDocumentFor(Element* aElement, nsIDocument* aSubDoc)
|
|||
SubDocInitEntry
|
||||
};
|
||||
|
||||
mSubDocuments = PL_NewDHashTable(&hash_table_ops, sizeof(SubDocMapEntry));
|
||||
if (!mSubDocuments) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mSubDocuments = new PLDHashTable();
|
||||
PL_DHashTableInit(mSubDocuments, &hash_table_ops, sizeof(SubDocMapEntry));
|
||||
}
|
||||
|
||||
// Add a mapping to the hash table
|
||||
SubDocMapEntry *entry =
|
||||
static_cast<SubDocMapEntry*>
|
||||
(PL_DHashTableAdd(mSubDocuments, aElement));
|
||||
SubDocMapEntry *entry = static_cast<SubDocMapEntry*>
|
||||
(PL_DHashTableAdd(mSubDocuments, aElement, fallible));
|
||||
|
||||
if (!entry) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -8597,25 +8637,9 @@ nsDocument::RetrieveRelevantHeaders(nsIChannel *aChannel)
|
|||
}
|
||||
}
|
||||
|
||||
if (modDate == 0) {
|
||||
// We got nothing from our attempt to ask nsIFileChannel and
|
||||
// nsIHttpChannel for the last modified time. Return the current
|
||||
// time.
|
||||
modDate = PR_Now();
|
||||
}
|
||||
|
||||
mLastModified.Truncate();
|
||||
if (modDate != 0) {
|
||||
PRExplodedTime prtime;
|
||||
PR_ExplodeTime(modDate, PR_LocalTimeParameters, &prtime);
|
||||
// "MM/DD/YYYY hh:mm:ss"
|
||||
char formatedTime[24];
|
||||
if (PR_snprintf(formatedTime, sizeof(formatedTime),
|
||||
"%02ld/%02ld/%04hd %02ld:%02ld:%02ld",
|
||||
prtime.tm_month + 1, prtime.tm_mday, prtime.tm_year,
|
||||
prtime.tm_hour , prtime.tm_min, prtime.tm_sec)) {
|
||||
CopyASCIItoUTF16(nsDependentCString(formatedTime), mLastModified);
|
||||
}
|
||||
GetFormattedTimeString(modDate, mLastModified);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2098,7 +2098,7 @@ nsFrameLoader::TryRemoteBrowser()
|
|||
return false;
|
||||
}
|
||||
|
||||
TabParent* openingTab = static_cast<TabParent*>(parentDocShell->GetOpener());
|
||||
TabParent* openingTab = TabParent::GetFrom(parentDocShell->GetOpener());
|
||||
ContentParent* openerContentParent = nullptr;
|
||||
|
||||
if (openingTab &&
|
||||
|
@ -2304,7 +2304,7 @@ nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
|
|||
bool
|
||||
nsFrameLoader::DoLoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
|
||||
{
|
||||
auto* tabParent = static_cast<TabParent*>(GetRemoteBrowser());
|
||||
auto* tabParent = TabParent::GetFrom(GetRemoteBrowser());
|
||||
if (tabParent) {
|
||||
return tabParent->SendLoadRemoteScript(nsString(aURL), aRunInGlobalScope);
|
||||
}
|
||||
|
@ -2500,7 +2500,7 @@ nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
|
|||
MOZ_ASSERT(!mRemoteBrowser);
|
||||
MOZ_ASSERT(!mCurrentRemoteFrame);
|
||||
mRemoteFrame = true;
|
||||
mRemoteBrowser = static_cast<TabParent*>(aTabParent);
|
||||
mRemoteBrowser = TabParent::GetFrom(aTabParent);
|
||||
mChildID = mRemoteBrowser ? mRemoteBrowser->Manager()->ChildID() : 0;
|
||||
ShowRemoteFrame(nsIntSize(0, 0));
|
||||
}
|
||||
|
|
|
@ -598,6 +598,12 @@ public:
|
|||
return mSandboxFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string representation of sandbox flags (null if no flags as
|
||||
* set).
|
||||
*/
|
||||
void GetSandboxFlagsAsString(nsAString& aFlags);
|
||||
|
||||
/**
|
||||
* Set the sandbox flags for this document.
|
||||
* @see nsSandboxFlags.h for the possible flags
|
||||
|
|
|
@ -230,7 +230,7 @@ nsPropertyTable::SetPropertyInternal(nsPropertyOwner aObject,
|
|||
// value is destroyed
|
||||
nsresult result = NS_OK;
|
||||
PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
|
||||
(PL_DHashTableAdd(&propertyList->mObjectValueMap, aObject));
|
||||
(PL_DHashTableAdd(&propertyList->mObjectValueMap, aObject, fallible));
|
||||
if (!entry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
// A nullptr entry->key is the sign that the entry has just been allocated
|
||||
|
|
|
@ -147,7 +147,7 @@ nsQueryContentEventResult::SetEventResult(nsIWidget* aWidget,
|
|||
}
|
||||
|
||||
// Convert the top widget related coordinates to the given widget's.
|
||||
nsIntPoint offset =
|
||||
LayoutDeviceIntPoint offset =
|
||||
aWidget->WidgetToScreenOffset() - topWidget->WidgetToScreenOffset();
|
||||
mRect.MoveBy(-offset);
|
||||
}
|
||||
|
|
|
@ -31,10 +31,10 @@ protected:
|
|||
|
||||
uint32_t mOffset;
|
||||
nsString mString;
|
||||
nsIntRect mRect;
|
||||
mozilla::LayoutDeviceIntRect mRect;
|
||||
|
||||
bool mSucceeded;
|
||||
bool mReversed;
|
||||
};
|
||||
|
||||
#endif // mozilla_dom_nsQueryContentEventResult_h
|
||||
#endif // mozilla_dom_nsQueryContentEventResult_h
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
#ifndef nsSandboxFlags_h___
|
||||
#define nsSandboxFlags_h___
|
||||
|
||||
/**
|
||||
* This constant denotes the lack of a sandbox attribute/directive.
|
||||
*/
|
||||
const unsigned long SANDBOXED_NONE = 0x0;
|
||||
|
||||
/**
|
||||
* This flag prevents content from navigating browsing contexts other than
|
||||
* itself, browsing contexts nested inside it, the top-level browsing context
|
||||
|
|
|
@ -122,19 +122,16 @@ NS_IMPL_ISUPPORTS(
|
|||
nsIMemoryReporter)
|
||||
|
||||
nsScriptNameSpaceManager::nsScriptNameSpaceManager()
|
||||
: mIsInitialized(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
|
||||
{
|
||||
if (mIsInitialized) {
|
||||
UnregisterWeakMemoryReporter(this);
|
||||
// Destroy the hash
|
||||
PL_DHashTableFinish(&mGlobalNames);
|
||||
PL_DHashTableFinish(&mNavigatorNames);
|
||||
}
|
||||
UnregisterWeakMemoryReporter(this);
|
||||
// Destroy the hash
|
||||
PL_DHashTableFinish(&mGlobalNames);
|
||||
PL_DHashTableFinish(&mNavigatorNames);
|
||||
MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
|
||||
}
|
||||
|
||||
|
@ -142,9 +139,8 @@ nsGlobalNameStruct *
|
|||
nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const nsAString *aKey,
|
||||
const char16_t **aClassName)
|
||||
{
|
||||
GlobalNameMapEntry *entry =
|
||||
static_cast<GlobalNameMapEntry *>
|
||||
(PL_DHashTableAdd(aTable, aKey));
|
||||
GlobalNameMapEntry *entry = static_cast<GlobalNameMapEntry *>
|
||||
(PL_DHashTableAdd(aTable, aKey, fallible));
|
||||
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
|
@ -326,21 +322,13 @@ nsScriptNameSpaceManager::Init()
|
|||
GlobalNameHashInitEntry
|
||||
};
|
||||
|
||||
mIsInitialized = PL_DHashTableInit(&mGlobalNames, &hash_table_ops,
|
||||
sizeof(GlobalNameMapEntry),
|
||||
fallible,
|
||||
GLOBALNAME_HASHTABLE_INITIAL_LENGTH);
|
||||
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_OUT_OF_MEMORY);
|
||||
PL_DHashTableInit(&mGlobalNames, &hash_table_ops,
|
||||
sizeof(GlobalNameMapEntry),
|
||||
GLOBALNAME_HASHTABLE_INITIAL_LENGTH);
|
||||
|
||||
mIsInitialized = PL_DHashTableInit(&mNavigatorNames, &hash_table_ops,
|
||||
sizeof(GlobalNameMapEntry),
|
||||
fallible,
|
||||
GLOBALNAME_HASHTABLE_INITIAL_LENGTH);
|
||||
if (!mIsInitialized) {
|
||||
PL_DHashTableFinish(&mGlobalNames);
|
||||
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PL_DHashTableInit(&mNavigatorNames, &hash_table_ops,
|
||||
sizeof(GlobalNameMapEntry),
|
||||
GLOBALNAME_HASHTABLE_INITIAL_LENGTH);
|
||||
|
||||
RegisterWeakMemoryReporter(this);
|
||||
|
||||
|
|
|
@ -240,8 +240,6 @@ private:
|
|||
|
||||
PLDHashTable mGlobalNames;
|
||||
PLDHashTable mNavigatorNames;
|
||||
|
||||
bool mIsInitialized;
|
||||
};
|
||||
|
||||
#endif /* nsScriptNameSpaceManager_h__ */
|
||||
|
|
|
@ -829,7 +829,7 @@ function runUnloadTests1(aNextTest)
|
|||
iframe.addEventListener("load", function () {
|
||||
ok(true, description + "old iframe is restored");
|
||||
// And also restore the iframe information with restored contents.
|
||||
iframe.removeEventListener("DOMContentLoaded", arguments.callee, true);
|
||||
iframe.removeEventListener("load", arguments.callee, true);
|
||||
childWindow = iframe.contentWindow;
|
||||
textareaInFrame = iframe.contentDocument.getElementById("textarea");
|
||||
setTimeout(aNextTest, 0);
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: default-src 'self'
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: default-src 'self'
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: default-src 'none'
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: default-src 'none'
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: default-src 'none' 'unsafe-inline';
|
|
@ -1 +0,0 @@
|
|||
Content-Security-Policy: default-src 'self' 'unsafe-inline';
|
|
@ -5,11 +5,12 @@
|
|||
<!-- Content-Security-Policy: default-src 'self' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img_bad&type=img/png"> </img>
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img1_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img_good&type=img/png" />
|
||||
<script src='/tests/dom/base/test/csp/file_CSP.sjs?testid=scripta_bad&type=text/javascript'></script>
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img1a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: default-src 'none'; sandbox -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img10_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img10a_bad&type=img/png" />
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
}
|
||||
</script>
|
||||
<script src='file_csp_sandbox_fail.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with only inline "allow-scripts"
|
||||
|
||||
<!-- Content-Security-Policy: default-src 'none'; script-src 'unsafe-inline'; sandbox allow-scripts -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img11_bad&type=img/png" />
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img11a_bad&type=img/png"> </img>
|
||||
<script src='/tests/dom/base/test/csp/file_CSP.sjs?testid=script11_bad&type=text/javascript'></script>
|
||||
<script src='http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=script11a_bad&type=text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
|
||||
document.getElementById('a_form').submit();
|
||||
|
||||
// trigger the javascript: url test
|
||||
sendMouseEvent({type:'click'}, 'a_link');
|
||||
}
|
||||
</script>
|
||||
<script src='file_csp_sandbox_pass.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with "allow-same-origin" and allow-scripts"
|
||||
|
||||
|
||||
<!-- Content-Security-Policy: sandbox allow-same-origin allow-scripts; default-src 'self' 'unsafe-inline'; -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img12_bad&type=img/png"> </img>
|
||||
<script src='http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=script12_bad&type=text/javascript'></script>
|
||||
|
||||
<form method="get" action="/tests/content/html/content/test/file_iframe_sandbox_form_fail.html" id="a_form">
|
||||
First name: <input type="text" name="firstname">
|
||||
Last name: <input type="text" name="lastname">
|
||||
<input type="submit" onclick="doSubmit()" id="a_button">
|
||||
</form>
|
||||
|
||||
<a href = 'javascript:ok(true, "documents sandboxed with allow-scripts should be able to run script from javascript: URLs");' id='a_link'>click me</a>
|
||||
</body>
|
||||
</html>
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img2a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,12 +1,13 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox -->
|
||||
<!-- sandbox="allow-same-origin" -->
|
||||
<!-- Content-Security-Policy: default-src 'none' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img3_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img3a_bad&type=img/png" />
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -7,6 +7,7 @@
|
|||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img4_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img4a_bad&type=img/png" />
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -10,12 +10,12 @@
|
|||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
}
|
||||
</script>
|
||||
<script src='file_iframe_sandbox_pass.js'></script>
|
||||
<script src='file_csp_sandbox_fail.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with only inline "allow-scripts"
|
||||
|
||||
<!-- sandbox="allow-scripts" -->
|
||||
<!-- Content-Security-Policy: default-src 'none' 'unsafe-inline'-->
|
||||
<!-- Content-Security-Policy: default-src 'none'; script-src 'unsafe-inline' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img5_bad&type=img/png" />
|
|
@ -18,13 +18,13 @@
|
|||
sendMouseEvent({type:'click'}, 'a_link');
|
||||
}
|
||||
</script>
|
||||
<script src='file_iframe_sandbox_pass.js'></script>
|
||||
<script src='file_csp_sandbox_pass.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with "allow-scripts"
|
||||
I am sandboxed but with "allow-same-origin" and allow-scripts"
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img6_bad&type=img/png"> </img>
|
||||
<script src='http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=script6_bad&type=text/javascript'></script>
|
||||
|
||||
<form method="get" action="file_iframe_sandbox_form_fail.html" id="a_form">
|
||||
<form method="get" action="/tests/content/html/content/test/file_iframe_sandbox_form_fail.html" id="a_form">
|
||||
First name: <input type="text" name="firstname">
|
||||
Last name: <input type="text" name="lastname">
|
||||
<input type="submit" onclick="doSubmit()" id="a_button">
|
|
@ -0,0 +1,15 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: default-src 'self'; sandbox allow-same-origin -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img7_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img7a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: sandbox; default-src 'self' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img8_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img8a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: default-src 'none'; sandbox allow-same-origin -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img9_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img9a_bad&type=img/png" />
|
||||
|
||||
<script src='/tests/dom/base/test/csp/file_csp_sandbox_fail.js'></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
ok(false, "documents sandboxed with allow-scripts should NOT be able to run <script src=...>");
|
|
@ -0,0 +1,4 @@
|
|||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run <script src=...>");
|
|
@ -30,16 +30,25 @@ function handleRequest(request, response)
|
|||
query[name] = unescape(value);
|
||||
});
|
||||
|
||||
var csp = unescape(query['csp']);
|
||||
var file = unescape(query['file']);
|
||||
|
||||
// avoid confusing cache behaviors
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
// Deliver the CSP policy encoded in the URI
|
||||
response.setHeader("Content-Security-Policy", csp, false);
|
||||
if (query['csp']) {
|
||||
var csp = unescape(query['csp']);
|
||||
// Deliver the CSP policy encoded in the URI
|
||||
response.setHeader("Content-Security-Policy", csp, false);
|
||||
}
|
||||
|
||||
// Send HTML to test allowed/blocked behaviors
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.write(loadHTMLFromFile(file));
|
||||
if (query['cspRO']) {
|
||||
var cspRO = unescape(query['cspRO']);
|
||||
// Deliver the CSP report-only policy encoded in the URI
|
||||
response.setHeader("Content-Security-Policy-Report-Only", cspRO, false);
|
||||
}
|
||||
|
||||
if (query['file']) {
|
||||
var file = unescape(query['file']);
|
||||
// Send HTML to test allowed/blocked behaviors
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.write(loadHTMLFromFile(file));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
function doStuff() {
|
||||
var beforePrincipal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
document.open();
|
||||
document.write("rewritten sandboxed document");
|
||||
document.close();
|
||||
var afterPrincipal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
ok(beforePrincipal.equals(afterPrincipal),
|
||||
"document.write() does not change underlying principal");
|
||||
}
|
||||
</script>
|
||||
<body onLoad='doStuff();'>
|
||||
sandboxed with allow-scripts
|
||||
</body>
|
||||
</html>
|
|
@ -45,18 +45,20 @@ support-files =
|
|||
file_bug836922_npolicies.html^headers^
|
||||
file_bug836922_npolicies_ro_violation.sjs
|
||||
file_bug836922_npolicies_violation.sjs
|
||||
file_bug886164.html
|
||||
file_bug886164.html^headers^
|
||||
file_bug886164_2.html
|
||||
file_bug886164_2.html^headers^
|
||||
file_bug886164_3.html
|
||||
file_bug886164_3.html^headers^
|
||||
file_bug886164_4.html
|
||||
file_bug886164_4.html^headers^
|
||||
file_bug886164_5.html
|
||||
file_bug886164_5.html^headers^
|
||||
file_bug886164_6.html
|
||||
file_bug886164_6.html^headers^
|
||||
file_csp_sandbox_pass.js
|
||||
file_csp_sandbox_fail.js
|
||||
file_csp_sandbox_1.html
|
||||
file_csp_sandbox_2.html
|
||||
file_csp_sandbox_3.html
|
||||
file_csp_sandbox_4.html
|
||||
file_csp_sandbox_5.html
|
||||
file_csp_sandbox_6.html
|
||||
file_csp_sandbox_7.html
|
||||
file_csp_sandbox_8.html
|
||||
file_csp_sandbox_9.html
|
||||
file_csp_sandbox_10.html
|
||||
file_csp_sandbox_11.html
|
||||
file_csp_sandbox_12.html
|
||||
file_csp_bug768029.html
|
||||
file_csp_bug768029.sjs
|
||||
file_csp_bug773891.html
|
||||
|
@ -105,6 +107,8 @@ support-files =
|
|||
file_worker_redirect.sjs
|
||||
file_csp_referrerdirective.html
|
||||
referrerdirective.sjs
|
||||
test_iframe_sandbox_csp_top_1.html^headers^
|
||||
file_iframe_sandbox_csp_document_write.html
|
||||
|
||||
[test_base-uri.html]
|
||||
[test_connect-src.html]
|
||||
|
@ -122,7 +126,7 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'and
|
|||
[test_CSP_inlinestyle.html]
|
||||
[test_csp_invalid_source_expression.html]
|
||||
[test_bug836922_npolicies.html]
|
||||
[test_bug886164.html]
|
||||
[test_csp_sandbox.html]
|
||||
[test_csp_redirects.html]
|
||||
[test_CSP_bug910139.html]
|
||||
[test_CSP_bug909029.html]
|
||||
|
@ -130,6 +134,8 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'and
|
|||
[test_nonce_source.html]
|
||||
[test_CSP_bug941404.html]
|
||||
[test_form-action.html]
|
||||
[test_iframe_sandbox_csp.html]
|
||||
[test_iframe_sandbox_csp_top_1.html]
|
||||
skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observers are not available in child processes
|
||||
[test_hash_source.html]
|
||||
skip-if = e10s || buildapp == 'b2g' # can't compute hashes in child process (bug 958702)
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for bugs 886164 and 671389</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var testCases = [
|
||||
{
|
||||
// Test 1: don't load image from non-same-origin; allow loading
|
||||
// images from same-same origin
|
||||
sandboxAttribute: "allow-same-origin",
|
||||
csp: "default-src 'self'",
|
||||
file: "file_csp_sandbox_1.html",
|
||||
results: { img1a_good: -1, img1_bad: -1 }
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 2: don't load image from non-same-origin; allow loading
|
||||
// images from same-same origin, even without allow-same-origin
|
||||
// flag
|
||||
sandboxAttribute: "",
|
||||
csp: "default-src 'self'",
|
||||
file: "file_csp_sandbox_2.html",
|
||||
results: { img2_bad: -1, img2a_good: -1 }
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 3: disallow loading images from any host, even with
|
||||
// allow-same-origin flag set
|
||||
sandboxAttribute: "allow-same-origin",
|
||||
csp: "default-src 'none'",
|
||||
file: "file_csp_sandbox_3.html",
|
||||
results: { img3_bad: -1, img3a_bad: -1 },
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 4: disallow loading images from any host
|
||||
sandboxAttribute: "",
|
||||
csp: "default-src 'none'",
|
||||
file: "file_csp_sandbox_4.html",
|
||||
results: { img4_bad: -1, img4a_bad: -1 }
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 5: disallow loading images or scripts, allow inline scripts
|
||||
sandboxAttribute: "allow-scripts",
|
||||
csp: "default-src 'none'; script-src 'unsafe-inline';",
|
||||
file: "file_csp_sandbox_5.html",
|
||||
results: { img5_bad: -1, img5a_bad: -1, script5_bad: -1, script5a_bad: -1 },
|
||||
nrOKmessages: 2 // sends 2 ok message
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 6: disallow non-same-origin images, allow inline and same origin scripts
|
||||
sandboxAttribute: "allow-same-origin allow-scripts",
|
||||
csp: "default-src 'self' 'unsafe-inline';",
|
||||
file: "file_csp_sandbox_6.html",
|
||||
results: { img6_bad: -1, script6_bad: -1 },
|
||||
nrOKmessages: 4 // sends 4 ok message
|
||||
// fails if forms are not disallowed
|
||||
},
|
||||
{
|
||||
// Test 7: same as Test 1
|
||||
csp: "default-src 'self'; sandbox allow-same-origin",
|
||||
file: "file_csp_sandbox_7.html",
|
||||
results: { img7a_good: -1, img7_bad: -1 }
|
||||
},
|
||||
{
|
||||
// Test 8: same as Test 2
|
||||
csp: "sandbox; default-src 'self'",
|
||||
file: "file_csp_sandbox_8.html",
|
||||
results: { img8_bad: -1, img8a_good: -1 }
|
||||
},
|
||||
{
|
||||
// Test 9: same as Test 3
|
||||
csp: "default-src 'none'; sandbox allow-same-origin",
|
||||
file: "file_csp_sandbox_9.html",
|
||||
results: { img9_bad: -1, img9a_bad: -1 }
|
||||
},
|
||||
{
|
||||
// Test 10: same as Test 4
|
||||
csp: "default-src 'none'; sandbox",
|
||||
file: "file_csp_sandbox_10.html",
|
||||
results: { img10_bad: -1, img10a_bad: -1 }
|
||||
},
|
||||
{
|
||||
// Test 11: same as Test 5
|
||||
csp: "default-src 'none'; script-src 'unsafe-inline'; sandbox allow-scripts",
|
||||
file: "file_csp_sandbox_11.html",
|
||||
results: { img11_bad: -1, img11a_bad: -1, script11_bad: -1, script11a_bad: -1 },
|
||||
nrOKmessages: 2 // sends 2 ok message
|
||||
},
|
||||
{
|
||||
// Test 12: same as Test 6
|
||||
csp: "sandbox allow-same-origin allow-scripts; default-src 'self' 'unsafe-inline';",
|
||||
file: "file_csp_sandbox_12.html",
|
||||
results: { img12_bad: -1, script12_bad: -1 },
|
||||
nrOKmessages: 4 // sends 4 ok message
|
||||
},
|
||||
];
|
||||
|
||||
// a postMessage handler that is used by sandboxed iframes without
|
||||
// 'allow-same-origin' to communicate pass/fail back to this main page.
|
||||
// it expects to be called with an object like:
|
||||
// { ok: true/false,
|
||||
// desc: <description of the test> which it then forwards to ok() }
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
|
||||
function receiveMessage(event) {
|
||||
ok_wrapper(event.data.ok, event.data.desc);
|
||||
}
|
||||
|
||||
var completedTests = 0;
|
||||
var passedTests = 0;
|
||||
|
||||
var totalTests = (function() {
|
||||
var nrCSPloadTests = 0;
|
||||
for(var i = 0; i < testCases.length; i++) {
|
||||
nrCSPloadTests += Object.keys(testCases[i].results).length;
|
||||
if (testCases[i].nrOKmessages) {
|
||||
// + number of expected postMessages from iframe
|
||||
nrCSPloadTests += testCases[i].nrOKmessages;
|
||||
}
|
||||
}
|
||||
return nrCSPloadTests;
|
||||
})();
|
||||
|
||||
function ok_wrapper(result, desc) {
|
||||
ok(result, desc);
|
||||
|
||||
completedTests++;
|
||||
|
||||
if (result) {
|
||||
passedTests++;
|
||||
}
|
||||
|
||||
if (completedTests === totalTests) {
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the iframe src and sandbox attribute
|
||||
function runTest(test) {
|
||||
var iframe = document.createElement('iframe');
|
||||
|
||||
document.getElementById('content').appendChild(iframe);
|
||||
|
||||
// set sandbox attribute
|
||||
if (test.sandboxAttribute !== undefined) {
|
||||
iframe.sandbox = test.sandboxAttribute;
|
||||
}
|
||||
|
||||
// set query string
|
||||
var src = 'file_csp_testserver.sjs';
|
||||
// path where the files are
|
||||
var path = '/tests/dom/base/test/csp/';
|
||||
|
||||
src += '?file=' + escape(path+test.file);
|
||||
|
||||
if (test.csp !== undefined) {
|
||||
src += '&csp=' + escape(test.csp);
|
||||
}
|
||||
|
||||
iframe.src = src;
|
||||
iframe.width = iframe.height = 10;
|
||||
}
|
||||
|
||||
// Examiner related
|
||||
|
||||
// This is used to watch the blocked data bounce off CSP and allowed data
|
||||
// get sent out to the wire.
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
var testpat = new RegExp("testid=([a-z0-9_]+)");
|
||||
|
||||
//_good things better be allowed!
|
||||
//_bad things better be stopped!
|
||||
|
||||
if (topic === "specialpowers-http-notify-request") {
|
||||
//these things were allowed by CSP
|
||||
var uri = data;
|
||||
if (!testpat.test(uri)) return;
|
||||
var testid = testpat.exec(uri)[1];
|
||||
|
||||
if(/_good/.test(testid)) {
|
||||
ok_wrapper(true, uri + " is allowed by csp");
|
||||
} else {
|
||||
ok_wrapper(false, uri + " should not be allowed by csp");
|
||||
}
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
//these were blocked... record that they were blocked
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
|
||||
if (!testpat.test(asciiSpec)) return;
|
||||
var testid = testpat.exec(asciiSpec)[1];
|
||||
if(/_bad/.test(testid)) {
|
||||
ok_wrapper(true, asciiSpec + " was blocked by \"" + data + "\"");
|
||||
} else {
|
||||
ok_wrapper(false, asciiSpec + " should have been blocked by \"" + data + "\"");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(function() { // Run tests:
|
||||
for(var i = 0; i < testCases.length; i++) {
|
||||
runTest(testCases[i]);
|
||||
}
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,239 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=671389
|
||||
Bug 671389 - Implement CSP sandbox directive
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for Bug 671389</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Check if two sandbox flags are the same, ignoring case-sensitivity.
|
||||
// getSandboxFlags returns a list of sandbox flags (if any) or
|
||||
// null if the flag is not set.
|
||||
// This function checks if two flags are the same, i.e., they're
|
||||
// either not set or have the same flags.
|
||||
function eqFlags(a, b) {
|
||||
if (a === null && b === null) { return true; }
|
||||
if (a === null || b === null) { return false; }
|
||||
if (a.length !== b.length) { return false; }
|
||||
var a_sorted = a.map(function(e) { return e.toLowerCase(); }).sort();
|
||||
var b_sorted = b.map(function(e) { return e.toLowerCase(); }).sort();
|
||||
for (var i in a_sorted) {
|
||||
if (a_sorted[i] !== b_sorted[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the sandbox flags of document doc.
|
||||
// If the flag is not set sandboxFlagsAsString returns null,
|
||||
// this function also returns null.
|
||||
// If the flag is set it may have some flags; in this case
|
||||
// this function returns the (potentially empty) list of flags.
|
||||
function getSandboxFlags(doc) {
|
||||
var flags = doc.sandboxFlagsAsString;
|
||||
if (flags === null) { return null; }
|
||||
return flags? flags.split(" "):[];
|
||||
}
|
||||
|
||||
// Constructor for a CSP sandbox flags test. The constructor
|
||||
// expectes a description 'desc' and set of options 'opts':
|
||||
// - sandboxAttribute: [null] or string corresponding to the iframe sandbox attributes
|
||||
// - csp: [null] or string corresponding to the CSP sandbox flags
|
||||
// - cspReportOnly: [null] or string corresponding to the CSP report-only sandbox flags
|
||||
// - file: [null] or string corresponding to file the server should serve
|
||||
// Above, we use [brackets] to denote default values.
|
||||
function CSPFlagsTest(desc, opts) {
|
||||
function ifundef(x, v) {
|
||||
return (x !== undefined) ? x : v;
|
||||
}
|
||||
|
||||
function intersect(as, bs) { // Intersect two csp attributes:
|
||||
as = as === null ? null
|
||||
: as.split(' ').filter(function(x) { return !!x; });
|
||||
bs = bs === null ? null
|
||||
: bs.split(' ').filter(function(x) { return !!x; });
|
||||
|
||||
if (as === null) { return bs; }
|
||||
if (bs === null) { return as; }
|
||||
|
||||
var cs = [];
|
||||
as.forEach(function(a) {
|
||||
if (a && bs.indexOf(a) != -1)
|
||||
cs.push(a);
|
||||
});
|
||||
return cs;
|
||||
}
|
||||
|
||||
this.desc = desc || "Untitled test";
|
||||
this.attr = ifundef(opts.sandboxAttribute, null);
|
||||
this.csp = ifundef(opts.csp, null);
|
||||
this.cspRO = ifundef(opts.cspReportOnly, null);
|
||||
this.file = ifundef(opts.file, null);
|
||||
this.expected = intersect(this.attr, this.csp);
|
||||
}
|
||||
|
||||
// Return function that checks that the actual flags are the same as the
|
||||
// expected flags
|
||||
CSPFlagsTest.prototype.checkFlags = function(iframe) {
|
||||
var this_ = this;
|
||||
return function() {
|
||||
try {
|
||||
var actual = getSandboxFlags(SpecialPowers.wrap(iframe).contentDocument);
|
||||
ok(eqFlags(actual, this_.expected),
|
||||
this_.desc, 'expected: "' + this_.expected + '", got: "' + actual + '"');
|
||||
} catch (e) {
|
||||
ok(false, this_.desc, 'expected: "' + this_.expected + '", failed with: "' + e + '"');
|
||||
}
|
||||
runNextTest();
|
||||
};
|
||||
};
|
||||
|
||||
// Set the iframe src and sandbox attribute
|
||||
CSPFlagsTest.prototype.runTest = function () {
|
||||
var iframe = document.createElement('iframe');
|
||||
document.getElementById("content").appendChild(iframe);
|
||||
iframe.onload = this.checkFlags(iframe);
|
||||
|
||||
// set sandbox attribute
|
||||
if (this.attr === null) {
|
||||
iframe.removeAttribute('sandbox');
|
||||
} else {
|
||||
iframe.sandbox = this.attr;
|
||||
}
|
||||
|
||||
// set query string
|
||||
var src = 'file_csp_testserver.sjs';
|
||||
|
||||
var delim = '?';
|
||||
|
||||
if (this.csp !== null) {
|
||||
src += delim + 'csp=' + escape('sandbox ' + this.csp);
|
||||
delim = '&';
|
||||
}
|
||||
|
||||
if (this.cspRO !== null) {
|
||||
src += delim + 'cspRO=' + escape('sandbox ' + this.cspRO);
|
||||
delim = '&';
|
||||
}
|
||||
|
||||
if (this.file !== null) {
|
||||
src += delim + 'file=' + escape(this.file);
|
||||
delim = '&';
|
||||
}
|
||||
|
||||
iframe.src = src;
|
||||
iframe.width = iframe.height = 10;
|
||||
|
||||
}
|
||||
|
||||
testCases = [
|
||||
{
|
||||
desc: "Test 1: Header should not override attribute",
|
||||
sandboxAttribute: "",
|
||||
csp: "allow-forms aLLOw-POinter-lock alLOW-popups aLLOW-SAME-ORIGin ALLOW-SCRIPTS allow-top-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 2: Attribute should not override header",
|
||||
sandboxAttribute: "sandbox allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation",
|
||||
csp: ""
|
||||
},
|
||||
{
|
||||
desc: "Test 3: Header and attribute intersect",
|
||||
sandboxAttribute: "allow-same-origin allow-scripts",
|
||||
csp: "allow-forms allow-same-origin allow-scripts"
|
||||
},
|
||||
{
|
||||
desc: "Test 4: CSP sandbox sets the right flags (pt 1)",
|
||||
csp: "alLOW-FORms ALLOW-pointer-lock allow-popups allow-same-origin allow-scripts ALLOW-TOP-NAVIGation"
|
||||
},
|
||||
{
|
||||
desc: "Test 5: CSP sandbox sets the right flags (pt 2)",
|
||||
csp: "allow-same-origin allow-TOP-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 6: CSP sandbox sets the right flags (pt 3)",
|
||||
csp: "allow-FORMS ALLOW-scripts"
|
||||
},
|
||||
{
|
||||
desc: "Test 7: CSP sandbox sets the right flags (pt 4)",
|
||||
csp: ""
|
||||
},
|
||||
{
|
||||
desc: "Test 8: CSP sandbox sets the right flags (pt 5)",
|
||||
csp: null
|
||||
},
|
||||
{
|
||||
desc: "Test 9: Read-only header should not override attribute",
|
||||
sandboxAttribute: "",
|
||||
cspReportOnly: "allow-forms ALLOW-pointer-lock allow-POPUPS allow-same-origin ALLOW-scripts allow-top-NAVIGATION"
|
||||
},
|
||||
{
|
||||
desc: "Test 10: Read-only header should not override CSP header",
|
||||
csp: "allow-forms allow-scripts",
|
||||
cspReportOnly: "allow-forms aLlOw-PoInTeR-lOcK aLLow-pOPupS aLLoW-SaME-oRIgIN alLow-scripts allow-tOp-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 11: Read-only header should not override attribute or CSP header",
|
||||
sandboxAttribute: "allow-same-origin allow-scripts",
|
||||
csp: "allow-forms allow-same-origin allow-scripts",
|
||||
cspReportOnly: "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 12: CSP sandbox not affected by document.write()",
|
||||
csp: "allow-scripts",
|
||||
file: 'tests/dom/base/test/csp/file_iframe_sandbox_csp_document_write.html'
|
||||
},
|
||||
].map(function(t) { return (new CSPFlagsTest(t.desc,t)); });
|
||||
|
||||
|
||||
var testCaseIndex = 0;
|
||||
|
||||
// Track ok messages from iframes
|
||||
var childMessages = 0;
|
||||
var totalChildMessages = 1;
|
||||
|
||||
|
||||
// Check to see if we ran all the tests and received all messges
|
||||
// from child iframes. If so, finish.
|
||||
function tryFinish() {
|
||||
if (testCaseIndex === testCases.length && childMessages === totalChildMessages){
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
|
||||
tryFinish();
|
||||
|
||||
if (testCaseIndex < testCases.length) {
|
||||
testCases[testCaseIndex].runTest();
|
||||
testCaseIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
function receiveMessage(event) {
|
||||
ok(event.data.ok, event.data.desc);
|
||||
childMessages++;
|
||||
tryFinish();
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
|
||||
addLoadEvent(runNextTest);
|
||||
</script>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=671389">Mozilla Bug 671389</a> - Implement CSP sandbox directive
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=671389
|
||||
Bug 671389 - Implement CSP sandbox directive
|
||||
|
||||
Tests CSP sandbox attribute on top-level page.
|
||||
|
||||
Minimal flags: allow-same-origin allow-scripts:
|
||||
Since we need to load the SimpleTest files, we have to set the
|
||||
allow-same-origin flag. Additionally, we set the allow-scripts flag
|
||||
since we need JS to check the flags.
|
||||
|
||||
Though not necessary, for this test we also set the allow-forms flag.
|
||||
We may later wish to extend the testing suite with sandbox_csp_top_*
|
||||
tests that set different permutations of the flags.
|
||||
|
||||
CSP header: Content-Security-Policy: sandbox allow-forms allow-scripts allow-same-origin
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for Bug 671389</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Check if two sandbox flags are the same.
|
||||
// getSandboxFlags returns a list of sandbox flags (if any) or
|
||||
// null if the flag is not set.
|
||||
// This function checks if two flags are the same, i.e., they're
|
||||
// either not set or have the same flags.
|
||||
function eqFlags(a, b) {
|
||||
if (a === null && b === null) { return true; }
|
||||
if (a === null || b === null) { return false; }
|
||||
if (a.length !== b.length) { return false; }
|
||||
var a_sorted = a.sort();
|
||||
var b_sorted = b.sort();
|
||||
for (var i in a_sorted) {
|
||||
if (a_sorted[i] !== b_sorted[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the sandbox flags of document doc.
|
||||
// If the flag is not set sandboxFlagsAsString returns null,
|
||||
// this function also returns null.
|
||||
// If the flag is set it may have some flags; in this case
|
||||
// this function returns the (potentially empty) list of flags.
|
||||
function getSandboxFlags(doc) {
|
||||
var flags = doc.sandboxFlagsAsString;
|
||||
if (flags === null) { return null; }
|
||||
return flags? flags.split(" "):[];
|
||||
}
|
||||
|
||||
function checkFlags(expected) {
|
||||
try {
|
||||
var flags = getSandboxFlags(SpecialPowers.wrap(document));
|
||||
ok(eqFlags(flags, expected), name + ' expected: "' + expected + '", got: "' + flags + '"');
|
||||
} catch (e) {
|
||||
ok(false, name + ' expected "' + expected + ', but failed with ' + e);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<body onLoad='checkFlags(["allow-forms", "allow-scripts", "allow-same-origin"]);'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=671389">Mozilla Bug 671389</a> - Implement CSP sandbox directive
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
I am a top-level page sandboxed with "allow-scripts allow-forms
|
||||
allow-same-origin".
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
Content-Security-Policy: sAnDbOx aLLow-FOrms aLlOw-ScRiPtS ALLOW-same-origin
|
|
@ -4452,13 +4452,15 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
|
|||
|
||||
SVGImageContext svgContext(scaledImageSize, Nothing(), CurrentState().globalAlpha);
|
||||
|
||||
nsresult rv = image.mImgContainer->
|
||||
auto result = image.mImgContainer->
|
||||
Draw(context, scaledImageSize,
|
||||
ImageRegion::Create(gfxRect(src.x, src.y, src.width, src.height)),
|
||||
image.mWhichFrame, GraphicsFilter::FILTER_GOOD,
|
||||
Some(svgContext), modifiedFlags);
|
||||
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (result != DrawResult::SUCCESS) {
|
||||
NS_WARNING("imgIContainer::Draw failed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -505,7 +505,7 @@ IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature)
|
|||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||
WebGLContext* webgl)
|
||||
bool requireCompatProfile, WebGLContext* webgl)
|
||||
{
|
||||
if (!forceEnabled &&
|
||||
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL))
|
||||
|
@ -515,7 +515,7 @@ CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContext> gl = gl::GLContextProvider::CreateHeadless();
|
||||
nsRefPtr<GLContext> gl = gl::GLContextProvider::CreateHeadless(requireCompatProfile);
|
||||
if (!gl) {
|
||||
webgl->GenerateWarning("Error during native OpenGL init.");
|
||||
return nullptr;
|
||||
|
@ -530,7 +530,7 @@ CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
// Eventually, we want to be able to pick ANGLE-EGL or native EGL.
|
||||
static already_AddRefed<GLContext>
|
||||
CreateHeadlessANGLE(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||
WebGLContext* webgl)
|
||||
bool requireCompatProfile, WebGLContext* webgl)
|
||||
{
|
||||
nsRefPtr<GLContext> gl;
|
||||
|
||||
|
@ -543,7 +543,7 @@ CreateHeadlessANGLE(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless();
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless(requireCompatProfile);
|
||||
if (!gl) {
|
||||
webgl->GenerateWarning("Error during ANGLE OpenGL init.");
|
||||
return nullptr;
|
||||
|
@ -555,13 +555,13 @@ CreateHeadlessANGLE(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
}
|
||||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateHeadlessEGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||
CreateHeadlessEGL(bool forceEnabled, bool requireCompatProfile,
|
||||
WebGLContext* webgl)
|
||||
{
|
||||
nsRefPtr<GLContext> gl;
|
||||
|
||||
#ifdef ANDROID
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless();
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless(requireCompatProfile);
|
||||
if (!gl) {
|
||||
webgl->GenerateWarning("Error during EGL OpenGL init.");
|
||||
return nullptr;
|
||||
|
@ -583,16 +583,22 @@ CreateHeadlessGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"))
|
||||
disableANGLE = true;
|
||||
|
||||
bool requireCompatProfile = webgl->IsWebGL2() ? false : true;
|
||||
|
||||
nsRefPtr<GLContext> gl;
|
||||
|
||||
if (preferEGL)
|
||||
gl = CreateHeadlessEGL(forceEnabled, gfxInfo, webgl);
|
||||
gl = CreateHeadlessEGL(forceEnabled, requireCompatProfile, webgl);
|
||||
|
||||
if (!gl && !disableANGLE)
|
||||
gl = CreateHeadlessANGLE(forceEnabled, gfxInfo, webgl);
|
||||
if (!gl && !disableANGLE) {
|
||||
gl = CreateHeadlessANGLE(forceEnabled, gfxInfo, requireCompatProfile,
|
||||
webgl);
|
||||
}
|
||||
|
||||
if (!gl)
|
||||
gl = CreateHeadlessNativeGL(forceEnabled, gfxInfo, webgl);
|
||||
if (!gl) {
|
||||
gl = CreateHeadlessNativeGL(forceEnabled, gfxInfo,
|
||||
requireCompatProfile, webgl);
|
||||
}
|
||||
|
||||
return gl.forget();
|
||||
}
|
||||
|
|
|
@ -1209,9 +1209,10 @@ protected:
|
|||
|
||||
// -------------------------------------------------------------------------
|
||||
// WebGL 2 specifics (implemented in WebGL2Context.cpp)
|
||||
|
||||
public:
|
||||
virtual bool IsWebGL2() const = 0;
|
||||
|
||||
protected:
|
||||
bool InitWebGL2();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
@ -2106,7 +2106,6 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
|||
|
||||
// if we're reading alpha, we may need to do fixup. Note that we don't allow
|
||||
// GL_ALPHA to readpixels currently, but we had the code written for it already.
|
||||
|
||||
const bool formatHasAlpha = format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_RGBA;
|
||||
if (!formatHasAlpha)
|
||||
|
|
|
@ -1117,14 +1117,22 @@ WebGLContext::AssertCachedState()
|
|||
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_CLEAR_VALUE, mStencilClearValue);
|
||||
|
||||
GLint stencilBits = 0;
|
||||
gl->fGetIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
|
||||
const GLuint stencilRefMask = (1 << stencilBits) - 1;
|
||||
if (GetStencilBits(&stencilBits)) {
|
||||
const GLuint stencilRefMask = (1 << stencilBits) - 1;
|
||||
|
||||
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, stencilRefMask, mStencilRefFront);
|
||||
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, stencilRefMask, mStencilRefBack);
|
||||
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, stencilRefMask, mStencilRefFront);
|
||||
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, stencilRefMask, mStencilRefBack);
|
||||
}
|
||||
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack);
|
||||
// GLES 3.0.4, $4.1.4, p177:
|
||||
// [...] the front and back stencil mask are both set to the value `2^s - 1`, where
|
||||
// `s` is greater than or equal to the number of bits in the deepest stencil buffer
|
||||
// supported by the GL implementation.
|
||||
const int maxStencilBits = 8;
|
||||
const GLuint maxStencilBitsMask = (1 << maxStencilBits) - 1;
|
||||
|
||||
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, maxStencilBitsMask, mStencilValueMaskFront);
|
||||
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, maxStencilBitsMask, mStencilValueMaskBack);
|
||||
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront);
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack);
|
||||
|
|
|
@ -1779,8 +1779,8 @@ WebGLContext::InitAndValidateGL()
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
// on desktop OpenGL, we always keep vertex attrib 0 array enabled
|
||||
if (!gl->IsGLES())
|
||||
// For OpenGL compat. profiles, we always keep vertex attrib 0 array enabled.
|
||||
if (gl->IsCompatibilityProfile())
|
||||
gl->fEnableVertexAttribArray(0);
|
||||
|
||||
if (MinCapabilityMode())
|
||||
|
@ -1889,7 +1889,7 @@ WebGLContext::InitAndValidateGL()
|
|||
// Always 1 for GLES2
|
||||
mMaxFramebufferColorAttachments = 1;
|
||||
|
||||
if (!gl->IsGLES()) {
|
||||
if (gl->IsCompatibilityProfile()) {
|
||||
// gl_PointSize is always available in ES2 GLSL, but has to be
|
||||
// specifically enabled on desktop GLSL.
|
||||
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
|
|
|
@ -182,8 +182,8 @@ ContentEventHandler::QueryContentRect(nsIContent* aContent,
|
|||
resultRect.UnionRect(resultRect, frameRect);
|
||||
}
|
||||
|
||||
aEvent->mReply.mRect =
|
||||
resultRect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel());
|
||||
aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
|
||||
resultRect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
|
||||
aEvent->mSucceeded = true;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -992,8 +992,8 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
|||
} else {
|
||||
rect.UnionRect(rect, frameRect);
|
||||
}
|
||||
aEvent->mReply.mRect =
|
||||
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel());
|
||||
aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
|
||||
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
|
||||
aEvent->mSucceeded = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1043,8 +1043,8 @@ ContentEventHandler::OnQueryCaretRect(WidgetQueryContentEvent* aEvent)
|
|||
}
|
||||
rv = ConvertToRootViewRelativeOffset(caretFrame, caretRect);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aEvent->mReply.mRect =
|
||||
caretRect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
|
||||
caretRect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel()));
|
||||
aEvent->mReply.mOffset = aEvent->mInput.mOffset;
|
||||
aEvent->mSucceeded = true;
|
||||
return NS_OK;
|
||||
|
@ -1076,8 +1076,8 @@ ContentEventHandler::OnQueryCaretRect(WidgetQueryContentEvent* aEvent)
|
|||
rv = ConvertToRootViewRelativeOffset(frame, rect);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aEvent->mReply.mRect =
|
||||
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel());
|
||||
aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
|
||||
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
|
||||
aEvent->mSucceeded = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1149,9 +1149,8 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
|
|||
eventOnRoot.mUseNativeLineBreak = aEvent->mUseNativeLineBreak;
|
||||
eventOnRoot.refPoint = aEvent->refPoint;
|
||||
if (rootWidget != aEvent->widget) {
|
||||
eventOnRoot.refPoint += LayoutDeviceIntPoint::FromUntyped(
|
||||
aEvent->widget->WidgetToScreenOffset() -
|
||||
rootWidget->WidgetToScreenOffset());
|
||||
eventOnRoot.refPoint += aEvent->widget->WidgetToScreenOffset() -
|
||||
rootWidget->WidgetToScreenOffset();
|
||||
}
|
||||
nsPoint ptInRoot =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(&eventOnRoot, rootFrame);
|
||||
|
@ -1214,8 +1213,7 @@ ContentEventHandler::OnQueryDOMWidgetHittest(WidgetQueryContentEvent* aEvent)
|
|||
nsIFrame* docFrame = mPresShell->GetRootFrame();
|
||||
NS_ENSURE_TRUE(docFrame, NS_ERROR_FAILURE);
|
||||
|
||||
LayoutDeviceIntPoint eventLoc = aEvent->refPoint +
|
||||
LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
|
||||
LayoutDeviceIntPoint eventLoc = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
|
||||
nsIntRect docFrameRect = docFrame->GetScreenRect(); // Returns CSS pixels
|
||||
CSSIntPoint eventLocCSS(
|
||||
mPresContext->DevPixelsToIntCSSPixels(eventLoc.x) - docFrameRect.x,
|
||||
|
|
|
@ -902,8 +902,7 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
|
|||
return LayoutDeviceIntPoint::ToUntyped(aPoint);
|
||||
}
|
||||
|
||||
LayoutDeviceIntPoint offset = aPoint +
|
||||
LayoutDeviceIntPoint::FromUntyped(guiEvent->widget->WidgetToScreenOffset());
|
||||
LayoutDeviceIntPoint offset = aPoint + guiEvent->widget->WidgetToScreenOffset();
|
||||
nscoord factor =
|
||||
aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
|
||||
return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
|
||||
|
|
|
@ -1088,8 +1088,7 @@ bool
|
|||
EventStateManager::DispatchCrossProcessEvent(WidgetEvent* aEvent,
|
||||
nsFrameLoader* aFrameLoader,
|
||||
nsEventStatus *aStatus) {
|
||||
PBrowserParent* remoteBrowser = aFrameLoader->GetRemoteBrowser();
|
||||
TabParent* remote = static_cast<TabParent*>(remoteBrowser);
|
||||
TabParent* remote = TabParent::GetFrom(aFrameLoader);
|
||||
if (!remote) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1505,8 +1504,7 @@ EventStateManager::BeginTrackingDragGesture(nsPresContext* aPresContext,
|
|||
|
||||
// Note that |inDownEvent| could be either a mouse down event or a
|
||||
// synthesized mouse move event.
|
||||
mGestureDownPoint = inDownEvent->refPoint +
|
||||
LayoutDeviceIntPoint::FromUntyped(inDownEvent->widget->WidgetToScreenOffset());
|
||||
mGestureDownPoint = inDownEvent->refPoint + inDownEvent->widget->WidgetToScreenOffset();
|
||||
|
||||
inDownFrame->GetContentForEvent(inDownEvent,
|
||||
getter_AddRefs(mGestureDownContent));
|
||||
|
@ -1544,8 +1542,7 @@ EventStateManager::FillInEventFromGestureDown(WidgetMouseEvent* aEvent)
|
|||
// Set the coordinates in the new event to the coordinates of
|
||||
// the old event, adjusted for the fact that the widget might be
|
||||
// different
|
||||
aEvent->refPoint = mGestureDownPoint -
|
||||
LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
|
||||
aEvent->refPoint = mGestureDownPoint - aEvent->widget->WidgetToScreenOffset();
|
||||
aEvent->modifiers = mGestureModifiers;
|
||||
aEvent->buttons = mGestureDownButtons;
|
||||
}
|
||||
|
@ -1601,8 +1598,7 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
// fire drag gesture if mouse has moved enough
|
||||
LayoutDeviceIntPoint pt = aEvent->refPoint +
|
||||
LayoutDeviceIntPoint::FromUntyped(aEvent->widget->WidgetToScreenOffset());
|
||||
LayoutDeviceIntPoint pt = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
|
||||
LayoutDeviceIntPoint distance = pt - mGestureDownPoint;
|
||||
if (Abs(distance.x) > AssertedCast<uint32_t>(pixelThresholdX) ||
|
||||
Abs(distance.y) > AssertedCast<uint32_t>(pixelThresholdY)) {
|
||||
|
@ -3216,9 +3212,9 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
||||
event.refPoint = mouseEvent->refPoint;
|
||||
if (mouseEvent->widget) {
|
||||
event.refPoint += LayoutDeviceIntPoint::FromUntyped(mouseEvent->widget->WidgetToScreenOffset());
|
||||
event.refPoint += mouseEvent->widget->WidgetToScreenOffset();
|
||||
}
|
||||
event.refPoint -= LayoutDeviceIntPoint::FromUntyped(widget->WidgetToScreenOffset());
|
||||
event.refPoint -= widget->WidgetToScreenOffset();
|
||||
event.modifiers = mouseEvent->modifiers;
|
||||
event.buttons = mouseEvent->buttons;
|
||||
event.inputSource = mouseEvent->inputSource;
|
||||
|
@ -4023,8 +4019,8 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
|
|||
// in the other branch here.
|
||||
sSynthCenteringPoint = center;
|
||||
aMouseEvent->widget->SynthesizeNativeMouseMove(
|
||||
LayoutDeviceIntPoint::ToUntyped(center) +
|
||||
aMouseEvent->widget->WidgetToScreenOffset());
|
||||
LayoutDeviceIntPoint::ToUntyped(center +
|
||||
aMouseEvent->widget->WidgetToScreenOffset()));
|
||||
} else if (aMouseEvent->refPoint == sSynthCenteringPoint) {
|
||||
// This is the "synthetic native" event we dispatched to re-center the
|
||||
// pointer. Cancel it so we don't expose the centering move to content.
|
||||
|
@ -4160,7 +4156,7 @@ EventStateManager::SetPointerLock(nsIWidget* aWidget,
|
|||
aWidget,
|
||||
mPresContext);
|
||||
aWidget->SynthesizeNativeMouseMove(
|
||||
LayoutDeviceIntPoint::ToUntyped(sLastRefPoint) + aWidget->WidgetToScreenOffset());
|
||||
LayoutDeviceIntPoint::ToUntyped(sLastRefPoint + aWidget->WidgetToScreenOffset()));
|
||||
|
||||
// Retarget all events to this element via capture.
|
||||
nsIPresShell::SetCapturingContent(aElement, CAPTURE_POINTERLOCK);
|
||||
|
@ -4176,7 +4172,7 @@ EventStateManager::SetPointerLock(nsIWidget* aWidget,
|
|||
// no movement.
|
||||
sLastRefPoint = mPreLockPoint;
|
||||
aWidget->SynthesizeNativeMouseMove(
|
||||
LayoutDeviceIntPoint::ToUntyped(mPreLockPoint) + aWidget->WidgetToScreenOffset());
|
||||
LayoutDeviceIntPoint::ToUntyped(mPreLockPoint + aWidget->WidgetToScreenOffset()));
|
||||
|
||||
// Don't retarget events to this element any more.
|
||||
nsIPresShell::SetCapturingContent(nullptr, CAPTURE_POINTERLOCK);
|
||||
|
@ -4437,6 +4433,14 @@ EventStateManager::CheckForAndDispatchClick(nsPresContext* aPresContext,
|
|||
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIContent> mouseContent = GetEventTargetContent(aEvent);
|
||||
// Click events apply to *elements* not nodes. At this point the target
|
||||
// content may have been reset to some non-element content, and so we need
|
||||
// to walk up the closest ancestor element, just like we do in
|
||||
// nsPresShell::HandlePositionedEvent.
|
||||
while (mouseContent && !mouseContent->IsElement()) {
|
||||
mouseContent = mouseContent->GetParent();
|
||||
}
|
||||
|
||||
if (!mouseContent && !mCurrentTarget) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -455,9 +455,8 @@ IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
|
|||
// The refPt is relative to its widget.
|
||||
// We should notify it with offset in the widget.
|
||||
if (aMouseEvent->widget != mWidget) {
|
||||
charAtPt.refPoint += LayoutDeviceIntPoint::FromUntyped(
|
||||
aMouseEvent->widget->WidgetToScreenOffset() -
|
||||
mWidget->WidgetToScreenOffset());
|
||||
charAtPt.refPoint += aMouseEvent->widget->WidgetToScreenOffset() -
|
||||
mWidget->WidgetToScreenOffset();
|
||||
}
|
||||
|
||||
IMENotification notification(NOTIFY_IME_OF_MOUSE_BUTTON_EVENT);
|
||||
|
@ -465,7 +464,8 @@ IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
|
|||
notification.mMouseButtonEventData.mOffset = charAtPt.mReply.mOffset;
|
||||
notification.mMouseButtonEventData.mCursorPos.Set(
|
||||
LayoutDeviceIntPoint::ToUntyped(charAtPt.refPoint));
|
||||
notification.mMouseButtonEventData.mCharRect.Set(charAtPt.mReply.mRect);
|
||||
notification.mMouseButtonEventData.mCharRect.Set(
|
||||
LayoutDevicePixel::ToUntyped(charAtPt.mReply.mRect));
|
||||
notification.mMouseButtonEventData.mButton = aMouseEvent->button;
|
||||
notification.mMouseButtonEventData.mButtons = aMouseEvent->buttons;
|
||||
notification.mMouseButtonEventData.mModifiers = aMouseEvent->modifiers;
|
||||
|
|
|
@ -57,8 +57,7 @@ public:
|
|||
return LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint);
|
||||
}
|
||||
|
||||
LayoutDeviceIntPoint offset = aEvent->refPoint +
|
||||
LayoutDeviceIntPoint::FromUntyped(event->widget->WidgetToScreenOffset());
|
||||
LayoutDeviceIntPoint offset = aEvent->refPoint + event->widget->WidgetToScreenOffset();
|
||||
nscoord factor =
|
||||
aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
|
||||
return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset.x * factor),
|
||||
|
|
|
@ -293,8 +293,8 @@ WheelTransaction::GetScreenPoint(WidgetGUIEvent* aEvent)
|
|||
{
|
||||
NS_ASSERTION(aEvent, "aEvent is null");
|
||||
NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
|
||||
return LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint) +
|
||||
aEvent->widget->WidgetToScreenOffset();
|
||||
return LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint +
|
||||
aEvent->widget->WidgetToScreenOffset());
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIFormControlFrame.h"
|
||||
#include "nsISecureBrowserUI.h"
|
||||
#include "nsError.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
|
@ -33,6 +32,7 @@
|
|||
#include "mozilla/BinarySearch.h"
|
||||
|
||||
// form submission
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsIFormSubmitObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsICategoryManager.h"
|
||||
|
@ -45,6 +45,9 @@
|
|||
#include "nsIDocShell.h"
|
||||
#include "nsFormData.h"
|
||||
#include "nsFormSubmissionConstants.h"
|
||||
#include "nsIPromptService.h"
|
||||
#include "nsISecurityUITelemetry.h"
|
||||
#include "nsIStringBundle.h"
|
||||
|
||||
// radio buttons
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
|
@ -858,6 +861,108 @@ HTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLFormElement::DoSecureToInsecureSubmitCheck(nsIURI* aActionURL,
|
||||
bool* aCancelSubmit)
|
||||
{
|
||||
*aCancelSubmit = false;
|
||||
|
||||
// Only ask the user about posting from a secure URI to an insecure URI if
|
||||
// this element is in the root document. When this is not the case, the mixed
|
||||
// content blocker will take care of security for us.
|
||||
nsIDocument* parent = OwnerDoc()->GetParentDocument();
|
||||
bool isRootDocument = (!parent || nsContentUtils::IsChromeDoc(parent));
|
||||
if (!isRootDocument) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal* principal = NodePrincipal();
|
||||
if (!principal) {
|
||||
*aCancelSubmit = true;
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
nsresult rv = principal->GetURI(getter_AddRefs(principalURI));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!principalURI) {
|
||||
principalURI = OwnerDoc()->GetDocumentURI();
|
||||
}
|
||||
bool formIsHTTPS;
|
||||
rv = principalURI->SchemeIs("https", &formIsHTTPS);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
bool actionIsHTTPS;
|
||||
rv = aActionURL->SchemeIs("https", &actionIsHTTPS);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
bool actionIsJS;
|
||||
rv = aActionURL->SchemeIs("javascript", &actionIsJS);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!formIsHTTPS || actionIsHTTPS || actionIsJS) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPromptService> promptSvc =
|
||||
do_GetService("@mozilla.org/embedcomp/prompt-service;1");
|
||||
if (!promptSvc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<nsIStringBundle> stringBundle;
|
||||
nsCOMPtr<nsIStringBundleService> stringBundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (!stringBundleService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = stringBundleService->CreateBundle(
|
||||
"chrome://global/locale/browser.properties",
|
||||
getter_AddRefs(stringBundle));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoString title;
|
||||
nsAutoString message;
|
||||
nsAutoString cont;
|
||||
stringBundle->GetStringFromName(
|
||||
MOZ_UTF16("formPostSecureToInsecureWarning.title"), getter_Copies(title));
|
||||
stringBundle->GetStringFromName(
|
||||
MOZ_UTF16("formPostSecureToInsecureWarning.message"),
|
||||
getter_Copies(message));
|
||||
stringBundle->GetStringFromName(
|
||||
MOZ_UTF16("formPostSecureToInsecureWarning.continue"),
|
||||
getter_Copies(cont));
|
||||
int32_t buttonPressed;
|
||||
bool checkState = false; // this is unused (ConfirmEx requires this parameter)
|
||||
nsCOMPtr<nsPIDOMWindow> window = OwnerDoc()->GetWindow();
|
||||
rv = promptSvc->ConfirmEx(window, title.get(), message.get(),
|
||||
(nsIPromptService::BUTTON_TITLE_IS_STRING *
|
||||
nsIPromptService::BUTTON_POS_0) +
|
||||
(nsIPromptService::BUTTON_TITLE_CANCEL *
|
||||
nsIPromptService::BUTTON_POS_1),
|
||||
cont.get(), nullptr, nullptr, nullptr,
|
||||
&checkState, &buttonPressed);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
*aCancelSubmit = (buttonPressed == 1);
|
||||
uint32_t telemetryBucket =
|
||||
nsISecurityUITelemetry::WARNING_CONFIRM_POST_TO_INSECURE_FROM_SECURE;
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SECURITY_UI,
|
||||
telemetryBucket);
|
||||
if (!*aCancelSubmit) {
|
||||
// The user opted to continue, so note that in the next telemetry bucket.
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SECURITY_UI,
|
||||
telemetryBucket + 1);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
|
||||
bool* aCancelSubmit,
|
||||
|
@ -872,28 +977,13 @@ HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
|
|||
NS_FIRST_FORMSUBMIT_CATEGORY);
|
||||
}
|
||||
|
||||
// XXXbz what do the submit observers actually want? The window
|
||||
// of the document this is shown in? Or something else?
|
||||
// sXBL/XBL2 issue
|
||||
nsCOMPtr<nsPIDOMWindow> window = OwnerDoc()->GetWindow();
|
||||
|
||||
// Notify the secure browser UI, if any, that the form is being submitted.
|
||||
nsCOMPtr<nsIDocShell> docshell = OwnerDoc()->GetDocShell();
|
||||
if (docshell && !aEarlyNotify) {
|
||||
nsCOMPtr<nsISecureBrowserUI> secureUI;
|
||||
docshell->GetSecurityUI(getter_AddRefs(secureUI));
|
||||
nsCOMPtr<nsIFormSubmitObserver> formSubmitObserver =
|
||||
do_QueryInterface(secureUI);
|
||||
if (formSubmitObserver) {
|
||||
nsresult rv = formSubmitObserver->Notify(this,
|
||||
window,
|
||||
aActionURL,
|
||||
aCancelSubmit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (*aCancelSubmit) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!aEarlyNotify) {
|
||||
nsresult rv = DoSecureToInsecureSubmitCheck(aActionURL, aCancelSubmit);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (*aCancelSubmit) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -914,6 +1004,11 @@ HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
|
|||
nsCOMPtr<nsISupports> inst;
|
||||
*aCancelSubmit = false;
|
||||
|
||||
// XXXbz what do the submit observers actually want? The window
|
||||
// of the document this is shown in? Or something else?
|
||||
// sXBL/XBL2 issue
|
||||
nsCOMPtr<nsPIDOMWindow> window = OwnerDoc()->GetWindow();
|
||||
|
||||
bool loop = true;
|
||||
while (NS_SUCCEEDED(theEnum->HasMoreElements(&loop)) && loop) {
|
||||
theEnum->GetNext(getter_AddRefs(inst));
|
||||
|
|
|
@ -495,6 +495,16 @@ protected:
|
|||
nsresult NotifySubmitObservers(nsIURI* aActionURL, bool* aCancelSubmit,
|
||||
bool aEarlyNotify);
|
||||
|
||||
/**
|
||||
* If this form submission is secure -> insecure, ask the user if they want
|
||||
* to continue.
|
||||
*
|
||||
* @param aActionURL the URL being submitted to
|
||||
* @param aCancelSubmit out param: will be true if the user wants to cancel
|
||||
*/
|
||||
nsresult DoSecureToInsecureSubmitCheck(nsIURI* aActionURL,
|
||||
bool* aCancelSubmit);
|
||||
|
||||
/**
|
||||
* Find form controls in this form with the correct value in the name
|
||||
* attribute.
|
||||
|
|
|
@ -207,6 +207,10 @@ HTMLImageElement::Complete()
|
|||
return true;
|
||||
}
|
||||
|
||||
if (mPendingRequest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t status;
|
||||
mCurrentRequest->GetImageStatus(&status);
|
||||
return
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 671389</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
I am
|
||||
<ul>
|
||||
<li>sandboxed but with "allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", and "allow-top-navigation", </li>
|
||||
<li>sandboxed but with "allow-same-origin", "allow-scripts", </li>
|
||||
<li>sandboxed, or </li>
|
||||
<li>not sandboxed.</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -92,6 +92,7 @@ support-files =
|
|||
file_iframe_sandbox_c_if6.html
|
||||
file_iframe_sandbox_c_if7.html
|
||||
file_iframe_sandbox_c_if8.html
|
||||
file_iframe_sandbox_c_if9.html
|
||||
file_iframe_sandbox_close.html
|
||||
file_iframe_sandbox_d_if1.html
|
||||
file_iframe_sandbox_d_if10.html
|
||||
|
@ -583,3 +584,4 @@ support-files = file_bug871161-1.html file_bug871161-2.html
|
|||
[test_bug1081037.html]
|
||||
[test_window_open_close.html]
|
||||
skip-if = buildapp == 'b2g' # bug 1129014
|
||||
[test_img_complete.html]
|
||||
|
|
|
@ -41,7 +41,7 @@ function ok_wrapper(result, desc) {
|
|||
passedTests++;
|
||||
}
|
||||
|
||||
if (completedTests == 27) {
|
||||
if (completedTests == 33) {
|
||||
is(passedTests, completedTests, "There are " + completedTests + " general tests that should pass");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -180,6 +180,14 @@ function doTest() {
|
|||
// This is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin"
|
||||
// the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok()
|
||||
// function that calls window.parent.ok_wrapper.
|
||||
|
||||
// passes twice if good
|
||||
// 29-32) Test that sandboxFlagsAsString returns the set flags.
|
||||
// see if_14 and if_15
|
||||
|
||||
// passes once if good
|
||||
// 33) Test that sandboxFlagsAsString returns null if iframe does not have sandbox flag set.
|
||||
// see if_16
|
||||
}
|
||||
|
||||
addLoadEvent(doTest);
|
||||
|
@ -212,6 +220,36 @@ function do_if_10() {
|
|||
var if_10 = document.getElementById('if_10');
|
||||
if_10.src = 'javascript:"<html><script>window.parent.ok_wrapper(true, \'an iframe sandboxed with allow-scripts should execute script in a javascript URL in a newly set src attribute\');<\/script><\/html>"';
|
||||
}
|
||||
|
||||
function eqFlags(a, b) {
|
||||
// both a and b should be either null or have the array same flags
|
||||
if (a === null && b === null) { return true; }
|
||||
if (a === null || b === null) { return false; }
|
||||
if (a.length !== b.length) { return false; }
|
||||
var a_sorted = a.sort();
|
||||
var b_sorted = b.sort();
|
||||
for (var i in a_sorted) {
|
||||
if (a_sorted[i] !== b_sorted[i]) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSandboxFlags(doc) {
|
||||
var flags = doc.sandboxFlagsAsString;
|
||||
if (flags === null) { return null; }
|
||||
return flags? flags.split(" "):[];
|
||||
}
|
||||
|
||||
function test_sandboxFlagsAsString(name, expected) {
|
||||
var ifr = document.getElementById(name);
|
||||
try {
|
||||
var flags = getSandboxFlags(SpecialPowers.wrap(ifr).contentDocument);
|
||||
ok_wrapper(eqFlags(flags, expected), name + ' expected: "' + expected + '", got: "' + flags + '"');
|
||||
} catch (e) {
|
||||
ok_wrapper(false, name + ' expected "' + expected + ', but failed with ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
|
||||
|
@ -234,6 +272,10 @@ function do_if_10() {
|
|||
<iframe sandbox="allow-same-origin allow-scripts" onload='start_if_10()' id='if_10' src="about:blank" height="10" width="10"></iframe>
|
||||
<iframe sandbox="allow-scripts" id='if_11' src="file_iframe_sandbox_c_if7.html" height="10" width="10"></iframe>
|
||||
<iframe sandbox="allow-same-origin allow-scripts" id='if_12' src="file_iframe_sandbox_c_if8.html" height="10" width="10"></iframe>
|
||||
<iframe sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation " id='if_13' src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_13",["allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", "allow-top-navigation"])'></iframe>
|
||||
<iframe sandbox="	allow-same-origin	allow-scripts	" id="if_14" src="file_iframe_sandbox_c_if6.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_14",["allow-same-origin","allow-scripts"])'></iframe>
|
||||
<iframe sandbox="" id="if_15" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_15",[])'></iframe>
|
||||
<iframe id="if_16" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_16",null)'></iframe>
|
||||
<input type='button' id="a_button" onclick='do_if_9()'>
|
||||
<input type='button' id="a_button2" onclick='do_if_10()'>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=608261
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 608261</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 608261 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=608261">Mozilla Bug 608261</a>
|
||||
<p id="display"><img src="image.png"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
addLoadEvent(function() {
|
||||
var img = document.querySelector("img");
|
||||
ok(img.complete, "By onload, image should have loaded");
|
||||
img.src = "image.png?cachebust";
|
||||
ok(!img.complete, "Now that we're loading we should no longer be complete");
|
||||
img.onload = function() {
|
||||
ok(img.complete, "The new thing should have loaded.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -10987,7 +10987,7 @@ FactoryOp::CheckAtLeastOneAppHasPermission(ContentParent* aContentParent,
|
|||
index < count;
|
||||
index++) {
|
||||
uint32_t appId =
|
||||
static_cast<TabParent*>(browsers[index])->OwnOrContainingAppId();
|
||||
TabParent::GetFrom(browsers[index])->OwnOrContainingAppId();
|
||||
MOZ_ASSERT(kUnknownAppId != appId && kNoAppId != appId);
|
||||
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
|
|
|
@ -20,7 +20,7 @@ interface nsIURI;
|
|||
|
||||
typedef unsigned short CSPDirective;
|
||||
|
||||
[scriptable, uuid(68434447-b816-4473-a731-efc4f6d59902)]
|
||||
[scriptable, uuid(9454a677-5342-4220-8154-e619410e07e7)]
|
||||
interface nsIContentSecurityPolicy : nsISerializable
|
||||
{
|
||||
/**
|
||||
|
@ -48,6 +48,7 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
const unsigned short BASE_URI_DIRECTIVE = 13;
|
||||
const unsigned short FORM_ACTION_DIRECTIVE = 14;
|
||||
const unsigned short REFERRER_DIRECTIVE = 15;
|
||||
const unsigned short SANDBOX_DIRECTIVE = 16;
|
||||
|
||||
/**
|
||||
* Accessor method for a read-only string version of the policy at a given
|
||||
|
@ -262,6 +263,17 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
*/
|
||||
boolean permits(in nsIURI aURI, in CSPDirective aDir, in boolean aSpecific);
|
||||
|
||||
/**
|
||||
* Delegate method called by the service when the protected document is loaded.
|
||||
* Returns the intersection of all the sandbox flags contained in
|
||||
* CSP policies. This is the most restricting sandbox policy.
|
||||
* See nsSandboxFlags.h for the possible flags.
|
||||
*
|
||||
* @return
|
||||
* sandbox flags or SANDBOXED_NONE if no sandbox directive exists
|
||||
*/
|
||||
uint32_t getCSPSandboxFlags();
|
||||
|
||||
/**
|
||||
* Delegate method called by the service when sub-elements of the protected
|
||||
* document are being loaded. Given a bit of information about the request,
|
||||
|
|
|
@ -83,7 +83,7 @@ AssertAppProcess(PBrowserParent* aActor,
|
|||
return false;
|
||||
}
|
||||
|
||||
TabParent* tab = static_cast<TabParent*>(aActor);
|
||||
TabParent* tab = TabParent::GetFrom(aActor);
|
||||
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
|
||||
|
||||
return CheckAppTypeHelper(app, aType, aCapability, tab->IsBrowserElement());
|
||||
|
@ -114,7 +114,7 @@ AssertAppStatus(PBrowserParent* aActor,
|
|||
return false;
|
||||
}
|
||||
|
||||
TabParent* tab = static_cast<TabParent*>(aActor);
|
||||
TabParent* tab = TabParent::GetFrom(aActor);
|
||||
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
|
||||
|
||||
return CheckAppStatusHelper(app, aStatus);
|
||||
|
|
|
@ -51,7 +51,7 @@ ColorPickerParent::CreateColorPicker()
|
|||
return false;
|
||||
}
|
||||
|
||||
Element* ownerElement = static_cast<TabParent*>(Manager())->GetOwnerElement();
|
||||
Element* ownerElement = TabParent::GetFrom(Manager())->GetOwnerElement();
|
||||
if (!ownerElement) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1075,7 +1075,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
constructorSender->ChildID(),
|
||||
constructorSender->IsForApp(),
|
||||
constructorSender->IsForBrowser());
|
||||
return static_cast<TabParent*>(browser);
|
||||
return TabParent::GetFrom(browser);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1189,7 +1189,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
|
||||
if (isInContentProcess) {
|
||||
// Just return directly without the following check in content process.
|
||||
return static_cast<TabParent*>(browser);
|
||||
return TabParent::GetFrom(browser);
|
||||
}
|
||||
|
||||
if (!browser) {
|
||||
|
@ -1218,7 +1218,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
|
||||
parent->AsContentParent()->MaybeTakeCPUWakeLock(aFrameElement);
|
||||
|
||||
return static_cast<TabParent*>(browser);
|
||||
return TabParent::GetFrom(browser);
|
||||
}
|
||||
|
||||
/*static*/ ContentBridgeParent*
|
||||
|
|
|
@ -292,7 +292,7 @@ ContentProcessManager::GetTabParentByProcessAndTabId(const ContentParentId& aChi
|
|||
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||
iter->second.mCp->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); i++) {
|
||||
nsRefPtr<TabParent> tab = static_cast<TabParent*>(browsers[i]);
|
||||
nsRefPtr<TabParent> tab = TabParent::GetFrom(browsers[i]);
|
||||
if (tab->GetTabId() == aChildTabId) {
|
||||
return tab.forget();
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ FilePickerParent::FileSizeAndDateRunnable::Destroy()
|
|||
void
|
||||
FilePickerParent::SendFiles(const nsCOMArray<nsIDOMFile>& aDomfiles)
|
||||
{
|
||||
nsIContentParent* parent = static_cast<TabParent*>(Manager())->Manager();
|
||||
nsIContentParent* parent = TabParent::GetFrom(Manager())->Manager();
|
||||
InfallibleTArray<PBlobParent*> files;
|
||||
|
||||
for (unsigned i = 0; i < aDomfiles.Length(); i++) {
|
||||
|
@ -183,7 +183,7 @@ FilePickerParent::CreateFilePicker()
|
|||
return false;
|
||||
}
|
||||
|
||||
Element* element = static_cast<TabParent*>(Manager())->GetOwnerElement();
|
||||
Element* element = TabParent::GetFrom(Manager())->GetOwnerElement();
|
||||
if (!element) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
|
|||
using class mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
|
||||
using struct gfxSize from "gfxPoint.h";
|
||||
using CSSRect from "Units.h";
|
||||
using LayoutDeviceIntRect from "Units.h";
|
||||
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
|
||||
using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
|
||||
using struct mozilla::layers::ZoomConstraints from "FrameMetrics.h";
|
||||
|
@ -206,9 +207,9 @@ parent:
|
|||
* caretRect The rect of IME caret
|
||||
*/
|
||||
prio(urgent) async NotifyIMESelectedCompositionRect(uint32_t offset,
|
||||
nsIntRect[] rect,
|
||||
LayoutDeviceIntRect[] rect,
|
||||
uint32_t caretOffset,
|
||||
nsIntRect caretRect);
|
||||
LayoutDeviceIntRect caretRect);
|
||||
|
||||
/**
|
||||
* Notifies chrome that there has been a change in selection
|
||||
|
@ -245,7 +246,7 @@ parent:
|
|||
*
|
||||
* rect Rect of current focused editor
|
||||
*/
|
||||
prio(urgent) async NotifyIMEEditorRect(nsIntRect rect);
|
||||
prio(urgent) async NotifyIMEEditorRect(LayoutDeviceIntRect rect);
|
||||
|
||||
/**
|
||||
* Notifies chrome to position change
|
||||
|
@ -253,9 +254,9 @@ parent:
|
|||
* editorRect Rect of current focused editor
|
||||
* compositionRects Rects of current composition string
|
||||
*/
|
||||
prio(urgent) async NotifyIMEPositionChange(nsIntRect editorRect,
|
||||
nsIntRect[] compositionRects,
|
||||
nsIntRect caretRect);
|
||||
prio(urgent) async NotifyIMEPositionChange(LayoutDeviceIntRect editorRect,
|
||||
LayoutDeviceIntRect[] compositionRects,
|
||||
LayoutDeviceIntRect caretRect);
|
||||
|
||||
/**
|
||||
* Instructs chrome to end any pending composition
|
||||
|
|
|
@ -619,7 +619,7 @@ HangMonitoredProcess::GetScriptBrowser(nsIDOMElement** aBrowser)
|
|||
nsTArray<PBrowserParent*> tabs;
|
||||
mContentParent->ManagedPBrowserParent(tabs);
|
||||
for (size_t i = 0; i < tabs.Length(); i++) {
|
||||
TabParent* tp = static_cast<TabParent*>(tabs[i]);
|
||||
TabParent* tp = TabParent::GetFrom(tabs[i]);
|
||||
if (tp->GetTabId() == tabId) {
|
||||
nsCOMPtr<nsIDOMElement> node = do_QueryInterface(tp->GetOwnerElement());
|
||||
node.forget(aBrowser);
|
||||
|
@ -765,14 +765,13 @@ HangMonitoredProcess::IsReportForBrowser(nsIFrameLoader* aFrameLoader, bool* aRe
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITabParent> itp;
|
||||
aFrameLoader->GetTabParent(getter_AddRefs(itp));
|
||||
if (!itp) {
|
||||
TabParent* tp = TabParent::GetFrom(aFrameLoader);
|
||||
if (!tp) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aResult = mContentParent == static_cast<TabParent*>(itp.get())->Manager();
|
||||
*aResult = mContentParent == tp->Manager();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -813,12 +813,11 @@ ParticularProcessPriorityManager::OnRemoteBrowserFrameShown(nsISupports* aSubjec
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITabParent> tp;
|
||||
fl->GetTabParent(getter_AddRefs(tp));
|
||||
TabParent* tp = TabParent::GetFrom(fl);
|
||||
NS_ENSURE_TRUE_VOID(tp);
|
||||
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
if (static_cast<TabParent*>(tp.get())->Manager() != mContentParent) {
|
||||
if (tp->Manager() != mContentParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -832,7 +831,7 @@ ParticularProcessPriorityManager::OnTabParentDestroyed(nsISupports* aSubject)
|
|||
NS_ENSURE_TRUE_VOID(tp);
|
||||
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
if (static_cast<TabParent*>(tp.get())->Manager() != mContentParent) {
|
||||
if (TabParent::GetFrom(tp)->Manager() != mContentParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -845,14 +844,13 @@ ParticularProcessPriorityManager::OnFrameloaderVisibleChanged(nsISupports* aSubj
|
|||
nsCOMPtr<nsIFrameLoader> fl = do_QueryInterface(aSubject);
|
||||
NS_ENSURE_TRUE_VOID(fl);
|
||||
|
||||
nsCOMPtr<nsITabParent> tp;
|
||||
fl->GetTabParent(getter_AddRefs(tp));
|
||||
TabParent* tp = TabParent::GetFrom(fl);
|
||||
if (!tp) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
if (static_cast<TabParent*>(tp.get())->Manager() != mContentParent) {
|
||||
if (tp->Manager() != mContentParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -932,7 +930,7 @@ ParticularProcessPriorityManager::HasAppType(const char* aAppType)
|
|||
mContentParent->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); i++) {
|
||||
nsAutoString appType;
|
||||
static_cast<TabParent*>(browsers[i])->GetAppType(appType);
|
||||
TabParent::GetFrom(browsers[i])->GetAppType(appType);
|
||||
if (appType.EqualsASCII(aAppType)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -947,7 +945,7 @@ ParticularProcessPriorityManager::IsExpectingSystemMessage()
|
|||
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||
mContentParent->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); i++) {
|
||||
TabParent* tp = static_cast<TabParent*>(browsers[i]);
|
||||
TabParent* tp = TabParent::GetFrom(browsers[i]);
|
||||
nsCOMPtr<nsIMozBrowserFrame> bf = do_QueryInterface(tp->GetOwnerElement());
|
||||
if (!bf) {
|
||||
continue;
|
||||
|
@ -979,7 +977,7 @@ ParticularProcessPriorityManager::ComputePriority()
|
|||
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||
mContentParent->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); i++) {
|
||||
if (static_cast<TabParent*>(browsers[i])->IsVisible()) {
|
||||
if (TabParent::GetFrom(browsers[i])->IsVisible()) {
|
||||
isVisible = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -746,16 +746,28 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
StaticRefPtr<TabChild> sPreallocatedTab;
|
||||
|
||||
/*static*/
|
||||
std::map<TabId, nsRefPtr<TabChild>>&
|
||||
TabChild::NestedTabChildMap()
|
||||
NestedTabChildMap()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
static std::map<TabId, nsRefPtr<TabChild>> sNestedTabChildMap;
|
||||
return sNestedTabChildMap;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
already_AddRefed<TabChild>
|
||||
TabChild::FindTabChild(const TabId& aTabId)
|
||||
{
|
||||
auto iter = NestedTabChildMap().find(aTabId);
|
||||
if (iter == NestedTabChildMap().end()) {
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<TabChild> tabChild = iter->second;
|
||||
return tabChild.forget();
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
TabChild::PreloadSlowThings()
|
||||
|
@ -3330,6 +3342,15 @@ TabChild::GetTabId(uint64_t* aId)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::SetTabId(const TabId& aTabId)
|
||||
{
|
||||
MOZ_ASSERT(mUniqueId == 0);
|
||||
|
||||
mUniqueId = aTabId;
|
||||
NestedTabChildMap()[mUniqueId] = this;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::DoSendBlockingMessage(JSContext* aCx,
|
||||
const nsAString& aMessage,
|
||||
|
|
|
@ -254,7 +254,11 @@ class TabChild MOZ_FINAL : public TabChildBase,
|
|||
typedef mozilla::layers::ActiveElementManager ActiveElementManager;
|
||||
|
||||
public:
|
||||
static std::map<TabId, nsRefPtr<TabChild>>& NestedTabChildMap();
|
||||
/**
|
||||
* Find TabChild of aTabId in the same content process of the
|
||||
* caller.
|
||||
*/
|
||||
static already_AddRefed<TabChild> FindTabChild(const TabId& aTabId);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -609,13 +613,7 @@ private:
|
|||
// Get the pres shell resolution of the document in this tab.
|
||||
float GetPresShellResolution() const;
|
||||
|
||||
void SetTabId(const TabId& aTabId)
|
||||
{
|
||||
MOZ_ASSERT(mUniqueId == 0);
|
||||
|
||||
mUniqueId = aTabId;
|
||||
NestedTabChildMap()[mUniqueId] = this;
|
||||
}
|
||||
void SetTabId(const TabId& aTabId);
|
||||
|
||||
class CachedFileDescriptorInfo;
|
||||
class CachedFileDescriptorCallbackRunnable;
|
||||
|
|
|
@ -257,7 +257,7 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
|||
|
||||
TabContext *context;
|
||||
if (ipcContext.opener().type() == PBrowserOrId::TPBrowserParent) {
|
||||
context = static_cast<TabParent*>(ipcContext.opener().get_PBrowserParent());
|
||||
context = TabParent::GetFrom(ipcContext.opener().get_PBrowserParent());
|
||||
if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) {
|
||||
// If the TabParent corresponds to a browser element, then it can only
|
||||
// open other browser elements, for security reasons. We should have
|
||||
|
|
|
@ -549,7 +549,7 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
|||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
TabParent* newTab = static_cast<TabParent*>(aNewTab);
|
||||
TabParent* newTab = TabParent::GetFrom(aNewTab);
|
||||
|
||||
nsCOMPtr<nsIContent> frame(do_QueryInterface(mFrameElement));
|
||||
|
||||
|
@ -653,7 +653,7 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
|||
nsCOMPtr<nsITabParent> newRemoteTab = newDocShell->GetOpenedRemote();
|
||||
NS_ENSURE_TRUE(newRemoteTab, false);
|
||||
|
||||
MOZ_ASSERT(static_cast<TabParent*>(newRemoteTab.get()) == newTab);
|
||||
MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab);
|
||||
|
||||
aFrameScripts->SwapElements(newTab->mDelayedFrameScripts);
|
||||
return true;
|
||||
|
@ -1612,9 +1612,9 @@ TabParent::RecvNotifyIMETextChange(const uint32_t& aStart,
|
|||
bool
|
||||
TabParent::RecvNotifyIMESelectedCompositionRect(
|
||||
const uint32_t& aOffset,
|
||||
InfallibleTArray<nsIntRect>&& aRects,
|
||||
InfallibleTArray<LayoutDeviceIntRect>&& aRects,
|
||||
const uint32_t& aCaretOffset,
|
||||
const nsIntRect& aCaretRect)
|
||||
const LayoutDeviceIntRect& aCaretRect)
|
||||
{
|
||||
// add rect to cache for another query
|
||||
mIMECompositionRectOffset = aOffset;
|
||||
|
@ -1684,7 +1684,7 @@ TabParent::RecvNotifyIMEMouseButtonEvent(
|
|||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvNotifyIMEEditorRect(const nsIntRect& aRect)
|
||||
TabParent::RecvNotifyIMEEditorRect(const LayoutDeviceIntRect& aRect)
|
||||
{
|
||||
mIMEEditorRect = aRect;
|
||||
return true;
|
||||
|
@ -1692,9 +1692,9 @@ TabParent::RecvNotifyIMEEditorRect(const nsIntRect& aRect)
|
|||
|
||||
bool
|
||||
TabParent::RecvNotifyIMEPositionChange(
|
||||
const nsIntRect& aEditorRect,
|
||||
InfallibleTArray<nsIntRect>&& aCompositionRects,
|
||||
const nsIntRect& aCaretRect)
|
||||
const LayoutDeviceIntRect& aEditorRect,
|
||||
InfallibleTArray<LayoutDeviceIntRect>&& aCompositionRects,
|
||||
const LayoutDeviceIntRect& aCaretRect)
|
||||
{
|
||||
mIMEEditorRect = aEditorRect;
|
||||
mIMECompositionRects = aCompositionRects;
|
||||
|
@ -1929,7 +1929,8 @@ TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
|
|||
aEvent.mReply.mRect.Union(mIMECompositionRects[i]);
|
||||
}
|
||||
aEvent.mReply.mOffset = aEvent.mInput.mOffset;
|
||||
aEvent.mReply.mRect = aEvent.mReply.mRect - GetChildProcessOffset();
|
||||
aEvent.mReply.mRect =
|
||||
aEvent.mReply.mRect - LayoutDevicePixel::FromUntyped(GetChildProcessOffset());
|
||||
aEvent.mSucceeded = true;
|
||||
}
|
||||
break;
|
||||
|
@ -1940,13 +1941,15 @@ TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
|
|||
}
|
||||
|
||||
aEvent.mReply.mOffset = mIMECaretOffset;
|
||||
aEvent.mReply.mRect = mIMECaretRect - GetChildProcessOffset();
|
||||
aEvent.mReply.mRect =
|
||||
mIMECaretRect - LayoutDevicePixel::FromUntyped(GetChildProcessOffset());
|
||||
aEvent.mSucceeded = true;
|
||||
}
|
||||
break;
|
||||
case NS_QUERY_EDITOR_RECT:
|
||||
{
|
||||
aEvent.mReply.mRect = mIMEEditorRect - GetChildProcessOffset();
|
||||
aEvent.mReply.mRect =
|
||||
mIMEEditorRect - LayoutDevicePixel::FromUntyped(GetChildProcessOffset());
|
||||
aEvent.mSucceeded = true;
|
||||
}
|
||||
break;
|
||||
|
@ -2024,6 +2027,26 @@ TabParent::GetFrom(nsFrameLoader* aFrameLoader)
|
|||
return static_cast<TabParent*>(remoteBrowser);
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
TabParent::GetFrom(nsIFrameLoader* aFrameLoader)
|
||||
{
|
||||
if (!aFrameLoader)
|
||||
return nullptr;
|
||||
return GetFrom(static_cast<nsFrameLoader*>(aFrameLoader));
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
TabParent::GetFrom(nsITabParent* aTabParent)
|
||||
{
|
||||
return static_cast<TabParent*>(aTabParent);
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
TabParent::GetFrom(PBrowserParent* aTabParent)
|
||||
{
|
||||
return static_cast<TabParent*>(aTabParent);
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
TabParent::GetFrom(nsIContent* aContent)
|
||||
{
|
||||
|
@ -2422,7 +2445,7 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
|
|||
bool* aOutWindowOpened)
|
||||
{
|
||||
BrowserElementParent::OpenWindowResult opened =
|
||||
BrowserElementParent::OpenWindowOOP(static_cast<TabParent*>(aOpener),
|
||||
BrowserElementParent::OpenWindowOOP(TabParent::GetFrom(aOpener),
|
||||
this, aURL, aName, aFeatures);
|
||||
*aOutWindowOpened = (opened != BrowserElementParent::OPEN_WINDOW_CANCELLED);
|
||||
return true;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "js/TypeDecls.h"
|
||||
|
||||
class nsFrameLoader;
|
||||
class nsIFrameLoader;
|
||||
class nsIContent;
|
||||
class nsIPrincipal;
|
||||
class nsIURI;
|
||||
|
@ -172,9 +173,9 @@ public:
|
|||
const bool& aCausedByComposition) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMESelectedCompositionRect(
|
||||
const uint32_t& aOffset,
|
||||
InfallibleTArray<nsIntRect>&& aRects,
|
||||
InfallibleTArray<LayoutDeviceIntRect>&& aRects,
|
||||
const uint32_t& aCaretOffset,
|
||||
const nsIntRect& aCaretRect) MOZ_OVERRIDE;
|
||||
const LayoutDeviceIntRect& aCaretRect) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMESelection(const uint32_t& aSeqno,
|
||||
const uint32_t& aAnchor,
|
||||
const uint32_t& aFocus,
|
||||
|
@ -183,11 +184,11 @@ public:
|
|||
virtual bool RecvNotifyIMETextHint(const nsString& aText) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
|
||||
bool* aConsumedByIME) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMEEditorRect(const nsIntRect& aRect) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMEEditorRect(const LayoutDeviceIntRect& aRect) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMEPositionChange(
|
||||
const nsIntRect& aEditoRect,
|
||||
InfallibleTArray<nsIntRect>&& aCompositionRects,
|
||||
const nsIntRect& aCaretRect) MOZ_OVERRIDE;
|
||||
const LayoutDeviceIntRect& aEditorRect,
|
||||
InfallibleTArray<LayoutDeviceIntRect>&& aCompositionRects,
|
||||
const LayoutDeviceIntRect& aCaretRect) MOZ_OVERRIDE;
|
||||
virtual bool RecvEndIMEComposition(const bool& aCancel,
|
||||
nsString* aComposition) MOZ_OVERRIDE;
|
||||
virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
|
||||
|
@ -328,6 +329,9 @@ public:
|
|||
bool SendSelectionEvent(mozilla::WidgetSelectionEvent& event);
|
||||
|
||||
static TabParent* GetFrom(nsFrameLoader* aFrameLoader);
|
||||
static TabParent* GetFrom(nsIFrameLoader* aFrameLoader);
|
||||
static TabParent* GetFrom(nsITabParent* aTabParent);
|
||||
static TabParent* GetFrom(PBrowserParent* aTabParent);
|
||||
static TabParent* GetFrom(nsIContent* aContent);
|
||||
static TabId GetTabIdFrom(nsIDocShell* docshell);
|
||||
|
||||
|
@ -414,10 +418,10 @@ protected:
|
|||
uint32_t mIMESeqno;
|
||||
|
||||
uint32_t mIMECompositionRectOffset;
|
||||
InfallibleTArray<nsIntRect> mIMECompositionRects;
|
||||
InfallibleTArray<LayoutDeviceIntRect> mIMECompositionRects;
|
||||
uint32_t mIMECaretOffset;
|
||||
nsIntRect mIMECaretRect;
|
||||
nsIntRect mIMEEditorRect;
|
||||
LayoutDeviceIntRect mIMECaretRect;
|
||||
LayoutDeviceIntRect mIMEEditorRect;
|
||||
|
||||
// The number of event series we're currently capturing.
|
||||
int32_t mEventCaptureDepth;
|
||||
|
|
|
@ -87,7 +87,7 @@ nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
|
|||
return false;
|
||||
}
|
||||
|
||||
auto opener = static_cast<TabParent*>(popupContext.opener().get_PBrowserParent());
|
||||
auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
|
||||
if (!opener) {
|
||||
ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent.");
|
||||
return false;
|
||||
|
@ -140,7 +140,7 @@ nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
|
|||
bool
|
||||
nsIContentParent::DeallocPBrowserParent(PBrowserParent* aFrame)
|
||||
{
|
||||
TabParent* parent = static_cast<TabParent*>(aFrame);
|
||||
TabParent* parent = TabParent::GetFrom(aFrame);
|
||||
NS_RELEASE(parent);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@ scriptFromStringBlocked = An attempt to call JavaScript from a string (by callin
|
|||
# LOCALIZATION NOTE (hostNameMightBeKeyword):
|
||||
# %1$S is the hostname in question and %2$S is the keyword
|
||||
hostNameMightBeKeyword = Interpreting %1$S as a hostname, not a keyword. If you intended this to be a keyword, use '%2$S' (wrapped in single quotes).
|
||||
# LOCALIZATION NOTE (ignoringReportOnlyDirective):
|
||||
# %1$S is the directive that is ignore in report-only mode.
|
||||
ignoringReportOnlyDirective = Ignoring sandbox directive when delivered in a report-only policy '%1$S'.
|
||||
# LOCALIZATION NOTE (notSupportingDirective):
|
||||
# directive is not supported (e.g. 'reflected-xss')
|
||||
notSupportingDirective = Not supporting directive '%1$S'. Directive and values will be ignored.
|
||||
|
@ -70,3 +73,6 @@ couldntParsePort = Couldn't parse port in %1$S
|
|||
# LOCALIZATION NOTE (duplicateDirective):
|
||||
# %1$S is the name of the duplicate directive
|
||||
duplicateDirective = Duplicate %1$S directives detected. All but the first instance will be ignored.
|
||||
# LOCALIZATION NOTE (couldntParseInvalidSandboxFlag):
|
||||
# %1$S is the option that could not be understood
|
||||
couldntParseInvalidSandboxFlag = Couldn't parse invalid sandbox flag %1$S
|
||||
|
|
|
@ -24,7 +24,8 @@ class SharedDecoderManager;
|
|||
|
||||
struct WaitForDataRejectValue {
|
||||
enum Reason {
|
||||
SHUTDOWN
|
||||
SHUTDOWN,
|
||||
CANCELED
|
||||
};
|
||||
|
||||
WaitForDataRejectValue(MediaData::Type aType, Reason aReason)
|
||||
|
|
|
@ -657,42 +657,6 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::DecodeVideo()
|
||||
{
|
||||
int64_t currentTime = 0;
|
||||
bool skipToNextKeyFrame = false;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
|
||||
|
||||
if (mState != DECODER_STATE_DECODING &&
|
||||
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
mState != DECODER_STATE_BUFFERING &&
|
||||
mState != DECODER_STATE_SEEKING) {
|
||||
mVideoRequestStatus = RequestStatus::Idle;
|
||||
DispatchDecodeTasksIfNeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
skipToNextKeyFrame = NeedToSkipToNextKeyframe();
|
||||
currentTime = mState == DECODER_STATE_SEEKING ? 0 : GetMediaTime();
|
||||
|
||||
// Time the video decode, so that if it's slow, we can increase our low
|
||||
// audio threshold to reduce the chance of an audio underrun while we're
|
||||
// waiting for a video decode to complete.
|
||||
mVideoDecodeStartTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
SAMPLE_LOG("DecodeVideo() queued=%i, decoder-queued=%o, skip=%i, time=%lld",
|
||||
VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame, currentTime);
|
||||
|
||||
mReader->RequestVideoData(skipToNextKeyFrame, currentTime)
|
||||
->Then(DecodeTaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnVideoDecoded,
|
||||
&MediaDecoderStateMachine::OnVideoNotDecoded);
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderStateMachine::NeedToDecodeAudio()
|
||||
{
|
||||
|
@ -711,32 +675,6 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
|
|||
(mState != DECODER_STATE_SEEKING || mDecodeToSeekTarget)));
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::DecodeAudio()
|
||||
{
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
|
||||
|
||||
if (mState != DECODER_STATE_DECODING &&
|
||||
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
mState != DECODER_STATE_BUFFERING &&
|
||||
mState != DECODER_STATE_SEEKING) {
|
||||
mAudioRequestStatus = RequestStatus::Idle;
|
||||
DispatchDecodeTasksIfNeeded();
|
||||
mon.NotifyAll();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SAMPLE_LOG("DecodeAudio() queued=%i, decoder-queued=%o",
|
||||
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
|
||||
|
||||
mReader->RequestAudioData()->Then(DecodeTaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnAudioDecoded,
|
||||
&MediaDecoderStateMachine::OnAudioNotDecoded);
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderStateMachine::IsAudioSeekComplete()
|
||||
{
|
||||
|
@ -1989,23 +1927,26 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
|
|||
SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%d",
|
||||
IsAudioDecoding(), mAudioRequestStatus);
|
||||
|
||||
if (mState >= DECODER_STATE_COMPLETED || mState == DECODER_STATE_DORMANT) {
|
||||
if (mState != DECODER_STATE_DECODING &&
|
||||
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
mState != DECODER_STATE_BUFFERING &&
|
||||
mState != DECODER_STATE_SEEKING) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState >= DECODER_STATE_DECODING_FIRSTFRAME);
|
||||
|
||||
if (IsAudioDecoding() && mAudioRequestStatus == RequestStatus::Idle && !mWaitingForDecoderSeek) {
|
||||
RefPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeAudio));
|
||||
nsresult rv = DecodeTaskQueue()->Dispatch(task);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mAudioRequestStatus = RequestStatus::Pending;
|
||||
} else {
|
||||
DECODER_WARN("Failed to dispatch task to decode audio");
|
||||
}
|
||||
if (!IsAudioDecoding() || mAudioRequestStatus != RequestStatus::Idle || mWaitingForDecoderSeek) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
|
||||
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
|
||||
|
||||
mAudioRequestStatus = RequestStatus::Pending;
|
||||
ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__, &MediaDecoderReader::RequestAudioData)
|
||||
->Then(DecodeTaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnAudioDecoded,
|
||||
&MediaDecoderStateMachine::OnAudioNotDecoded);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2034,23 +1975,36 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
|
|||
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
|
||||
"Should be on state machine or decode thread.");
|
||||
|
||||
if (mState >= DECODER_STATE_COMPLETED || mState == DECODER_STATE_DORMANT) {
|
||||
if (mState != DECODER_STATE_DECODING &&
|
||||
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
|
||||
mState != DECODER_STATE_BUFFERING &&
|
||||
mState != DECODER_STATE_SEEKING) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mState >= DECODER_STATE_DECODING_FIRSTFRAME);
|
||||
|
||||
if (IsVideoDecoding() && mVideoRequestStatus == RequestStatus::Idle && !mWaitingForDecoderSeek) {
|
||||
RefPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeVideo));
|
||||
nsresult rv = DecodeTaskQueue()->Dispatch(task);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mVideoRequestStatus = RequestStatus::Pending;
|
||||
} else {
|
||||
DECODER_WARN("Failed to dispatch task to decode video");
|
||||
}
|
||||
if (!IsVideoDecoding() || mVideoRequestStatus != RequestStatus::Idle || mWaitingForDecoderSeek) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool skipToNextKeyFrame = NeedToSkipToNextKeyframe();
|
||||
int64_t currentTime = mState == DECODER_STATE_SEEKING ? 0 : GetMediaTime();
|
||||
|
||||
// Time the video decode, so that if it's slow, we can increase our low
|
||||
// audio threshold to reduce the chance of an audio underrun while we're
|
||||
// waiting for a video decode to complete.
|
||||
mVideoDecodeStartTime = TimeStamp::Now();
|
||||
|
||||
SAMPLE_LOG("Queueing video task - queued=%i, decoder-queued=%o, skip=%i, time=%lld",
|
||||
VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
|
||||
currentTime);
|
||||
|
||||
mVideoRequestStatus = RequestStatus::Pending;
|
||||
ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
|
||||
&MediaDecoderReader::RequestVideoData, skipToNextKeyFrame, currentTime)
|
||||
->Then(DecodeTaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnVideoDecoded,
|
||||
&MediaDecoderStateMachine::OnVideoNotDecoded);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -422,7 +422,6 @@ public:
|
|||
|
||||
void OnWaitForDataRejected(WaitForDataRejectValue aRejection)
|
||||
{
|
||||
MOZ_ASSERT(aRejection.mReason == WaitForDataRejectValue::SHUTDOWN);
|
||||
if (RequestStatusRef(aRejection.mType) == RequestStatus::Waiting) {
|
||||
RequestStatusRef(aRejection.mType) = RequestStatus::Idle;
|
||||
}
|
||||
|
@ -489,16 +488,10 @@ protected:
|
|||
// decode more.
|
||||
bool NeedToDecodeAudio();
|
||||
|
||||
// Decodes some audio. This should be run on the decode task queue.
|
||||
void DecodeAudio();
|
||||
|
||||
// True if our buffers of decoded video are not full, and we should
|
||||
// decode more.
|
||||
bool NeedToDecodeVideo();
|
||||
|
||||
// Decodes some video. This should be run on the decode task queue.
|
||||
void DecodeVideo();
|
||||
|
||||
// Returns true if we've got less than aAudioUsecs microseconds of decoded
|
||||
// and playable data. The decoder monitor must be held.
|
||||
//
|
||||
|
|
|
@ -36,12 +36,18 @@ struct TrackInfo {
|
|||
|
||||
// Stores info relevant to presenting media frames.
|
||||
class VideoInfo {
|
||||
private:
|
||||
VideoInfo(int32_t aWidth, int32_t aHeight, bool aHasVideo)
|
||||
: mDisplay(aWidth, aHeight)
|
||||
, mStereoMode(StereoMode::MONO)
|
||||
, mHasVideo(aHasVideo)
|
||||
, mIsHardwareAccelerated(false)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
VideoInfo()
|
||||
: mDisplay(0,0)
|
||||
, mStereoMode(StereoMode::MONO)
|
||||
, mHasVideo(false)
|
||||
, mIsHardwareAccelerated(false)
|
||||
: VideoInfo(0, 0, false)
|
||||
{
|
||||
// TODO: TrackInfo should be initialized by its specific codec decoder.
|
||||
// This following call should be removed once we have that implemented.
|
||||
|
@ -49,6 +55,11 @@ public:
|
|||
EmptyString(), EmptyString(), true);
|
||||
}
|
||||
|
||||
VideoInfo(int32_t aWidth, int32_t aHeight)
|
||||
: VideoInfo(aWidth, aHeight, true)
|
||||
{
|
||||
}
|
||||
|
||||
// Size in pixels at which the video is rendered. This is after it has
|
||||
// been scaled by its aspect ratio.
|
||||
nsIntSize mDisplay;
|
||||
|
|
|
@ -94,7 +94,7 @@ public:
|
|||
void Disconnect()
|
||||
{
|
||||
AssertOnDispatchThread();
|
||||
MOZ_RELEASE_ASSERT(!mComplete);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mComplete);
|
||||
mDisconnected = true;
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ public:
|
|||
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveConsumer);
|
||||
mHaveConsumer = true;
|
||||
nsRefPtr<ThenValueBase> thenValue = new ThenValue<TargetType, ThisType, ResolveMethodType,
|
||||
RejectMethodType>(aResponseTarget, aThisVal,
|
||||
|
@ -332,7 +332,7 @@ public:
|
|||
void ChainTo(already_AddRefed<MediaPromise> aChainedPromise, const char* aCallSite)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveConsumer);
|
||||
mHaveConsumer = true;
|
||||
nsRefPtr<MediaPromise> chainedPromise = aChainedPromise;
|
||||
PROMISE_LOG("%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
|
||||
|
@ -507,13 +507,13 @@ public:
|
|||
|
||||
void Begin(already_AddRefed<typename PromiseType::Consumer> aConsumer)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!Exists());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!Exists());
|
||||
mConsumer = aConsumer;
|
||||
}
|
||||
|
||||
void Complete()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(Exists());
|
||||
MOZ_DIAGNOSTIC_ASSERT(Exists());
|
||||
mConsumer = nullptr;
|
||||
}
|
||||
|
||||
|
@ -537,6 +537,112 @@ private:
|
|||
nsRefPtr<typename PromiseType::Consumer> mConsumer;
|
||||
};
|
||||
|
||||
// Proxy Media Calls.
|
||||
//
|
||||
// This machinery allows callers to schedule a promise-returning method to be
|
||||
// invoked asynchronously on a given thread, while at the same time receiving
|
||||
// a promise upon which to invoke Then() immediately. ProxyMediaCall dispatches
|
||||
// a task to invoke the method on the proper thread and also chain the resulting
|
||||
// promise to the one that the caller received, so that resolve/reject values
|
||||
// are forwarded through.
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename PromiseType>
|
||||
class MethodCallBase
|
||||
{
|
||||
public:
|
||||
MethodCallBase() { MOZ_COUNT_CTOR(MethodCallBase); }
|
||||
virtual nsRefPtr<PromiseType> Invoke() = 0;
|
||||
virtual ~MethodCallBase() { MOZ_COUNT_DTOR(MethodCallBase); };
|
||||
};
|
||||
|
||||
template<typename PromiseType, typename ThisType>
|
||||
class MethodCallWithNoArgs : public MethodCallBase<PromiseType>
|
||||
{
|
||||
public:
|
||||
typedef nsRefPtr<PromiseType>(ThisType::*Type)();
|
||||
MethodCallWithNoArgs(ThisType* aThisVal, Type aMethod)
|
||||
: mThisVal(aThisVal), mMethod(aMethod) {}
|
||||
nsRefPtr<PromiseType> Invoke() MOZ_OVERRIDE { return ((*mThisVal).*mMethod)(); }
|
||||
protected:
|
||||
nsRefPtr<ThisType> mThisVal;
|
||||
Type mMethod;
|
||||
};
|
||||
|
||||
// NB: MethodCallWithOneArg definition should go here, if/when it is needed.
|
||||
|
||||
template<typename PromiseType, typename ThisType, typename Arg1Type, typename Arg2Type>
|
||||
class MethodCallWithTwoArgs : public MethodCallBase<PromiseType>
|
||||
{
|
||||
public:
|
||||
typedef nsRefPtr<PromiseType>(ThisType::*Type)(Arg1Type, Arg2Type);
|
||||
MethodCallWithTwoArgs(ThisType* aThisVal, Type aMethod, Arg1Type aArg1, Arg2Type aArg2)
|
||||
: mThisVal(aThisVal), mMethod(aMethod), mArg1(aArg1), mArg2(aArg2) {}
|
||||
nsRefPtr<PromiseType> Invoke() MOZ_OVERRIDE { return ((*mThisVal).*mMethod)(mArg1, mArg2); }
|
||||
protected:
|
||||
nsRefPtr<ThisType> mThisVal;
|
||||
Type mMethod;
|
||||
Arg1Type mArg1;
|
||||
Arg2Type mArg2;
|
||||
};
|
||||
|
||||
template<typename PromiseType>
|
||||
class ProxyRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ProxyRunnable(PromiseType* aProxyPromise, MethodCallBase<PromiseType>* aMethodCall)
|
||||
: mProxyPromise(aProxyPromise), mMethodCall(aMethodCall) {}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
nsRefPtr<PromiseType> p = mMethodCall->Invoke();
|
||||
mMethodCall = nullptr;
|
||||
p->ChainTo(mProxyPromise.forget(), "<Proxy Promise>");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<PromiseType> mProxyPromise;
|
||||
nsAutoPtr<MethodCallBase<PromiseType>> mMethodCall;
|
||||
};
|
||||
|
||||
template<typename PromiseType, typename TargetType>
|
||||
static nsRefPtr<PromiseType>
|
||||
ProxyInternal(TargetType* aTarget, MethodCallBase<PromiseType>* aMethodCall, const char* aCallerName)
|
||||
{
|
||||
nsRefPtr<PromiseType> p = new PromiseType(aCallerName);
|
||||
nsRefPtr<ProxyRunnable<PromiseType>> r = new ProxyRunnable<PromiseType>(p, aMethodCall);
|
||||
nsresult rv = detail::DispatchMediaPromiseRunnable(aTarget, r);
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename PromiseType, typename TargetType, typename ThisType>
|
||||
static nsRefPtr<PromiseType>
|
||||
ProxyMediaCall(TargetType* aTarget, ThisType* aThisVal, const char* aCallerName,
|
||||
nsRefPtr<PromiseType>(ThisType::*aMethod)())
|
||||
{
|
||||
typedef detail::MethodCallWithNoArgs<PromiseType, ThisType> MethodCallType;
|
||||
MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod);
|
||||
return detail::ProxyInternal(aTarget, methodCall, aCallerName);
|
||||
}
|
||||
|
||||
// NB: One-arg overload should go here, if/when it is needed.
|
||||
|
||||
template<typename PromiseType, typename TargetType, typename ThisType,
|
||||
typename Arg1Type, typename Arg2Type>
|
||||
static nsRefPtr<PromiseType>
|
||||
ProxyMediaCall(TargetType* aTarget, ThisType* aThisVal, const char* aCallerName,
|
||||
nsRefPtr<PromiseType>(ThisType::*aMethod)(Arg1Type, Arg2Type), Arg1Type aArg1, Arg2Type aArg2)
|
||||
{
|
||||
typedef detail::MethodCallWithTwoArgs<PromiseType, ThisType, Arg1Type, Arg2Type> MethodCallType;
|
||||
MethodCallType* methodCall = new MethodCallType(aThisVal, aMethod, aArg1, aArg2);
|
||||
return detail::ProxyInternal(aTarget, methodCall, aCallerName);
|
||||
}
|
||||
|
||||
#undef PROMISE_LOG
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -107,11 +107,12 @@ MediaKeySystemAccess::IsKeySystemSupported(const nsAString& aKeySystem)
|
|||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (aKeySystem.EqualsLiteral("com.adobe.access") &&
|
||||
if ((aKeySystem.EqualsLiteral("com.adobe.access") ||
|
||||
aKeySystem.EqualsLiteral("com.adobe.primetime")) &&
|
||||
Preferences::GetBool("media.eme.adobe-access.enabled", false) &&
|
||||
IsVistaOrLater() && // Win Vista and later only.
|
||||
HaveGMPFor(mps,
|
||||
NS_LITERAL_CSTRING("com.adobe.access"),
|
||||
NS_ConvertUTF16toUTF8(aKeySystem),
|
||||
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR))) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -212,6 +212,12 @@ IsGonkMP4DecoderAvailable()
|
|||
return Preferences::GetBool("media.fragmented-mp4.gonk.enabled", false);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsGMPDecoderAvailable()
|
||||
{
|
||||
return Preferences::GetBool("media.fragmented-mp4.gmp.enabled", false);
|
||||
}
|
||||
|
||||
static bool
|
||||
HavePlatformMPEGDecoders()
|
||||
{
|
||||
|
@ -224,6 +230,7 @@ HavePlatformMPEGDecoders()
|
|||
IsFFmpegAvailable() ||
|
||||
IsAppleAvailable() ||
|
||||
IsGonkMP4DecoderAvailable() ||
|
||||
IsGMPDecoderAvailable() ||
|
||||
// TODO: Other platforms...
|
||||
false;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidDecoderModule.h"
|
||||
#endif
|
||||
#include "GMPDecoderModule.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#ifdef MOZ_EME
|
||||
|
@ -40,6 +41,7 @@ bool PlatformDecoderModule::sFFmpegDecoderEnabled = false;
|
|||
bool PlatformDecoderModule::sGonkDecoderEnabled = false;
|
||||
bool PlatformDecoderModule::sAndroidMCDecoderEnabled = false;
|
||||
bool PlatformDecoderModule::sAndroidMCDecoderPreferred = false;
|
||||
bool PlatformDecoderModule::sGMPDecoderEnabled = false;
|
||||
|
||||
/* static */
|
||||
void
|
||||
|
@ -68,6 +70,9 @@ PlatformDecoderModule::Init()
|
|||
"media.fragmented-mp4.android-media-codec.preferred", false);
|
||||
#endif
|
||||
|
||||
Preferences::AddBoolVarCache(&sGMPDecoderEnabled,
|
||||
"media.fragmented-mp4.gmp.enabled", false);
|
||||
|
||||
#ifdef XP_WIN
|
||||
WMFDecoderModule::Init();
|
||||
#endif
|
||||
|
@ -167,6 +172,10 @@ PlatformDecoderModule::CreatePDM()
|
|||
return m.forget();
|
||||
}
|
||||
#endif
|
||||
if (sGMPDecoderEnabled) {
|
||||
nsRefPtr<PlatformDecoderModule> m(new AVCCDecoderModule(new GMPDecoderModule()));
|
||||
return m.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,7 @@ protected:
|
|||
static bool sGonkDecoderEnabled;
|
||||
static bool sAndroidMCDecoderPreferred;
|
||||
static bool sAndroidMCDecoderEnabled;
|
||||
static bool sGMPDecoderEnabled;
|
||||
};
|
||||
|
||||
// A callback used by MediaDataDecoder to return output/errors to the
|
||||
|
|
|
@ -179,7 +179,7 @@ protected:
|
|||
return true;
|
||||
}
|
||||
|
||||
mGLContext = GLContextProvider::CreateHeadless();
|
||||
mGLContext = GLContextProvider::CreateHeadless(false);
|
||||
return mGLContext;
|
||||
}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче