Merge m-c to autoland, a=merge

This commit is contained in:
Wes Kocher 2016-07-13 14:12:44 -07:00
commit 85c761efaa
566 changed files with 35719 additions and 22832 deletions

View File

@ -659,9 +659,7 @@ TextAttrsMgr::FontWeightTextAttr::
// font->GetStyle()->weight will give the absolute weight requested of the
// font face. The gfxPangoFontGroup code uses the gfxFontEntry constructor
// which doesn't initialize the weight field.
#if defined(MOZ_WIDGET_QT)
useFontEntryWeight = false;
#elif defined(MOZ_WIDGET_GTK)
#if defined(MOZ_WIDGET_GTK)
useFontEntryWeight = gfxPlatformGtk::UseFcFontList();
#endif

View File

@ -11,6 +11,10 @@
#include "ARIAMap.h"
#include "nsCoreUtils.h"
#ifdef A11Y_LOG
#include "Logging.h"
#endif
namespace mozilla {
namespace a11y {
@ -76,6 +80,30 @@ Accessible::ScrollTo(uint32_t aHow) const
nsCoreUtils::ScrollTo(mDoc->PresShell(), mContent, aHow);
}
inline bool
Accessible::InsertAfter(Accessible* aNewChild, Accessible* aRefChild)
{
MOZ_ASSERT(aNewChild, "No new child to insert");
if (aRefChild && aRefChild->Parent() != this) {
#ifdef A11Y_LOG
logging::TreeInfo("broken accessible tree", 0,
"parent", this, "prev sibling parent",
aRefChild->Parent(), "child", aNewChild, nullptr);
if (logging::IsEnabled(logging::eVerbose)) {
logging::Tree("TREE", "Document tree", mDoc);
logging::DOMTree("TREE", "DOM document tree", mDoc);
}
#endif
MOZ_ASSERT_UNREACHABLE("Broken accessible tree");
mDoc->UnbindFromDocument(aNewChild);
return false;
}
return InsertChildAt(aRefChild ? aRefChild->IndexInParent() + 1 : 0,
aNewChild);
}
} // namespace a11y
} // namespace mozilla

View File

@ -18,7 +18,6 @@
#include "nsTextEquivUtils.h"
#include "DocAccessibleChild.h"
#include "EventTree.h"
#include "Logging.h"
#include "Relation.h"
#include "Role.h"
#include "RootAccessible.h"

View File

@ -393,12 +393,12 @@ public:
{ return InsertChildAt(mChildren.Length(), aChild); }
virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild);
bool InsertAfter(Accessible* aNewChild, Accessible* aRefChild)
{
MOZ_ASSERT(aNewChild, "No new child to insert");
return InsertChildAt(aRefChild ? aRefChild->IndexInParent() + 1 : 0,
aNewChild);
}
/**
* Inserts a child after given sibling. If the child cannot be inserted,
* then the child is unbound from the document, and false is returned. Make
* sure to null out any references on the child object as it may be destroyed.
*/
bool InsertAfter(Accessible* aNewChild, Accessible* aRefChild);
virtual bool RemoveChild(Accessible* aChild);

View File

@ -1681,6 +1681,12 @@ public:
*/
bool Next();
void Rejected()
{
mChild = nullptr;
mChildBefore = nullptr;
}
private:
Accessible* mChild;
Accessible* mChildBefore;
@ -1815,6 +1821,7 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
}
MOZ_ASSERT_UNREACHABLE("accessible was rejected");
iter.Rejected();
} while (iter.Next());
mt.Done();
@ -1852,7 +1859,9 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, nsIContent* aNode)
if (child) {
TreeMutation mt(aContainer);
aContainer->InsertAfter(child, walker.Prev());
if (!aContainer->InsertAfter(child, walker.Prev())) {
return;
}
mt.AfterInsertion(child);
mt.Done();

View File

@ -98,10 +98,10 @@ xpcAccessibleSelectable::Intl()
return static_cast<xpcAccessibleGeneric*>(this)->mIntl.AsAccessible();
}
inline Accessible*
inline AccessibleOrProxy
xpcAccessibleValue::Intl()
{
return static_cast<xpcAccessibleGeneric*>(this)->mIntl.AsAccessible();
return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
}
} // namespace a11y

View File

@ -16,10 +16,19 @@ xpcAccessibleValue::GetMaximumValue(double* aValue)
NS_ENSURE_ARG_POINTER(aValue);
*aValue = 0;
if (Intl()->IsDefunct())
if (Intl().IsNull())
return NS_ERROR_FAILURE;
double value = Intl()->MaxValue();
if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
return NS_ERROR_FAILURE;
double value;
if (Intl().IsAccessible()) {
value = Intl().AsAccessible()->MaxValue();
} else {
value = Intl().AsProxy()->MaxValue();
}
if (!IsNaN(value))
*aValue = value;
@ -32,10 +41,19 @@ xpcAccessibleValue::GetMinimumValue(double* aValue)
NS_ENSURE_ARG_POINTER(aValue);
*aValue = 0;
if (Intl()->IsDefunct())
if (Intl().IsNull())
return NS_ERROR_FAILURE;
double value = Intl()->MinValue();
if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
return NS_ERROR_FAILURE;
double value;
if (Intl().IsAccessible()) {
value = Intl().AsAccessible()->MinValue();
} else {
value = Intl().AsProxy()->MinValue();
}
if (!IsNaN(value))
*aValue = value;
@ -48,10 +66,19 @@ xpcAccessibleValue::GetCurrentValue(double* aValue)
NS_ENSURE_ARG_POINTER(aValue);
*aValue = 0;
if (Intl()->IsDefunct())
if (Intl().IsNull())
return NS_ERROR_FAILURE;
double value = Intl()->CurValue();
if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
return NS_ERROR_FAILURE;
double value;
if (Intl().IsAccessible()) {
value = Intl().AsAccessible()->CurValue();
} else {
value = Intl().AsProxy()->MinValue();
}
if (!IsNaN(value))
*aValue = value;
@ -61,10 +88,18 @@ xpcAccessibleValue::GetCurrentValue(double* aValue)
NS_IMETHODIMP
xpcAccessibleValue::SetCurrentValue(double aValue)
{
if (Intl()->IsDefunct())
if (Intl().IsNull())
return NS_ERROR_FAILURE;
Intl()->SetCurValue(aValue);
if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
return NS_ERROR_FAILURE;
if (Intl().IsAccessible()) {
Intl().AsAccessible()->SetCurValue(aValue);
} else {
Intl().AsProxy()->SetCurValue(aValue);
}
return NS_OK;
}
@ -74,10 +109,19 @@ xpcAccessibleValue::GetMinimumIncrement(double* aValue)
NS_ENSURE_ARG_POINTER(aValue);
*aValue = 0;
if (Intl()->IsDefunct())
if (Intl().IsNull())
return NS_ERROR_FAILURE;
double value = Intl()->Step();
if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
return NS_ERROR_FAILURE;
double value = Intl().AsAccessible()->Step();
if (Intl().IsAccessible()) {
value = Intl().AsAccessible()->Step();
} else {
value = Intl().AsProxy()->Step();
}
if (!IsNaN(value))
*aValue = value;

View File

@ -32,7 +32,7 @@ protected:
virtual ~xpcAccessibleValue() {}
private:
Accessible* Intl();
AccessibleOrProxy Intl();
xpcAccessibleValue(const xpcAccessibleValue&) = delete;
xpcAccessibleValue& operator =(const xpcAccessibleValue&) = delete;
@ -40,5 +40,4 @@ private:
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -136,7 +136,7 @@ ident:
merge-%:
ifdef LOCALE_MERGEDIR
$(RM) -rf $(LOCALE_MERGEDIR)
MACOSX_DEPLOYMENT_TARGET= compare-locales -m $(LOCALE_MERGEDIR) $(srcdir)/l10n.ini $(L10NBASEDIR) $*
$(topsrcdir)/mach compare-locales --merge-dir $(LOCALE_MERGEDIR) $*
endif
@echo

View File

@ -75,7 +75,7 @@
accesskey="&emailPageCmd.accesskey;"
command="Browser:SendLink"/>
<menuseparator/>
#if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT)
#if !defined(MOZ_WIDGET_GTK)
<menuitem id="menu_printSetup"
label="&printSetupCmd.label;"
accesskey="&printSetupCmd.accesskey;"

View File

@ -273,7 +273,7 @@ toolbar[customizing] > .overflow-button {
}
%endif
%if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT)
%if !defined(MOZ_WIDGET_GTK)
#TabsToolbar > .private-browsing-indicator {
-moz-box-ordinal-group: 1000;
}

View File

@ -561,7 +561,7 @@
#ifdef MENUBAR_CAN_AUTOHIDE
toolbarname="&menubarCmd.label;"
accesskey="&menubarCmd.accesskey;"
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
#if defined(MOZ_WIDGET_GTK)
autohide="true"
#endif
#endif
@ -590,7 +590,7 @@
context="toolbar-context-menu"
collapsed="true">
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
#if defined(MOZ_WIDGET_GTK)
<hbox id="private-browsing-indicator"
skipintoolbarset="true"/>
#endif
@ -640,7 +640,7 @@
</menupopup>
</toolbarbutton>
#if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT)
#if !defined(MOZ_WIDGET_GTK)
<hbox class="private-browsing-indicator" skipintoolbarset="true"/>
#endif
#ifdef CAN_DRAW_IN_TITLEBAR

View File

@ -9,16 +9,6 @@
color: #fff;
}
/* Use inverted spinner icon on the dark background */
.update-throbber {
list-style-image: url("chrome://global/skin/icons/loading-inverted.png");
}
@media (min-resolution: 1.1dppx) {
.update-throbber {
list-style-image: url("chrome://global/skin/icons/loading-inverted@2x.png");
}
}
.text-link {
color: #fff !important;
text-decoration: underline;

View File

@ -9,16 +9,6 @@
color: #fff;
}
/* Use inverted spinner icon on the dark background */
.update-throbber {
list-style-image: url("chrome://global/skin/icons/loading-inverted.png");
}
@media (min-resolution: 1.1dppx) {
.update-throbber {
list-style-image: url("chrome://global/skin/icons/loading-inverted@2x.png");
}
}
.text-link {
color: #fff !important;
text-decoration: underline;

View File

@ -9,16 +9,6 @@
color: #fff;
}
/* Use inverted spinner icon on the dark background */
.update-throbber {
list-style-image: url("chrome://global/skin/icons/loading-inverted.png");
}
@media (min-resolution: 1.1dppx) {
.update-throbber {
list-style-image: url("chrome://global/skin/icons/loading-inverted@2x.png");
}
}
.text-link {
color: #fff !important;
text-decoration: underline;

View File

@ -143,7 +143,6 @@
<radio id="networkProxySOCKSVersion4" value="4" label="&socks4.label;" accesskey="&socks4.accesskey;" />
<radio id="networkProxySOCKSVersion5" value="5" label="&socks5.label;" accesskey="&socks5.accesskey;" />
</radiogroup>
<checkbox id="networkProxySOCKSRemoteDNS" preference="network.proxy.socks_remote_dns" label="&socksRemoteDNS.label;" accesskey="&socksRemoteDNS.accesskey;" />
</box>
</row>
<label value="&noproxy.label;" accesskey="&noproxy.accesskey;" control="networkProxyNone"/>
@ -168,6 +167,7 @@
accesskey="&autologinproxy.accesskey;"
preference="signon.autologin.proxy"
tooltiptext="&autologinproxy.tooltip;"/>
<checkbox id="networkProxySOCKSRemoteDNS" preference="network.proxy.socks_remote_dns" label="&socksRemoteDNS.label2;" accesskey="&socksRemoteDNS.accesskey;" />
<separator/>
</prefpane>
</prefwindow>

View File

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "gecko rust 1.9.0 (commit e4e8b666850a763fdf1c3c2c142856ab51e32779)",
"size": 96854912,
"digest": "d613d5528e83bb73917372948c05a766912a9dd0ec4e8a5fab69161a515c1545d52e9ed3394716df96a9dcdf1c086b6f970413e97c2df78a11e5f9151573921a",
"version": "gecko rustc 1.10.0 (cfcb716cf 2016-07-03)",
"size": 102276708,
"digest": "8cc9ea8347fc7e6e6fdb15a8fd1faae977f1235a426b879b3f9128ec91d8f2b6268297ce80bf4eceb47738bd40bfeda13f143dc3fe85f1434b13adfbc095ab90",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

View File

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "gecko rust 1.9.0 (commit e4e8b666850a763fdf1c3c2c142856ab51e32779)",
"size": 96854912,
"digest": "d613d5528e83bb73917372948c05a766912a9dd0ec4e8a5fab69161a515c1545d52e9ed3394716df96a9dcdf1c086b6f970413e97c2df78a11e5f9151573921a",
"version": "gecko rustc 1.10.0 (cfcb716cf 2016-07-03)",
"size": 102276708,
"digest": "8cc9ea8347fc7e6e6fdb15a8fd1faae977f1235a426b879b3f9128ec91d8f2b6268297ce80bf4eceb47738bd40bfeda13f143dc3fe85f1434b13adfbc095ab90",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

View File

@ -188,7 +188,7 @@ ident:
merge-%:
ifdef LOCALE_MERGEDIR
$(RM) -rf $(LOCALE_MERGEDIR)
MACOSX_DEPLOYMENT_TARGET= compare-locales -m $(LOCALE_MERGEDIR) $(srcdir)/l10n.ini $(L10NBASEDIR) $*
$(topsrcdir)/mach compare-locales --merge-dir $(LOCALE_MERGEDIR) $*
endif
@echo

View File

@ -32,7 +32,7 @@
<!ENTITY socks4.accesskey "K">
<!ENTITY socks5.label "SOCKS v5">
<!ENTITY socks5.accesskey "v">
<!ENTITY socksRemoteDNS.label "Remote DNS">
<!ENTITY socksRemoteDNS.label2 "Proxy DNS when using SOCKS v5">
<!ENTITY socksRemoteDNS.accesskey "d">
<!ENTITY port.label "Port:">
<!ENTITY HTTPport.accesskey "P">

View File

@ -1,62 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
import re
import codecs
try:
from Mozilla.Parser import getParser
except ImportError:
sys.exit('''extract-bookmarks needs compare-locales
Find that on http://pypi.python.org/pypi/compare-locales.
This script has been tested with version 0.6, and might work with future
versions.''')
ll=re.compile('\.(title|a|dd|h[0-9])$')
p = getParser(sys.argv[1])
p.readFile(sys.argv[1])
template = '''#filter emptyLines
# LOCALIZATION NOTE: The 'en-US' strings in the URLs will be replaced with
# your locale code, and link to your translated pages as soon as they're
# live.
#define bookmarks_title %s
#define bookmarks_heading %s
#define bookmarks_toolbarfolder %s
#define bookmarks_toolbarfolder_description %s
# LOCALIZATION NOTE (getting_started):
# link title for https://www.mozilla.org/en-US/firefox/central/
#define getting_started %s
# LOCALIZATION NOTE (firefox_heading):
# Firefox links folder name
#define firefox_heading %s
# LOCALIZATION NOTE (firefox_help):
# link title for https://www.mozilla.org/en-US/firefox/help/
#define firefox_help %s
# LOCALIZATION NOTE (firefox_customize):
# link title for https://www.mozilla.org/en-US/firefox/customize/
#define firefox_customize %s
# LOCALIZATION NOTE (firefox_community):
# link title for https://www.mozilla.org/en-US/contribute/
#define firefox_community %s
# LOCALIZATION NOTE (firefox_about):
# link title for https://www.mozilla.org/en-US/about/
#define firefox_about %s
#unfilter emptyLines'''
strings = tuple(e.val for e in p if ll.search(e.key))
print codecs.utf_8_encode(template % strings)[0]

View File

@ -450,16 +450,8 @@ TabWindow.prototype = {
let preview = AeroPeek.taskbar.createTaskbarTabPreview(docShell, controller);
preview.visible = AeroPeek.enabled;
preview.active = this.tabbrowser.selectedTab == controller.tab;
// Grab the default favicon
getFaviconAsImage(
null,
PrivateBrowsingUtils.isWindowPrivate(this.win),
function (img) {
// It is possible that we've already gotten the real favicon, so make sure
// we have not set one before setting this default one.
if (!preview.icon)
preview.icon = img;
});
this.onLinkIconAvailable(controller.tab.linkedBrowser,
controller.tab.getAttribute("image"));
return preview;
},
@ -610,21 +602,20 @@ TabWindow.prototype = {
"file", "chrome", "resource", "about"
]),
onLinkIconAvailable: function (aBrowser, aIconURL) {
if (!aIconURL) {
return;
let requestURL = null;
if (aIconURL) {
let shouldRequestFaviconURL = true;
try {
urlObject = NetUtil.newURI(aIconURL);
shouldRequestFaviconURL =
!this.directRequestProtocols.has(urlObject.scheme);
} catch (ex) {}
requestURL = shouldRequestFaviconURL ?
"moz-anno:favicon:" + aIconURL :
aIconURL;
}
let tab = this.tabbrowser.getTabForBrowser(aBrowser);
let shouldRequestFaviconURL = true;
try {
urlObject = NetUtil.newURI(aIconURL);
shouldRequestFaviconURL =
!this.directRequestProtocols.has(urlObject.scheme);
} catch (ex) {}
let requestURL = shouldRequestFaviconURL ?
"moz-anno:favicon:" + aIconURL :
aIconURL;
let isDefaultFavicon = !requestURL;
getFaviconAsImage(
requestURL,
PrivateBrowsingUtils.isWindowPrivate(this.win),
@ -635,8 +626,10 @@ TabWindow.prototype = {
// will have finished fetching 'in order'.
if (index != -1) {
let tab = this.tabbrowser.tabs[index];
if (tab.getAttribute("image") == aIconURL) {
this.previews.get(tab).icon = img;
let preview = this.previews.get(tab);
if (tab.getAttribute("image") == aIconURL ||
(!preview.icon && isDefaultFavicon)) {
preview.icon = img;
}
}
}
@ -654,10 +647,12 @@ TabWindow.prototype = {
this.AeroPeek = {
available: false,
// Does the pref say we're enabled?
_prefenabled: true,
__prefenabled: false,
_enabled: true,
initialized: false,
// nsITaskbarTabPreview array
previews: [],
@ -681,25 +676,14 @@ this.AeroPeek = {
if (!this.available)
return;
this.prefs.addObserver(TOGGLE_PREF_NAME, this, false);
this.prefs.addObserver(DISABLE_THRESHOLD_PREF_NAME, this, false);
this.prefs.addObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this, false);
PlacesUtils.history.addObserver(this, true);
this.cacheLifespan = this.prefs.getIntPref(CACHE_EXPIRATION_TIME_PREF_NAME);
this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME);
this.prefs.addObserver(TOGGLE_PREF_NAME, this, true);
this.enabled = this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME);
this.initialized = true;
},
destroy: function destroy() {
this._enabled = false;
this.prefs.removeObserver(TOGGLE_PREF_NAME, this);
this.prefs.removeObserver(DISABLE_THRESHOLD_PREF_NAME, this);
this.prefs.removeObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this);
if (this.cacheTimer)
this.cacheTimer.cancel();
},
@ -719,6 +703,61 @@ this.AeroPeek = {
});
},
get _prefenabled() {
return this.__prefenabled;
},
set _prefenabled(enable) {
if (enable == this.__prefenabled) {
return;
}
this.__prefenabled = enable;
if (enable) {
this.enable();
} else {
this.disable();
}
},
_observersAdded: false,
enable() {
if (!this._observersAdded) {
this.prefs.addObserver(DISABLE_THRESHOLD_PREF_NAME, this, true);
this.prefs.addObserver(CACHE_EXPIRATION_TIME_PREF_NAME, this, true);
PlacesUtils.history.addObserver(this, true);
this._observersAdded = true;
}
this.cacheLifespan = this.prefs.getIntPref(CACHE_EXPIRATION_TIME_PREF_NAME);
this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME);
// If the user toggled us on/off while the browser was already up
// (rather than this code running on startup because the pref was
// already set to true), we must initialize previews for open windows:
if (this.initialized) {
let browserWindows = Services.wm.getEnumerator("navigator:browser");
while (browserWindows.hasMoreElements()) {
let win = browserWindows.getNext();
if (!win.closed) {
this.onOpenWindow(win);
}
}
}
},
disable() {
while (this.windows.length) {
// We can't call onCloseWindow here because it'll bail if we're not
// enabled.
let tabWinObject = this.windows[0];
tabWinObject.destroy(); // This will remove us from the array.
delete tabWinObject.win.gTaskbarTabGroup; // Tidy up the window.
}
},
addPreview: function (preview) {
this.previews.push(preview);
this.checkPreviewCount();
@ -731,15 +770,15 @@ this.AeroPeek = {
},
checkPreviewCount: function () {
if (this.previews.length > this.maxpreviews)
this.enabled = false;
else
this.enabled = this._prefenabled;
if (!this._prefenabled) {
return;
}
this.enabled = this.previews.length <= this.maxpreviews;
},
onOpenWindow: function (win) {
// This occurs when the taskbar service is not available (xp, vista)
if (!this.available)
if (!this.available || !this._prefenabled)
return;
win.gTaskbarTabGroup = new TabWindow(win);
@ -747,7 +786,7 @@ this.AeroPeek = {
onCloseWindow: function (win) {
// This occurs when the taskbar service is not available (xp, vista)
if (!this.available)
if (!this.available || !this._prefenabled)
return;
win.gTaskbarTabGroup.destroy();
@ -764,14 +803,18 @@ this.AeroPeek = {
//// nsIObserver
observe: function (aSubject, aTopic, aData) {
if (aTopic == "nsPref:changed" && aData == TOGGLE_PREF_NAME) {
this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME);
}
if (!this._prefenabled) {
return;
}
switch (aTopic) {
case "nsPref:changed":
if (aData == CACHE_EXPIRATION_TIME_PREF_NAME)
break;
if (aData == TOGGLE_PREF_NAME)
this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME);
else if (aData == DISABLE_THRESHOLD_PREF_NAME)
if (aData == DISABLE_THRESHOLD_PREF_NAME)
this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME);
// Might need to enable/disable ourselves
this.checkPreviewCount();
@ -796,7 +839,7 @@ this.AeroPeek = {
onClearHistory() {},
onDeleteVisits() {},
onPageChanged(uri, changedConst, newValue) {
if (this._enabled && changedConst == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
if (this.enabled && changedConst == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
for (let win of this.windows) {
for (let [tab, preview] of win.previews) {
if (tab.getAttribute("image") == newValue) {
@ -807,7 +850,11 @@ this.AeroPeek = {
}
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsINavHistoryObserver]),
QueryInterface: XPCOMUtils.generateQI([
Ci.nsISupportsWeakReference,
Ci.nsINavHistoryObserver,
Ci.nsIObserver
]),
};
XPCOMUtils.defineLazyGetter(AeroPeek, "cacheTimer", () =>

View File

@ -35,13 +35,10 @@ function test() {
ok(preview.visible, "Preview is shown as expected");
gPrefService.setBoolPref(ENABLE_PREF_NAME, false);
checkPreviews(4, "Previews are unchanged when disabling");
for (let preview of AeroPeek.previews)
ok(!preview.visible, "Preview is not shown as expected after disabling");
is(0, AeroPeek.previews.length, "Should have 0 previews when disabled");
gPrefService.setBoolPref(ENABLE_PREF_NAME, true);
checkPreviews(4, "Previews are unchanged when re-enabling");
checkPreviews(4, "Previews are back when re-enabling");
for (let preview of AeroPeek.previews)
ok(preview.visible, "Preview is shown as expected after re-enabling");
@ -82,14 +79,14 @@ function test() {
checkPreviews(1);
if (gPrefService.prefHasUserValue(ENABLE_PREF_NAME))
gPrefService.clearUserPref(ENABLE_PREF_NAME);
gPrefService.setBoolPref(ENABLE_PREF_NAME, !gPrefService.getBoolPref(ENABLE_PREF_NAME));
finish();
function checkPreviews(aPreviews, msg) {
let nPreviews = AeroPeek.previews.length;
is(aPreviews, gBrowser.tabs.length, "Browser has expected number of tabs");
is(nPreviews, gBrowser.tabs.length, "Browser has one preview per tab");
is(aPreviews, gBrowser.tabs.length, "Browser has expected number of tabs - " + msg);
is(nPreviews, gBrowser.tabs.length, "Browser has one preview per tab - " + msg);
is(nPreviews, aPreviews, msg || "Got expected number of previews");
}

View File

@ -8,7 +8,7 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
if toolkit == 'cocoa':
DIRS += ['osx']
elif toolkit in ('gtk2', 'gtk3', 'qt'):
elif toolkit in ('gtk2', 'gtk3'):
DIRS += ['linux']
else:
DIRS += ['windows']

View File

@ -91,7 +91,7 @@
.geo-icon {
%ifdef XP_MACOSX
list-style-image: url(chrome://browser/skin/permissions.svg#geo-osx);
%elif defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
%elif defined(MOZ_WIDGET_GTK)
list-style-image: url(chrome://browser/skin/permissions.svg#geo-linux);
%else
list-style-image: url(chrome://browser/skin/permissions.svg#geo-windows);
@ -101,7 +101,7 @@
.geo-icon.blocked {
%ifdef XP_MACOSX
list-style-image: url(chrome://browser/skin/permissions.svg#geo-osx-blocked);
%elif defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
%elif defined(MOZ_WIDGET_GTK)
list-style-image: url(chrome://browser/skin/permissions.svg#geo-linux-blocked);
%else
list-style-image: url(chrome://browser/skin/permissions.svg#geo-windows-blocked);
@ -111,7 +111,7 @@
.popup-notification-icon[popupid="geolocation"] {
%ifdef XP_MACOSX
list-style-image: url(chrome://browser/skin/permissions.svg#geo-osx);
%elif defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
%elif defined(MOZ_WIDGET_GTK)
list-style-image: url(chrome://browser/skin/permissions.svg#geo-linux-detailed);
%else
list-style-image: url(chrome://browser/skin/permissions.svg#geo-windows-detailed);

View File

@ -7,7 +7,7 @@
%filter substitution
%ifdef XP_MACOSX
%include ../osx/shared.inc
%elif defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
%elif defined(MOZ_WIDGET_GTK)
%include ../linux/linuxShared.inc
%else
%include ../windows/windowsShared.inc

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -7,6 +7,8 @@
# Avoid duplication if the file happens to be included twice.
if test -z "$bucket" -a -z "$NO_CACHE"; then
# buildbot (or builders that use buildprops.json):
if [ -f $topsrcdir/../buildprops.json ]; then
read branch platform master <<EOF
$(python2.7 -c 'import json; p = json.loads(open("'"$topsrcdir"'/../buildprops.json").read())["properties"]; print p["branch"], p["platform"], p["master"]' 2> /dev/null)
EOF
@ -40,6 +42,53 @@ if test -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z
esac
fi
# builds without buildprops (eg: taskcluster or non-buildbot) and without ccache env config and without sccache disabled:
elif test -z "$CCACHE_DIR" -a -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z "$MOZ_PGO"; then
# prevent rerun if az is set, or wget is not available
if test -z "$availability_zone" -a -x "$(command -v wget)"; then
# timeout after 1 second, and don't retry (failure indicates instance is not in ec2 or network issue)
# availability_zone is of the form <region><letter> where region is e.g. us-west-2, and az is us-west-2a
availability_zone=$(wget -T 1 -t 1 -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone || true)
if test -z "$availability_zone" -o "$availability_zone" = "not-ec2"; then
availability_zone=not-ec2
else
# region is az with last letter trimmed
region=${availability_zone%?}
# set S3 bucket according to tree (level)
case "${GECKO_HEAD_REPOSITORY}" in
*hg.mozilla.org/try*)
bucket=taskcluster-level-1-sccache-${region}
;;
*hg.mozilla.org/integration/mozilla-inbound*|*hg.mozilla.org/integration/fx-team*)
bucket=taskcluster-level-3-sccache-${region}
;;
esac
# set a dummy master
case "${region}" in
us-east-1)
master=dummy.use1.mozilla.com
;;
us-west-1)
master=dummy.usw1.mozilla.com
;;
us-west-2)
master=dummy.usw2.mozilla.com
;;
esac
fi
fi
# set platform based on the SYSTEMROOT env var
case "${SYSTEMROOT}" in
*Windows)
platform=windows
;;
esac
fi
if test -z "$bucket"; then
case "$platform" in
win*) : ;;
@ -53,7 +102,7 @@ else
fi
mk_add_options "export SCCACHE_BUCKET=$bucket"
case "$master" in
*use1.mozilla.com*|*usw2.mozilla.com*)
*us[ew][12].mozilla.com*)
mk_add_options "export SCCACHE_NAMESERVER=169.254.169.253"
;;
esac

View File

@ -284,6 +284,8 @@ skip-if = e10s && debug
skip-if = e10s # TODO
[browser_dbg_instruments-pane-collapse.js]
skip-if = e10s && debug
[browser_dbg_instruments-pane-collapse_keyboard.js]
skip-if = (os == 'mac' && e10s && debug) # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control
[browser_dbg_interrupts.js]
skip-if = e10s && debug
[browser_dbg_listaddons.js]

View File

@ -0,0 +1,40 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the debugger panes collapse properly.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
function test() {
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
Task.spawn(function* () {
let doc = aPanel.panelWin.document;
let panel = doc.getElementById("instruments-pane");
let button = doc.getElementById("instruments-pane-toggle");
ok(panel.classList.contains("pane-collapsed"),
"The instruments panel is initially in collapsed state");
yield togglePane(button, "Press on the toggle button to expand", panel, "VK_RETURN");
ok(!panel.classList.contains("pane-collapsed"),
"The instruments panel is in the expanded state");
yield togglePane(button, "Press on the toggle button to collapse", panel, "VK_SPACE");
ok(panel.classList.contains("pane-collapsed"),
"The instruments panel is in the collapsed state");
closeDebuggerAndFinish(aPanel);
});
});
}
function* togglePane(button, message, pane, keycode) {
let onTransitionEnd = once(pane, "transitionend");
info(message);
button.focus();
EventUtils.synthesizeKey(keycode, {});
yield onTransitionEnd;
}

View File

@ -21,6 +21,7 @@ function ToolbarView(DebuggerController, DebuggerView) {
this.DebuggerController = DebuggerController;
this.DebuggerView = DebuggerView;
this._onTogglePanesActivated = this._onTogglePanesActivated.bind(this);
this._onTogglePanesPressed = this._onTogglePanesPressed.bind(this);
this._onResumePressed = this._onResumePressed.bind(this);
this._onStepOverPressed = this._onStepOverPressed.bind(this);
@ -62,7 +63,10 @@ ToolbarView.prototype = {
this._stepInTooltip = L10N.getFormatStr("stepInTooltip", stepInKey);
this._stepOutTooltip = L10N.getFormatStr("stepOutTooltip", stepOutKey);
this._instrumentsPaneToggleButton.addEventListener("mousedown", this._onTogglePanesPressed, false);
this._instrumentsPaneToggleButton.addEventListener("mousedown",
this._onTogglePanesActivated, false);
this._instrumentsPaneToggleButton.addEventListener("keydown",
this._onTogglePanesPressed, false);
this._resumeButton.addEventListener("mousedown", this._onResumePressed, false);
this._stepOverButton.addEventListener("mousedown", this._onStepOverPressed, false);
this._stepInButton.addEventListener("mousedown", this._onStepInPressed, false);
@ -82,7 +86,10 @@ ToolbarView.prototype = {
destroy: function () {
dumpn("Destroying the ToolbarView");
this._instrumentsPaneToggleButton.removeEventListener("mousedown", this._onTogglePanesPressed, false);
this._instrumentsPaneToggleButton.removeEventListener("mousedown",
this._onTogglePanesActivated, false);
this._instrumentsPaneToggleButton.removeEventListener("keydown",
this._onTogglePanesPressed, false);
this._resumeButton.removeEventListener("mousedown", this._onResumePressed, false);
this._stepOverButton.removeEventListener("mousedown", this._onStepOverPressed, false);
this._stepInButton.removeEventListener("mousedown", this._onStepInPressed, false);
@ -168,10 +175,19 @@ ToolbarView.prototype = {
}
},
/**
* Listener handling the toggle button space and return key event.
*/
_onTogglePanesPressed: function (event) {
if (ViewHelpers.isSpaceOrReturn(event)) {
this._onTogglePanesActivated();
}
},
/**
* Listener handling the toggle button click event.
*/
_onTogglePanesPressed: function () {
_onTogglePanesActivated: function() {
DebuggerView.toggleInstrumentsPane({
visible: DebuggerView.instrumentsPaneHidden,
animated: true,

View File

@ -99,7 +99,8 @@ function InspectorPanel(iframeWindow, toolbox) {
this.onNewSelection = this.onNewSelection.bind(this);
this.onBeforeNewSelection = this.onBeforeNewSelection.bind(this);
this.onDetached = this.onDetached.bind(this);
this.onPaneToggleButtonClicked = this.onPaneToggleButtonClicked.bind(this);
this.onPaneToggleButtonActivated = this.onPaneToggleButtonActivated.bind(this);
this.onPaneToggleButtonPressed = this.onPaneToggleButtonPressed.bind(this);
this._onMarkupFrameLoad = this._onMarkupFrameLoad.bind(this);
let doc = this.panelDoc;
@ -447,7 +448,8 @@ InspectorPanel.prototype = {
"devtools/client/shared/components/sidebar-toggle"));
let sidebarToggle = SidebarToggle({
onClick: this.onPaneToggleButtonClicked,
onClick: this.onPaneToggleButtonActivated,
onKeyDown: this.onPaneToggleButtonPressed,
collapsed: false,
expandPaneTitle: strings.GetStringFromName("inspector.expandPane"),
collapsePaneTitle: strings.GetStringFromName("inspector.collapsePane"),
@ -1153,11 +1155,21 @@ InspectorPanel.prototype = {
return destroyPromise;
},
/**
* When the pane toggle button is pressed with space and return keys toggle
* the pane, change the button state and tooltip.
*/
onPaneToggleButtonPressed: function (event) {
if (ViewHelpers.isSpaceOrReturn(event)) {
this.onPaneToggleButtonActivated(event);
}
},
/**
* When the pane toggle button is clicked, toggle the pane, change the button
* state and tooltip.
*/
onPaneToggleButtonClicked: function (e) {
onPaneToggleButtonActivated: function (e) {
let sidePane = this.panelDoc.querySelector("#inspector-sidebar");
let isVisible = !this._sidebarToggle.state.collapsed;

View File

@ -172,7 +172,7 @@ MarkupView.prototype = {
this.eventDetailsTooltip = new HTMLTooltip(this._inspector.toolbox,
{type: "arrow"});
this.imagePreviewTooltip = new HTMLTooltip(this._inspector.toolbox,
{type: "arrow"});
{type: "arrow", useXulWrapper: "true"});
this._enableImagePreviewTooltip();
},

View File

@ -125,7 +125,8 @@ skip-if = e10s # Bug 1036409 - The last selected node isn't reselected
[browser_markup_tag_edit_01.js]
[browser_markup_tag_edit_02.js]
[browser_markup_tag_edit_03.js]
[browser_markup_tag_edit_04.js]
[browser_markup_tag_edit_04-backspace.js]
[browser_markup_tag_edit_04-delete.js]
[browser_markup_tag_edit_05.js]
[browser_markup_tag_edit_06.js]
[browser_markup_tag_edit_07.js]

View File

@ -0,0 +1,59 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Tests that a node can be deleted from the markup-view with the backspace key.
// Also checks that after deletion the correct element is highlighted.
// The previous sibling is preferred, but the parent is a fallback.
const HTML = `<style type="text/css">
#pseudo::before { content: 'before'; }
#pseudo::after { content: 'after'; }
</style>
<div id="parent">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</div>
<div id="only-child">
<div id="fourth"></div>
</div>
<div id="pseudo">
<div id="fifth"></div>
</div>`;
const TEST_URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
// List of all the test cases. Each item is an object with the following props:
// - selector: the css selector of the node that should be selected
// - focusedSelector: the css selector of the node we expect to be selected as
// a result of the deletion
// - pseudo: (optional) if the focused node is actually supposed to be a pseudo element
// of the specified selector.
// Note that after each test case, undo is called.
const TEST_DATA = [{
selector: "#first",
focusedSelector: "#second"
}, {
selector: "#second",
focusedSelector: "#first"
}, {
selector: "#third",
focusedSelector: "#second"
}, {
selector: "#fourth",
focusedSelector: "#only-child"
}, {
selector: "#fifth",
focusedSelector: "#pseudo",
pseudo: "before"
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URL);
for (let data of TEST_DATA) {
yield checkDeleteAndSelection(inspector, "back_space", data);
}
});

View File

@ -0,0 +1,59 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Tests that a node can be deleted from the markup-view with the delete key.
// Also checks that after deletion the correct element is highlighted.
// The next sibling is preferred, but the parent is a fallback.
const HTML = `<style type="text/css">
#pseudo::before { content: 'before'; }
#pseudo::after { content: 'after'; }
</style>
<div id="parent">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</div>
<div id="only-child">
<div id="fourth"></div>
</div>
<div id="pseudo">
<div id="fifth"></div>
</div>`;
const TEST_URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
// List of all the test cases. Each item is an object with the following props:
// - selector: the css selector of the node that should be selected
// - focusedSelector: the css selector of the node we expect to be selected as
// a result of the deletion
// - pseudo: (optional) if the focused node is actually supposed to be a pseudo element
// of the specified selector.
// Note that after each test case, undo is called.
const TEST_DATA = [{
selector: "#first",
focusedSelector: "#second"
}, {
selector: "#second",
focusedSelector: "#third"
}, {
selector: "#third",
focusedSelector: "#second"
}, {
selector: "#fourth",
focusedSelector: "#only-child"
}, {
selector: "#fifth",
focusedSelector: "#pseudo",
pseudo: "after"
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URL);
for (let data of TEST_DATA) {
yield checkDeleteAndSelection(inspector, "delete", data);
}
});

View File

@ -1,121 +0,0 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Tests that a node can be deleted from the markup-view with the delete key.
// Also checks that after deletion the correct element is highlighted.
// The next sibling is preferred, but the parent is a fallback.
const HTML = `<style type="text/css">
#pseudo::before { content: 'before'; }
#pseudo::after { content: 'after'; }
</style>
<div id="parent">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</div>
<div id="only-child">
<div id="fourth"></div>
</div>
<div id="pseudo">
<div id="fifth"></div>
</div>`;
const TEST_URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
// List of all the test cases. Each item is an object with the following props:
// - selector: the css selector of the node that should be selected
// - key: the key to press to delete the node (delete or back_space)
// - focusedSelector: the css selector of the node we expect to be selected as
// a result of the deletion
// - pseudo: (optional) if the focused node is actually supposed to be a pseudo element
// of the specified selector.
// Note that after each test case, undo is called.
const TEST_DATA = [{
selector: "#first",
key: "delete",
focusedSelector: "#second"
}, {
selector: "#second",
key: "delete",
focusedSelector: "#third"
}, {
selector: "#third",
key: "delete",
focusedSelector: "#second"
}, {
selector: "#fourth",
key: "delete",
focusedSelector: "#only-child"
}, {
selector: "#fifth",
key: "delete",
focusedSelector: "#pseudo",
pseudo: "after"
}, {
selector: "#first",
key: "back_space",
focusedSelector: "#second"
}, {
selector: "#second",
key: "back_space",
focusedSelector: "#first"
}, {
selector: "#third",
key: "back_space",
focusedSelector: "#second"
}, {
selector: "#fourth",
key: "back_space",
focusedSelector: "#only-child"
}, {
selector: "#fifth",
key: "back_space",
focusedSelector: "#pseudo",
pseudo: "before"
}];
add_task(function* () {
let {inspector} = yield openInspectorForURL(TEST_URL);
for (let data of TEST_DATA) {
yield checkDeleteAndSelection(inspector, data);
}
});
function* checkDeleteAndSelection(inspector, {key, selector, focusedSelector, pseudo}) {
info("Test deleting node " + selector + " with " + key + ", " +
"expecting " + focusedSelector + " to be focused");
info("Select node " + selector + " and make sure it is focused");
yield selectNode(selector, inspector);
yield clickContainer(selector, inspector);
info("Delete the node with: " + key);
let mutated = inspector.once("markupmutation");
EventUtils.sendKey(key, inspector.panelWin);
yield Promise.all([mutated, inspector.once("inspector-updated")]);
let nodeFront = yield getNodeFront(focusedSelector, inspector);
if (pseudo) {
// Update the selector for logging in case of failure.
focusedSelector = focusedSelector + "::" + pseudo;
// Retrieve the :before or :after pseudo element of the nodeFront.
let {nodes} = yield inspector.walker.children(nodeFront);
nodeFront = pseudo === "before" ? nodes[0] : nodes[nodes.length - 1];
}
is(inspector.selection.nodeFront, nodeFront,
focusedSelector + " is selected after deletion");
info("Check that the node was really removed");
let node = yield getNodeFront(selector, inspector);
ok(!node, "The node can't be found in the page anymore");
info("Undo the deletion to restore the original markup");
yield undoChange(inspector);
node = yield getNodeFront(selector, inspector);
ok(node, "The node is back");
}

View File

@ -610,3 +610,53 @@ function* waitForScrollStop(doc) {
return lastScrollTop;
}
/**
* Select a node in the inspector and try to delete it using the provided key. After that,
* check that the expected element is focused.
*
* @param {InspectorPanel} inspector
* The current inspector-panel instance.
* @param {String} key
* The key to simulate to delete the node
* @param {Object}
* - {String} selector: selector of the element to delete.
* - {String} focusedSelector: selector of the element that should be selected
* after deleting the node.
* - {String} pseudo: optional, "before" or "after" if the element focused after
* deleting the node is supposed to be a before/after pseudo-element.
*/
function* checkDeleteAndSelection(inspector, key, {selector, focusedSelector, pseudo}) {
info("Test deleting node " + selector + " with " + key + ", " +
"expecting " + focusedSelector + " to be focused");
info("Select node " + selector + " and make sure it is focused");
yield selectNode(selector, inspector);
yield clickContainer(selector, inspector);
info("Delete the node with: " + key);
let mutated = inspector.once("markupmutation");
EventUtils.sendKey(key, inspector.panelWin);
yield Promise.all([mutated, inspector.once("inspector-updated")]);
let nodeFront = yield getNodeFront(focusedSelector, inspector);
if (pseudo) {
// Update the selector for logging in case of failure.
focusedSelector = focusedSelector + "::" + pseudo;
// Retrieve the :before or :after pseudo element of the nodeFront.
let {nodes} = yield inspector.walker.children(nodeFront);
nodeFront = pseudo === "before" ? nodes[0] : nodes[nodes.length - 1];
}
is(inspector.selection.nodeFront, nodeFront,
focusedSelector + " is selected after deletion");
info("Check that the node was really removed");
let node = yield getNodeFront(selector, inspector);
ok(!node, "The node can't be found in the page anymore");
info("Undo the deletion to restore the original markup");
yield undoChange(inspector);
node = yield getNodeFront(selector, inspector);
ok(node, "The node is back");
}

View File

@ -280,7 +280,8 @@ TooltipsOverlay.prototype = {
// Image, fonts, ... preview tooltip
this.previewTooltip = new HTMLTooltip(this.view.inspector.toolbox, {
type: "arrow"
type: "arrow",
useXulWrapper: true
});
this.previewTooltip.startTogglingOnHover(this.view.element,
this._onPreviewTooltipTargetHover.bind(this));

View File

@ -114,6 +114,8 @@ subsuite = clipboard
[browser_inspector_pane-toggle-02.js]
[browser_inspector_pane-toggle-03.js]
[browser_inspector_pane-toggle-04.js]
[browser_inspector_pane-toggle-05.js]
skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard
[browser_inspector_picker-stop-on-destroy.js]
[browser_inspector_picker-stop-on-tool-change.js]
[browser_inspector_pseudoclass-lock.js]

View File

@ -0,0 +1,32 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test the keyboard navigation for the pane toggle using
* space and enter
*/
add_task(function* () {
let {inspector} = yield openInspectorForURL("about:blank", "side");
let panel = inspector.panelDoc.querySelector("#inspector-sidebar");
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
yield togglePane(button, "Press on the toggle button", panel, "VK_RETURN");
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
yield togglePane(button, "Press on the toggle button to expand the panel again",
panel, "VK_SPACE");
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
});
function* togglePane(button, message, panel, keycode) {
let onTransitionEnd = once(panel, "transitionend");
info(message);
button.focus();
EventUtils.synthesizeKey(keycode, {});
yield onTransitionEnd;
}

View File

@ -493,7 +493,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
window.addEventListener("resize", this._onResize, false);
this.requestsMenuSortEvent = getKeyWithEvent(this.sortBy.bind(this));
this.requestsMenuSortKeyboardEvent = getKeyWithEvent(this.sortBy.bind(this), true);
this.requestsMenuFilterEvent = getKeyWithEvent(this.filterOn.bind(this));
this.requestsMenuFilterKeyboardEvent = getKeyWithEvent(
this.filterOn.bind(this), true);
this.reqeustsMenuClearEvent = this.clear.bind(this);
this._onContextShowing = this._onContextShowing.bind(this);
this._onContextNewTabCommand = this.openRequestInTab.bind(this);
@ -525,8 +528,12 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
$("#toolbar-labels").addEventListener("click",
this.requestsMenuSortEvent, false);
$("#toolbar-labels").addEventListener("keydown",
this.requestsMenuSortKeyboardEvent, false);
$("#requests-menu-filter-buttons").addEventListener("click",
this.requestsMenuFilterEvent, false);
$("#requests-menu-filter-buttons").addEventListener("keydown",
this.requestsMenuFilterKeyboardEvent, false);
$("#requests-menu-clear-button").addEventListener("click",
this.reqeustsMenuClearEvent, false);
$("#network-request-popup").addEventListener("popupshowing",
@ -605,8 +612,12 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
$("#toolbar-labels").removeEventListener("click",
this.requestsMenuSortEvent, false);
$("#toolbar-labels").removeEventListener("keydown",
this.requestsMenuSortKeyboardEvent, false);
$("#requests-menu-filter-buttons").removeEventListener("click",
this.requestsMenuFilterEvent, false);
$("#requests-menu-filter-buttons").removeEventListener("keydown",
this.requestsMenuFilterKeyboardEvent, false);
$("#requests-menu-clear-button").removeEventListener("click",
this.reqeustsMenuClearEvent, false);
this.freetextFilterBox.removeEventListener("input",
@ -4017,13 +4028,19 @@ function responseIsFresh({ responseHeaders, status }) {
* @param function callback
* Function to execute execute when data-key
* is present in event.target.
* @param bool onlySpaceOrReturn
* Flag to indicate if callback should only be called
when the space or return button is pressed
* @return function
* Wrapped function with the target data-key as the first argument.
* Wrapped function with the target data-key as the first argument
* and the event as the second argument.
*/
function getKeyWithEvent(callback) {
function getKeyWithEvent(callback, onlySpaceOrReturn) {
return function (event) {
let key = event.target.getAttribute("data-key");
if (key) {
let filterKeyboardEvent = onlySpaceOrReturn
? ViewHelpers.isSpaceOrReturn(event) : true;
if (key && filterKeyboardEvent) {
callback.call(null, key);
}
};

View File

@ -15,6 +15,7 @@ support-files =
[test_reps_grip-array.html]
[test_reps_null.html]
[test_reps_number.html]
[test_reps_object.html]
[test_reps_object-with-text.html]
[test_reps_object-with-url.html]
[test_reps_string.html]

View File

@ -0,0 +1,190 @@
<!DOCTYPE HTML>
<html>
<!--
Test Obj rep
-->
<head>
<meta charset="utf-8">
<title>Rep test - Obj</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
let { Obj } = browserRequire("devtools/client/shared/components/reps/object");
const componentUnderTest = Obj;
try {
yield testBasic();
// Test property iterator
yield testMaxProps();
yield testMoreThanMaxProps();
yield testUninterestingProps();
// Test that properties are rendered as expected by PropRep
yield testNested();
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
function testBasic() {
const stub = {};
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, Obj.rep, `Rep correctly selects ${Obj.rep.displayName}`);
// Test rendering
const defaultOutput = `Object`;
const modeTests = [
{
mode: undefined,
expectedOutput: defaultOutput,
},
{
mode: "tiny",
expectedOutput: defaultOutput,
},
{
mode: "short",
expectedOutput: defaultOutput,
},
{
mode: "long",
expectedOutput: defaultOutput,
}
];
testRepRenderModes(modeTests, "testBasic", componentUnderTest, stub);
}
function testMaxProps() {
const testName = "testMaxProps";
const stub = {a: "a", b: "b", c: "c"};
const defaultOutput = `Object{a: "a", b: "b", c: "c"}`;
const modeTests = [
{
mode: undefined,
expectedOutput: defaultOutput,
},
{
mode: "tiny",
expectedOutput: `Object`,
},
{
mode: "short",
expectedOutput: defaultOutput,
},
{
mode: "long",
expectedOutput: defaultOutput,
}
];
testRepRenderModes(modeTests, "testMaxProps", componentUnderTest, stub);
}
function testMoreThanMaxProps() {
let stub = {};
for (let i = 0; i<100; i++) {
stub[`p${i}`] = i
}
const defaultOutput = `Object{p0: 0, p1: 1, p2: 2, more...}`;
const modeTests = [
{
mode: undefined,
expectedOutput: defaultOutput,
},
{
mode: "tiny",
expectedOutput: `Object`,
},
{
mode: "short",
expectedOutput: defaultOutput,
},
{
mode: "long",
expectedOutput: defaultOutput,
}
];
testRepRenderModes(modeTests, "testMoreThanMaxProps", componentUnderTest, stub);
}
function testUninterestingProps() {
const stub = {a:undefined, b:undefined, c:"c", d:0};
const defaultOutput = `Object{c: "c", d: 0, a: undefined, more...}`;
const modeTests = [
{
mode: undefined,
expectedOutput: defaultOutput,
},
{
mode: "tiny",
expectedOutput: `Object`,
},
{
mode: "short",
expectedOutput: defaultOutput,
},
{
mode: "long",
expectedOutput: defaultOutput,
}
];
testRepRenderModes(modeTests, "testUninterestingProps", componentUnderTest, stub);
}
function testNested() {
const stub = {
objProp: {
id: 1,
arr: [2]
},
strProp: "test string",
arrProp: [1]
};
const defaultOutput = `Object{strProp: "test string", objProp: Object{id: 1, arr: [2]}, arrProp: [1]}`;
const modeTests = [
{
mode: undefined,
expectedOutput: defaultOutput,
},
{
mode: "tiny",
expectedOutput: `Object`,
},
{
mode: "short",
expectedOutput: defaultOutput,
},
{
mode: "long",
expectedOutput: defaultOutput,
}
];
testRepRenderModes(modeTests, "testNestedObject", componentUnderTest, stub);
}
});
</script>
</pre>
</body>
</html>

View File

@ -10,6 +10,7 @@ const defer = require("devtools/shared/defer");
const Services = require("Services");
const { TargetFactory } = require("devtools/client/framework/target");
const Telemetry = require("devtools/client/shared/telemetry");
const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
const NS_XHTML = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -109,6 +110,13 @@ var CommandUtils = {
requisition.updateExec(typed);
}, false);
button.addEventListener("keypress", (event) => {
if (ViewHelpers.isSpaceOrReturn(event)) {
event.preventDefault();
requisition.updateExec(typed);
}
}, false);
// Allow the command button to be toggleable
if (command.state) {
button.setAttribute("autocheck", false);

View File

@ -22,15 +22,13 @@ const TEST_URI = `data:text/xml;charset=UTF-8,<?xml version="1.0"?>
</vbox>
</window>`;
const CONTAINER_HEIGHT = 200;
const CONTAINER_HEIGHT = 300;
const CONTAINER_WIDTH = 200;
const TOOLTIP_HEIGHT = 50;
const {HTMLTooltip} = require("devtools/client/shared/widgets/HTMLTooltip");
loadHelperScript("helper_html_tooltip.js");
let useXulWrapper;
add_task(function* () {
// Force the toolbox to be 400px tall => 50px for each box.
yield pushPref("devtools.toolbox.footer.height", 400);
@ -38,21 +36,11 @@ add_task(function* () {
yield addTab("about:blank");
let [,, doc] = yield createHost("bottom", TEST_URI);
info("Run tests for a Tooltip without using a XUL panel");
useXulWrapper = false;
yield runTests(doc);
info("Run tests for a Tooltip with a XUL panel");
useXulWrapper = true;
yield runTests(doc);
});
function* runTests(doc) {
let tooltip = new HTMLTooltip({doc}, {useXulWrapper});
let tooltip = new HTMLTooltip({doc}, {useXulWrapper: false});
info("Set tooltip content 50px tall, but request a container 200px tall");
let tooltipContent = doc.createElementNS(HTML_NS, "div");
tooltipContent.style.cssText = "height: " + TOOLTIP_HEIGHT + "px; background: red;";
tooltip.setContent(tooltipContent, {width: CONTAINER_WIDTH, height: CONTAINER_HEIGHT});
tooltip.setContent(tooltipContent, {width: CONTAINER_WIDTH, height: Infinity});
info("Show the tooltip and check the container and panel height.");
yield showTooltip(tooltip, doc.getElementById("box1"));
@ -78,11 +66,10 @@ function* runTests(doc) {
yield onPanelClick;
is(tooltip.isVisible(), true, "Tooltip is still visible");
info("Click below the tooltip container, the tooltip should be closed.");
info("Click above the tooltip container, the tooltip should be closed.");
onHidden = once(tooltip, "hidden");
EventUtils.synthesizeMouse(tooltip.container, 100, CONTAINER_HEIGHT + 10,
{}, doc.defaultView);
EventUtils.synthesizeMouse(tooltip.container, 100, -10, {}, doc.defaultView);
yield onHidden;
tooltip.destroy();
}
});

View File

@ -211,7 +211,7 @@ function HTMLTooltip(toolbox, {
this.type = type;
this.autofocus = autofocus;
this.consumeOutsideClicks = consumeOutsideClicks;
this.useXulWrapper = useXulWrapper;
this.useXulWrapper = this._isXUL() && useXulWrapper;
this._position = null;
@ -229,7 +229,7 @@ function HTMLTooltip(toolbox, {
if (stylesheet) {
this._applyStylesheet(stylesheet);
}
if (this._isXUL() && this.useXulWrapper) {
if (this.useXulWrapper) {
// When using a XUL panel as the wrapper, the actual markup for the tooltip is as
// follows :
// <panel> <!-- XUL panel used to position the tooltip anywhere on screen -->
@ -285,9 +285,8 @@ HTMLTooltip.prototype = {
* - {Number} width: preferred width for the tooltip container. If not specified
* the tooltip container will be measured before being displayed, and the
* measured width will be used as preferred width.
* - {Number} height: optional, preferred height for the tooltip container. This
* parameter acts as a max-height for the tooltip content. If not specified,
* the tooltip will be able to use all the height available.
* - {Number} height: optional, preferred height for the tooltip container. If
* not specified, the tooltip will be able to use all the height available.
*/
setContent: function (content, {width = "auto", height = Infinity} = {}) {
this.preferredWidth = width;
@ -332,6 +331,12 @@ HTMLTooltip.prototype = {
let isTop = computedPosition === POSITION.TOP;
this.container.classList.toggle("tooltip-top", isTop);
this.container.classList.toggle("tooltip-bottom", !isTop);
// If the preferred height is set to Infinity, the tooltip container should grow based
// on its content's height and use as much height as possible.
this.container.classList.toggle("tooltip-flexible-height",
this.preferredHeight === Infinity);
this.container.style.height = height + "px";
let preferredWidth;
@ -550,6 +555,9 @@ HTMLTooltip.prototype = {
panel.setAttribute("noautofocus", true);
panel.setAttribute("ignorekeys", true);
// Use type="arrow" to prevent side effects (see Bug 1285206)
panel.setAttribute("type", "arrow");
panel.setAttribute("level", "float");
panel.setAttribute("class", "tooltip-xul-wrapper");

View File

@ -218,6 +218,17 @@ const ViewHelpers = exports.ViewHelpers = {
}
},
/**
* Check if the enter key or space was pressed
*
* @param event event
* The event triggered by a keypress on an element
*/
isSpaceOrReturn: function (event) {
return event.keyCode === event.DOM_VK_SPACE ||
event.keyCode === event.DOM_VK_RETURN;
},
/**
* Sets a toggled pane hidden or visible. The pane can either be displayed on
* the side (right or left depending on the locale) or at the bottom.

View File

@ -79,9 +79,10 @@
}
/* Add element toolbar button */
#inspector-element-add-button::before {
background-image: url("chrome://devtools/skin/images/add.svg");
list-style-image: url("chrome://devtools/skin/images/add.svg");
-moz-user-focus: normal;
}
/* "no results" warning message displayed in the ruleview and in the computed view */

View File

@ -131,6 +131,7 @@
.tooltip-panel{
background-color: var(--theme-tooltip-background);
pointer-events: all;
flex-grow: 1;
}
.tooltip-visible {
@ -142,6 +143,35 @@
visibility: hidden;
}
/* Tooltip : flexible height styles */
.tooltip-flexible-height .tooltip-panel {
/* In flexible mode the tooltip panel should only grow according to its content. */
flex-grow: 0;
}
.tooltip-flexible-height .tooltip-filler {
/* In flexible mode the filler should grow as much as possible. */
flex-grow: 1;
}
/* type="arrow" overrides: remove arrow decorations for the xul <panel> wrapper */
.tooltip-xul-wrapper[type="arrow"] {
margin: 0;
}
/* The arrow image is hidden because the panel is opened using openPopupAtScreen(). */
/* Remove all decorations on .panel-arrowcontent is the tooltip content container. */
.tooltip-xul-wrapper[type="arrow"] .panel-arrowcontent {
margin: 0;
padding: 0;
background: transparent;
border: none;
box-shadow: none;
}
/* Tooltip : arrow style */
.tooltip-xul-wrapper .tooltip-container {
@ -151,7 +181,6 @@
.tooltip-container[type="arrow"] > .tooltip-panel {
position: relative;
flex-grow: 0;
min-height: 10px;
box-sizing: border-box;
width: 100%;
@ -180,10 +209,6 @@
align-self: flex-end;
}
.tooltip-filler {
flex: 1;
}
.tooltip-top .tooltip-arrow {
margin-top: -3px;
}

View File

@ -21,6 +21,8 @@
return Cu.import("resource://gre/modules/Promise.jsm", {}).Promise.defer;
case "Services":
return Cu.import("resource://gre/modules/Services.jsm", {}).Services;
case "resource://gre/modules/Console.jsm":
return Cu.import("resource://gre/modules/Console.jsm", {});
case "chrome":
return {
Cu,
@ -42,13 +44,18 @@
const defer = require("devtools/shared/defer");
let loggingEnabled = true;
let console = {};
if (!isWorker) {
console = require("resource://gre/modules/Console.jsm").console;
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
Services.prefs.addObserver("devtools.dump.emit", {
observe: () => {
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
}
}, false);
} else {
// Workers can't load JSMs, so we can't import Console.jsm here.
console.error = () => {};
}
/**

View File

@ -74,10 +74,25 @@
}
function onlyOnce() {
ok(!beenHere2, "\"once\" listner has been called once");
ok(!beenHere2, "\"once\" listener has been called once");
beenHere2 = true;
emitter.emit("onlyonce");
testThrowingExceptionInListener();
}
function testThrowingExceptionInListener() {
function throwListener() {
emitter.off("throw-exception");
throw {
toString: () => "foo",
stack: "bar",
};
}
emitter.on("throw-exception", throwListener);
emitter.emit("throw-exception");
killItWhileEmitting();
}

View File

@ -429,8 +429,6 @@ var testcases = [ {
protocolChange: true,
}, {
input: "?'.com",
fixedURI: "http:///?%27.com",
alternateURI: "http://www..com/?%27.com",
keywordLookup: true,
protocolChange: true,
}, {
@ -439,14 +437,10 @@ var testcases = [ {
protocolChange: true
}, {
input: "?mozilla",
fixedURI: "http:///?mozilla",
alternateURI: "http://www..com/?mozilla",
keywordLookup: true,
protocolChange: true,
}, {
input: "??mozilla",
fixedURI: "http:///??mozilla",
alternateURI: "http://www..com/??mozilla",
keywordLookup: true,
protocolChange: true,
}, {

View File

@ -776,7 +776,11 @@ BlobImplBase::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
nsAutoString contentType;
GetType(contentType);
CopyUTF16toUTF8(contentType, aContentType);
if (contentType.IsEmpty()) {
aContentType.SetIsVoid(true);
} else {
CopyUTF16toUTF8(contentType, aContentType);
}
aCharset.Truncate();

View File

@ -30,6 +30,7 @@
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/SubtleCryptoBinding.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/WebCryptoCommon.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/ipc/BackgroundChild.h"
@ -395,7 +396,7 @@ StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx,
return ReadStructuredCloneImageData(aCx, aReader);
}
if (aTag == SCTAG_DOM_WEBCRYPTO_KEY) {
if (aTag == SCTAG_DOM_WEBCRYPTO_KEY || aTag == SCTAG_DOM_URLSEARCHPARAMS) {
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
if (!global) {
return nullptr;
@ -404,11 +405,20 @@ StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx,
// Prevent the return value from being trashed by a GC during ~nsRefPtr.
JS::Rooted<JSObject*> result(aCx);
{
RefPtr<CryptoKey> key = new CryptoKey(global);
if (!key->ReadStructuredClone(aReader)) {
result = nullptr;
} else {
result = key->WrapObject(aCx, nullptr);
if (aTag == SCTAG_DOM_WEBCRYPTO_KEY) {
RefPtr<CryptoKey> key = new CryptoKey(global);
if (!key->ReadStructuredClone(aReader)) {
result = nullptr;
} else {
result = key->WrapObject(aCx, nullptr);
}
} else if (aTag == SCTAG_DOM_URLSEARCHPARAMS) {
RefPtr<URLSearchParams> usp = new URLSearchParams(global);
if (!usp->ReadStructuredClone(aReader)) {
result = nullptr;
} else {
result = usp->WrapObject(aCx, nullptr);
}
}
}
return result;
@ -504,6 +514,15 @@ StructuredCloneHolder::WriteFullySerializableObjects(JSContext* aCx,
}
}
// Handle URLSearchParams cloning
{
URLSearchParams* usp = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(URLSearchParams, aObj, usp))) {
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_URLSEARCHPARAMS, 0) &&
usp->WriteStructuredClone(aWriter);
}
}
// Handle Key cloning
{
CryptoKey* key = nullptr;

View File

@ -54,6 +54,9 @@ enum StructuredCloneTags {
SCTAG_DOM_DIRECTORY,
// This tag is used by both main thread and workers.
SCTAG_DOM_URLSEARCHPARAMS,
SCTAG_DOM_MAX
};

View File

@ -223,7 +223,6 @@
#include "nsDOMCaretPosition.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsViewportInfo.h"
#include "nsIContentPermissionPrompt.h"
#include "mozilla/StaticPtr.h"
#include "nsITextControlElement.h"
#include "nsIDOMNSEditableElement.h"
@ -241,7 +240,6 @@
#include "nsIDocumentActivity.h"
#include "nsIStructuredCloneContainer.h"
#include "nsIMutableArray.h"
#include "nsContentPermissionHelper.h"
#include "mozilla/dom/DOMStringList.h"
#include "nsWindowMemoryReporter.h"
#include "nsLocation.h"
@ -11878,27 +11876,11 @@ FullscreenRequest::FullscreenRequest(Element* aElement)
, mDocument(static_cast<nsDocument*>(aElement->OwnerDoc()))
{
MOZ_COUNT_CTOR(FullscreenRequest);
mDocument->mPendingFullscreenRequests++;
if (MOZ_UNLIKELY(!mDocument->mPendingFullscreenRequests)) {
NS_WARNING("Pending fullscreen request counter overflow");
}
}
static void RedispatchPendingPointerLockRequest(nsIDocument* aDocument);
FullscreenRequest::~FullscreenRequest()
{
MOZ_COUNT_DTOR(FullscreenRequest);
if (MOZ_UNLIKELY(!mDocument->mPendingFullscreenRequests)) {
NS_WARNING("Pending fullscreen request counter underflow");
return;
}
mDocument->mPendingFullscreenRequests--;
if (!mDocument->mPendingFullscreenRequests) {
// There may be pointer lock request be blocked because of pending
// fullscreen requests. Re-dispatch it to ensure it gets handled.
RedispatchPendingPointerLockRequest(mDocument);
}
}
// Any fullscreen request waiting for the widget to finish being full-
@ -12301,7 +12283,7 @@ DispatchPointerLockChange(nsIDocument* aTarget)
}
static void
DispatchPointerLockError(nsIDocument* aTarget)
DispatchPointerLockError(nsIDocument* aTarget, const char* aMessage)
{
if (!aTarget) {
return;
@ -12313,178 +12295,117 @@ DispatchPointerLockError(nsIDocument* aTarget)
true,
false);
asyncDispatcher->PostDOMEvent();
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("DOM"), aTarget,
nsContentUtils::eDOM_PROPERTIES,
aMessage);
}
static const uint8_t kPointerLockRequestLimit = 2;
class nsPointerLockPermissionRequest;
mozilla::StaticRefPtr<nsPointerLockPermissionRequest> gPendingPointerLockRequest;
class nsPointerLockPermissionRequest : public Runnable,
public nsIContentPermissionRequest
class PointerLockRequest final : public Runnable
{
public:
nsPointerLockPermissionRequest(Element* aElement, bool aUserInputOrChromeCaller)
: mElement(do_GetWeakReference(aElement)),
mDocument(do_GetWeakReference(aElement->OwnerDoc())),
mUserInputOrChromeCaller(aUserInputOrChromeCaller)
{
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
if (doc && doc->GetInnerWindow()) {
mRequester = new nsContentPermissionRequester(doc->GetInnerWindow());
}
}
PointerLockRequest(Element* aElement, bool aUserInputOrChromeCaller)
: mElement(do_GetWeakReference(aElement))
, mDocument(do_GetWeakReference(aElement->OwnerDoc()))
, mUserInputOrChromeCaller(aUserInputOrChromeCaller)
{}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICONTENTPERMISSIONREQUEST
NS_IMETHOD Run() override
{
nsCOMPtr<Element> e = do_QueryReferent(mElement);
nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
if (!e || !d || gPendingPointerLockRequest != this ||
e->GetUncomposedDoc() != d) {
Handled();
DispatchPointerLockError(d);
return NS_OK;
}
nsDocument* doc = static_cast<nsDocument*>(d.get());
if (doc->mPendingFullscreenRequests > 0) {
// We're still entering fullscreen.
return NS_OK;
}
if (doc->GetFullscreenElement() || doc->mAllowRelocking) {
Allow(JS::UndefinedHandleValue);
return NS_OK;
}
// In non-fullscreen mode user input (or chrome caller) is required!
// Also, don't let the page to try to get the permission too many times.
if (!mUserInputOrChromeCaller ||
doc->mCancelledPointerLockRequests > kPointerLockRequestLimit) {
Handled();
DispatchPointerLockError(d);
return NS_OK;
}
Allow(JS::UndefinedHandleValue);
return NS_OK;
}
void Handled()
{
mElement = nullptr;
mDocument = nullptr;
if (gPendingPointerLockRequest == this) {
gPendingPointerLockRequest = nullptr;
}
}
NS_IMETHOD Run() final;
private:
nsWeakPtr mElement;
nsWeakPtr mDocument;
bool mUserInputOrChromeCaller;
protected:
virtual ~nsPointerLockPermissionRequest() {}
nsCOMPtr<nsIContentPermissionRequester> mRequester;
};
NS_IMPL_ISUPPORTS_INHERITED(nsPointerLockPermissionRequest,
Runnable,
nsIContentPermissionRequest)
NS_IMETHODIMP
nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
static const char*
GetPointerLockError(Element* aElement, Element* aCurrentLock,
bool aNoFocusCheck = false)
{
nsTArray<nsString> emptyOptions;
return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
NS_LITERAL_CSTRING("unused"),
emptyOptions,
aTypes);
}
NS_IMETHODIMP
nsPointerLockPermissionRequest::GetPrincipal(nsIPrincipal** aPrincipal)
{
nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
if (d) {
NS_ADDREF(*aPrincipal = d->NodePrincipal());
// Check if pointer lock pref is enabled
if (!Preferences::GetBool("full-screen-api.pointer-lock.enabled")) {
return "PointerLockDeniedDisabled";
}
return NS_OK;
}
NS_IMETHODIMP
nsPointerLockPermissionRequest::GetWindow(mozIDOMWindow** aWindow)
{
nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
if (d) {
NS_IF_ADDREF(*aWindow = d->GetInnerWindow());
nsCOMPtr<nsIDocument> ownerDoc = aElement->OwnerDoc();
if (aCurrentLock && aCurrentLock->OwnerDoc() != ownerDoc) {
return "PointerLockDeniedInUse";
}
return NS_OK;
}
NS_IMETHODIMP
nsPointerLockPermissionRequest::GetElement(nsIDOMElement** aElement)
{
// It is enough to implement GetWindow.
*aElement = nullptr;
return NS_OK;
}
if (!aElement->IsInUncomposedDoc()) {
return "PointerLockDeniedNotInDocument";
}
NS_IMETHODIMP
nsPointerLockPermissionRequest::Cancel()
{
nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
Handled();
if (d) {
auto doc = static_cast<nsDocument*>(d.get());
if (doc->mCancelledPointerLockRequests <= kPointerLockRequestLimit) {
doc->mCancelledPointerLockRequests++;
if (ownerDoc->GetSandboxFlags() & SANDBOXED_POINTER_LOCK) {
return "PointerLockDeniedSandboxed";
}
// Check if the element is in a document with a docshell.
if (!ownerDoc->GetContainer()) {
return "PointerLockDeniedHidden";
}
nsCOMPtr<nsPIDOMWindowOuter> ownerWindow = ownerDoc->GetWindow();
if (!ownerWindow) {
return "PointerLockDeniedHidden";
}
nsCOMPtr<nsPIDOMWindowInner> ownerInnerWindow = ownerDoc->GetInnerWindow();
if (!ownerInnerWindow) {
return "PointerLockDeniedHidden";
}
if (ownerWindow->GetCurrentInnerWindow() != ownerInnerWindow) {
return "PointerLockDeniedHidden";
}
nsCOMPtr<nsPIDOMWindowOuter> top = ownerWindow->GetScriptableTop();
if (!top || !top->GetExtantDoc() || top->GetExtantDoc()->Hidden()) {
return "PointerLockDeniedHidden";
}
if (!aNoFocusCheck) {
mozilla::ErrorResult rv;
if (!top->GetExtantDoc()->HasFocus(rv)) {
return "PointerLockDeniedNotFocused";
}
DispatchPointerLockError(d);
}
return NS_OK;
return nullptr;
}
NS_IMETHODIMP
nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
PointerLockRequest::Run()
{
MOZ_ASSERT(aChoices.isUndefined());
nsCOMPtr<Element> e = do_QueryReferent(mElement);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
nsDocument* d = static_cast<nsDocument*>(doc.get());
if (!e || !d || gPendingPointerLockRequest != this ||
e->GetUncomposedDoc() != d) {
Handled();
DispatchPointerLockError(d);
const char* error = nullptr;
if (!e || !d || !e->GetUncomposedDoc()) {
error = "PointerLockDeniedNotInDocument";
} else if (e->GetUncomposedDoc() != d) {
error = "PointerLockDeniedMovedDocument";
}
if (!error) {
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (e == pointerLockedElement) {
DispatchPointerLockChange(d);
return NS_OK;
}
// Note, we must bypass focus change, so pass true as the last parameter!
error = GetPointerLockError(e, pointerLockedElement, true);
}
// If it is neither user input initiated, nor requested in fullscreen,
// it should be rejected.
if (!error && !mUserInputOrChromeCaller && !doc->GetFullscreenElement()) {
error = "PointerLockDeniedNotInputDriven";
}
if (!error && !d->SetPointerLock(e, NS_STYLE_CURSOR_NONE)) {
error = "PointerLockDeniedFailedToLock";
}
if (error) {
DispatchPointerLockError(d, error);
return NS_OK;
}
// Mark handled here so that we don't need to call it everywhere below.
Handled();
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (e == pointerLockedElement) {
DispatchPointerLockChange(d);
return NS_OK;
}
// Note, we must bypass focus change, so pass true as the last parameter!
if (!d->ShouldLockPointer(e, pointerLockedElement, true)) {
DispatchPointerLockError(d);
return NS_OK;
}
if (!d->SetPointerLock(e, NS_STYLE_CURSOR_NONE)) {
DispatchPointerLockError(d);
return NS_OK;
}
d->mCancelledPointerLockRequests = 0;
e->SetPointerLock();
EventStateManager::sPointerLockedElement = do_GetWeakReference(e);
EventStateManager::sPointerLockedDoc = do_GetWeakReference(doc);
@ -12500,43 +12421,148 @@ nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
return NS_OK;
}
NS_IMETHODIMP
nsPointerLockPermissionRequest::GetRequester(nsIContentPermissionRequester** aRequester)
void
nsDocument::RequestPointerLock(Element* aElement)
{
NS_ENSURE_ARG_POINTER(aRequester);
NS_ASSERTION(aElement,
"Must pass non-null element to nsDocument::RequestPointerLock");
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (aElement == pointerLockedElement) {
DispatchPointerLockChange(this);
return;
}
if (const char* msg = GetPointerLockError(aElement, pointerLockedElement)) {
DispatchPointerLockError(this, msg);
return;
}
bool userInputOrChromeCaller = EventStateManager::IsHandlingUserInput() ||
nsContentUtils::IsCallerChrome();
NS_DispatchToMainThread(new PointerLockRequest(aElement,
userInputOrChromeCaller));
}
bool
nsDocument::SetPointerLock(Element* aElement, int aCursorStyle)
{
MOZ_ASSERT(!aElement || aElement->OwnerDoc() == this,
"We should be either unlocking pointer (aElement is nullptr), "
"or locking pointer to an element in this document");
#ifdef DEBUG
if (!aElement) {
nsCOMPtr<nsIDocument> pointerLockedDoc =
do_QueryReferent(EventStateManager::sPointerLockedDoc);
MOZ_ASSERT(pointerLockedDoc == this);
}
#endif
nsIPresShell* shell = GetShell();
if (!shell) {
NS_WARNING("SetPointerLock(): No PresShell");
return false;
}
nsPresContext* presContext = shell->GetPresContext();
if (!presContext) {
NS_WARNING("SetPointerLock(): Unable to get PresContext");
return false;
}
nsCOMPtr<nsIWidget> widget;
nsIFrame* rootFrame = shell->GetRootFrame();
if (!NS_WARN_IF(!rootFrame)) {
widget = rootFrame->GetNearestWidget();
NS_WARN_IF_FALSE(widget, "SetPointerLock(): Unable to find widget "
"in shell->GetRootFrame()->GetNearestWidget();");
if (aElement && !widget) {
return false;
}
}
// Hide the cursor and set pointer lock for future mouse events
RefPtr<EventStateManager> esm = presContext->EventStateManager();
esm->SetCursor(aCursorStyle, nullptr, false,
0.0f, 0.0f, widget, true);
esm->SetPointerLock(widget, aElement);
return true;
}
void
nsDocument::UnlockPointer(nsIDocument* aDoc)
{
if (!EventStateManager::sIsPointerLocked) {
return;
}
nsCOMPtr<nsIDocument> pointerLockedDoc =
do_QueryReferent(EventStateManager::sPointerLockedDoc);
if (!pointerLockedDoc || (aDoc && aDoc != pointerLockedDoc)) {
return;
}
nsDocument* doc = static_cast<nsDocument*>(pointerLockedDoc.get());
if (!doc->SetPointerLock(nullptr, NS_STYLE_CURSOR_AUTO)) {
return;
}
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (pointerLockedElement) {
pointerLockedElement->ClearPointerLock();
}
EventStateManager::sPointerLockedElement = nullptr;
EventStateManager::sPointerLockedDoc = nullptr;
nsContentUtils::DispatchEventOnlyToChrome(
doc, ToSupports(pointerLockedElement),
NS_LITERAL_STRING("MozDOMPointerLock:Exited"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
DispatchPointerLockChange(pointerLockedDoc);
}
void
nsIDocument::UnlockPointer(nsIDocument* aDoc)
{
nsDocument::UnlockPointer(aDoc);
}
NS_IMETHODIMP
nsDocument::MozExitPointerLock()
{
nsIDocument::MozExitPointerLock();
return NS_OK;
}
static void
RedispatchPendingPointerLockRequest(nsIDocument* aDocument)
NS_IMETHODIMP
nsDocument::GetMozPointerLockElement(nsIDOMElement** aPointerLockedElement)
{
if (!gPendingPointerLockRequest) {
return;
}
nsCOMPtr<nsIDocument> doc =
do_QueryReferent(gPendingPointerLockRequest->mDocument);
if (doc != aDocument) {
return;
}
nsCOMPtr<Element> elem =
do_QueryReferent(gPendingPointerLockRequest->mElement);
if (!elem || elem->GetUncomposedDoc() != aDocument) {
gPendingPointerLockRequest->Handled();
return;
Element* el = nsIDocument::GetMozPointerLockElement();
nsCOMPtr<nsIDOMElement> retval = do_QueryInterface(el);
retval.forget(aPointerLockedElement);
return NS_OK;
}
Element*
nsIDocument::GetMozPointerLockElement()
{
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (!pointerLockedElement) {
return nullptr;
}
// We have a request pending on the document which may previously be
// blocked for fullscreen change. Create a clone and re-dispatch it
// to guarantee that Run() method gets called again.
bool userInputOrChromeCaller =
gPendingPointerLockRequest->mUserInputOrChromeCaller;
gPendingPointerLockRequest->Handled();
gPendingPointerLockRequest =
new nsPointerLockPermissionRequest(elem, userInputOrChromeCaller);
NS_DispatchToMainThread(gPendingPointerLockRequest);
// Make sure pointer locked element is in the same document.
nsCOMPtr<nsIDocument> pointerLockedDoc =
do_QueryReferent(EventStateManager::sPointerLockedDoc);
if (pointerLockedDoc != this) {
return nullptr;
}
return pointerLockedElement;
}
nsresult
@ -12612,218 +12638,9 @@ nsDocument::OnAppThemeChanged()
}
}
void
nsDocument::RequestPointerLock(Element* aElement)
{
NS_ASSERTION(aElement,
"Must pass non-null element to nsDocument::RequestPointerLock");
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (aElement == pointerLockedElement) {
DispatchPointerLockChange(this);
return;
}
if (!ShouldLockPointer(aElement, pointerLockedElement)) {
DispatchPointerLockError(this);
return;
}
bool userInputOrChromeCaller = EventStateManager::IsHandlingUserInput() ||
nsContentUtils::IsCallerChrome();
gPendingPointerLockRequest =
new nsPointerLockPermissionRequest(aElement, userInputOrChromeCaller);
nsCOMPtr<nsIRunnable> r = gPendingPointerLockRequest.get();
NS_DispatchToMainThread(r);
}
bool
nsDocument::ShouldLockPointer(Element* aElement, Element* aCurrentLock,
bool aNoFocusCheck)
{
// Check if pointer lock pref is enabled
if (!Preferences::GetBool("full-screen-api.pointer-lock.enabled")) {
NS_WARNING("ShouldLockPointer(): Pointer Lock pref not enabled");
return false;
}
if (aCurrentLock && aCurrentLock->OwnerDoc() != aElement->OwnerDoc()) {
NS_WARNING("ShouldLockPointer(): Existing pointer lock element in a different document");
return false;
}
if (!aElement->IsInUncomposedDoc()) {
NS_WARNING("ShouldLockPointer(): Element without Document");
return false;
}
if (mSandboxFlags & SANDBOXED_POINTER_LOCK) {
NS_WARNING("ShouldLockPointer(): Document is sandboxed and doesn't allow pointer-lock");
return false;
}
// Check if the element is in a document with a docshell.
nsCOMPtr<nsIDocument> ownerDoc = aElement->OwnerDoc();
if (!ownerDoc->GetContainer()) {
return false;
}
nsCOMPtr<nsPIDOMWindowOuter> ownerWindow = ownerDoc->GetWindow();
if (!ownerWindow) {
return false;
}
nsCOMPtr<nsPIDOMWindowInner> ownerInnerWindow = ownerDoc->GetInnerWindow();
if (!ownerInnerWindow) {
return false;
}
if (ownerWindow->GetCurrentInnerWindow() != ownerInnerWindow) {
return false;
}
nsCOMPtr<nsPIDOMWindowOuter> top = ownerWindow->GetScriptableTop();
if (!top || !top->GetExtantDoc() || top->GetExtantDoc()->Hidden()) {
NS_WARNING("ShouldLockPointer(): Top document isn't visible.");
return false;
}
if (!aNoFocusCheck) {
mozilla::ErrorResult rv;
if (!top->GetExtantDoc()->HasFocus(rv)) {
NS_WARNING("ShouldLockPointer(): Top document isn't focused.");
return false;
}
}
return true;
}
bool
nsDocument::SetPointerLock(Element* aElement, int aCursorStyle)
{
MOZ_ASSERT(!aElement || aElement->OwnerDoc() == this,
"We should be either unlocking pointer (aElement is nullptr), "
"or locking pointer to an element in this document");
#ifdef DEBUG
if (!aElement) {
nsCOMPtr<nsIDocument> pointerLockedDoc =
do_QueryReferent(EventStateManager::sPointerLockedDoc);
MOZ_ASSERT(pointerLockedDoc == this);
}
#endif
nsIPresShell* shell = GetShell();
if (!shell) {
NS_WARNING("SetPointerLock(): No PresShell");
return false;
}
nsPresContext* presContext = shell->GetPresContext();
if (!presContext) {
NS_WARNING("SetPointerLock(): Unable to get PresContext");
return false;
}
nsCOMPtr<nsIWidget> widget;
nsIFrame* rootFrame = shell->GetRootFrame();
if (!NS_WARN_IF(!rootFrame)) {
widget = rootFrame->GetNearestWidget();
NS_WARN_IF_FALSE(widget, "SetPointerLock(): Unable to find widget "
"in shell->GetRootFrame()->GetNearestWidget();");
if (aElement && !widget) {
return false;
}
}
// Hide the cursor and set pointer lock for future mouse events
RefPtr<EventStateManager> esm = presContext->EventStateManager();
esm->SetCursor(aCursorStyle, nullptr, false,
0.0f, 0.0f, widget, true);
esm->SetPointerLock(widget, aElement);
return true;
}
void
nsDocument::UnlockPointer(nsIDocument* aDoc)
{
if (!EventStateManager::sIsPointerLocked) {
return;
}
nsCOMPtr<nsIDocument> pointerLockedDoc =
do_QueryReferent(EventStateManager::sPointerLockedDoc);
if (!pointerLockedDoc || (aDoc && aDoc != pointerLockedDoc)) {
return;
}
nsDocument* doc = static_cast<nsDocument*>(pointerLockedDoc.get());
if (!doc->SetPointerLock(nullptr, NS_STYLE_CURSOR_AUTO)) {
return;
}
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (pointerLockedElement) {
pointerLockedElement->ClearPointerLock();
}
EventStateManager::sPointerLockedElement = nullptr;
EventStateManager::sPointerLockedDoc = nullptr;
static_cast<nsDocument*>(pointerLockedDoc.get())->mAllowRelocking = !!aDoc;
gPendingPointerLockRequest = nullptr;
nsContentUtils::DispatchEventOnlyToChrome(
doc, ToSupports(pointerLockedElement),
NS_LITERAL_STRING("MozDOMPointerLock:Exited"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
DispatchPointerLockChange(pointerLockedDoc);
}
void
nsIDocument::UnlockPointer(nsIDocument* aDoc)
{
nsDocument::UnlockPointer(aDoc);
}
NS_IMETHODIMP
nsDocument::MozExitPointerLock()
{
nsIDocument::MozExitPointerLock();
return NS_OK;
}
NS_IMETHODIMP
nsDocument::GetMozPointerLockElement(nsIDOMElement** aPointerLockedElement)
{
Element* el = nsIDocument::GetMozPointerLockElement();
nsCOMPtr<nsIDOMElement> retval = do_QueryInterface(el);
retval.forget(aPointerLockedElement);
return NS_OK;
}
Element*
nsIDocument::GetMozPointerLockElement()
{
nsCOMPtr<Element> pointerLockedElement =
do_QueryReferent(EventStateManager::sPointerLockedElement);
if (!pointerLockedElement) {
return nullptr;
}
// Make sure pointer locked element is in the same document.
nsCOMPtr<nsIDocument> pointerLockedDoc =
do_QueryReferent(EventStateManager::sPointerLockedDoc);
if (pointerLockedDoc != this) {
return nullptr;
}
return pointerLockedElement;
}
void
nsDocument::XPCOMShutdown()
{
gPendingPointerLockRequest = nullptr;
sProcessingStack.reset();
}

View File

@ -1268,8 +1268,6 @@ public:
Element* GetFullscreenElement() override;
void RequestPointerLock(Element* aElement) override;
bool ShouldLockPointer(Element* aElement, Element* aCurrentLock,
bool aNoFocusCheck = false);
bool SetPointerLock(Element* aElement, int aCursorStyle);
static void UnlockPointer(nsIDocument* aDoc = nullptr);
@ -1651,11 +1649,7 @@ public:
// terminated instead of letting it finish at its own pace.
bool mParserAborted:1;
friend class nsPointerLockPermissionRequest;
friend class nsCallRequestFullScreen;
// When set, trying to lock the pointer doesn't require permission from the
// user.
bool mAllowRelocking:1;
// ScreenOrientation "pending promise" as described by
// http://www.w3.org/TR/screen-orientation/
@ -1674,10 +1668,6 @@ public:
// 'style-sheet-applicable-state-changed' notification.
bool mSSApplicableStateNotificationPending:1;
// The number of pointer lock requests which are cancelled by the user.
// The value is saturated to kPointerLockRequestLimit+1 = 3.
uint8_t mCancelledPointerLockRequests:2;
// Whether we have reported use counters for this document with Telemetry yet.
// Normally this is only done at document destruction time, but for image
// documents (SVG documents) that are not guaranteed to be destroyed, we

View File

@ -131,6 +131,13 @@ IsJavaMIME(const nsACString & aMIMEType)
nsPluginHost::GetSpecialType(aMIMEType) == nsPluginHost::eSpecialType_Java;
}
static bool
IsFlashMIME(const nsACString & aMIMEType)
{
return
nsPluginHost::GetSpecialType(aMIMEType) == nsPluginHost::eSpecialType_Flash;
}
static bool
InActiveDocument(nsIContent *aContent)
{
@ -465,11 +472,10 @@ private:
///
static bool
IsSuccessfulRequest(nsIRequest* aRequest)
IsSuccessfulRequest(nsIRequest* aRequest, nsresult* aStatus)
{
nsresult status;
nsresult rv = aRequest->GetStatus(&status);
if (NS_FAILED(rv) || NS_FAILED(status)) {
nsresult rv = aRequest->GetStatus(aStatus);
if (NS_FAILED(rv) || NS_FAILED(*aStatus)) {
return false;
}
@ -719,6 +725,7 @@ nsObjectLoadingContent::nsObjectLoadingContent()
, mInstantiating(false)
, mNetworkCreated(true)
, mActivated(false)
, mContentBlockingDisabled(false)
, mIsStopping(false)
, mIsLoading(false)
, mScriptRequested(false)
@ -1123,13 +1130,31 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
NS_ASSERTION(chan, "Why is our request not a channel?");
nsCOMPtr<nsIURI> uri;
nsresult status;
bool success = IsSuccessfulRequest(aRequest, &status);
if (IsSuccessfulRequest(aRequest)) {
chan->GetURI(getter_AddRefs(uri));
if (status == NS_ERROR_BLOCKED_URI) {
nsCOMPtr<nsIConsoleService> console(
do_GetService("@mozilla.org/consoleservice;1"));
if (console) {
nsCOMPtr<nsIURI> uri;
chan->GetURI(getter_AddRefs(uri));
nsAutoCString spec;
uri->GetSpec(spec);
nsString message = NS_LITERAL_STRING("Blocking ") +
NS_ConvertASCIItoUTF16(spec.get()) +
NS_LITERAL_STRING(" since it was found on an internal Firefox blocklist.");
console->LogStringMessage(message.get());
}
Telemetry::Accumulate(Telemetry::PLUGIN_BLOCKED_FOR_STABILITY, 1);
return NS_ERROR_FAILURE;
} else if (status == NS_ERROR_TRACKING_URI) {
return NS_ERROR_FAILURE;
} else {
mContentBlockingDisabled = true;
}
if (!uri) {
if (!success) {
LOG(("OBJLC [%p]: OnStartRequest: Request failed\n", this));
// If the request fails, we still call LoadObject() to handle fallback
// content and notifying of failure. (mChannelLoaded && !mChannel) indicates
@ -2280,32 +2305,6 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
allowLoad = CheckProcessPolicy(&contentPolicy);
}
// This needs to be reverted once the plugin stability experiment is over (see bug #1268120).
if (allowLoad && Preferences::GetBool(kPrefBlockURIs)) {
RefPtr<nsChannelClassifier> channelClassifier = new nsChannelClassifier();
nsCOMPtr<nsIURIClassifier> classifier = do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID);
if (classifier) {
nsAutoCString tables;
Preferences::GetCString("urlclassifier.blockedTable", &tables);
nsAutoCString results;
rv = classifier->ClassifyLocalWithTables(mURI, tables, results);
if (NS_SUCCEEDED(rv) && !results.IsEmpty()) {
nsAutoCString uri;
mURI->GetSpec(uri);
nsCOMPtr<nsIConsoleService> console(
do_GetService("@mozilla.org/consoleservice;1"));
if (console) {
nsString message = NS_LITERAL_STRING("Blocking ") +
NS_ConvertASCIItoUTF16(uri) +
NS_LITERAL_STRING(" since it was found on an internal Firefox blocklist.");
console->LogStringMessage(message.get());
}
Telemetry::Accumulate(Telemetry::PLUGIN_BLOCKED_FOR_STABILITY, 1);
allowLoad = false;
}
}
}
// Content policy implementations can mutate the DOM, check for re-entry
if (!mIsLoading) {
LOG(("OBJLC [%p]: We re-entered in content policy, leaving original load",
@ -2353,6 +2352,13 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
}
}
// Items resolved as Image/Document are no candidates for content blocking,
// as well as invalid plugins (they will not have the mContentType set).
if ((mType == eType_Null || mType == eType_Plugin) && ShouldBlockContent()) {
LOG(("OBJLC [%p]: Enable content blocking", this));
mType = eType_Loading;
}
// If we're a plugin but shouldn't start yet, load fallback with
// reason click-to-play instead. Items resolved as Image/Document
// will not be checked for previews, as well as invalid plugins
@ -3362,6 +3368,20 @@ static bool sPrefsInitialized;
static uint32_t sSessionTimeoutMinutes;
static uint32_t sPersistentTimeoutDays;
bool
nsObjectLoadingContent::ShouldBlockContent()
{
if (mContentBlockingDisabled)
return false;
if (!IsFlashMIME(mContentType) || !Preferences::GetBool(kPrefBlockURIs)) {
mContentBlockingDisabled = true;
return false;
}
return true;
}
bool
nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentType)
{

View File

@ -445,6 +445,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*/
nsresult CloseChannel();
/**
* If this object should be tested against blocking list.
*/
bool ShouldBlockContent();
/**
* If this object is allowed to play plugin content, or if it would display
* click-to-play instead.
@ -653,6 +658,9 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// activated by PlayPlugin(). (see ShouldPlay())
bool mActivated : 1;
// Whether content blocking is enabled or not for this object.
bool mContentBlockingDisabled : 1;
// Protects DoStopPlugin from reentry (bug 724781).
bool mIsStopping : 1;

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
#include "GLContextTypes.h"
#include "GLTypes.h"
#include "WebGLStrongTypes.h"
#include "WebGLTypes.h"
template <class T>
@ -56,66 +57,72 @@ public:
const uint32_t mWidth;
const uint32_t mHeight;
const uint32_t mDepth;
const bool mHasData;
const bool mIsSrcPremult;
protected:
TexUnpackBlob(const WebGLContext* webgl, uint32_t alignment, uint32_t rowLength,
uint32_t imageHeight, uint32_t width, uint32_t height, uint32_t depth,
bool hasData);
TexUnpackBlob(const WebGLContext* webgl, TexImageTarget target, uint32_t rowLength,
uint32_t width, uint32_t height, uint32_t depth, bool isSrcPremult);
public:
virtual ~TexUnpackBlob() { }
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const = 0;
protected:
bool ConvertIfNeeded(WebGLContext* webgl, const char* funcName, const void* srcBytes,
uint32_t srcStride, uint8_t srcBPP, WebGLTexelFormat srcFormat,
const webgl::DriverUnpackInfo* dstDUI,
const void** const out_bytes,
UniqueBuffer* const out_anchoredBuffer) const;
static void OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
gl::OriginPos* const out_dst);
public:
virtual bool HasData() const { return true; }
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const = 0;
};
class TexUnpackBytes : public TexUnpackBlob
class TexUnpackBytes final : public TexUnpackBlob
{
public:
const void* const mBytes;
TexUnpackBytes(const WebGLContext* webgl, uint32_t width, uint32_t height,
uint32_t depth, const void* bytes);
TexUnpackBytes(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
uint32_t height, uint32_t depth, const void* bytes);
virtual bool HasData() const override { return bool(mBytes); }
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const override;
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const override;
};
class TexUnpackImage : public TexUnpackBlob
class TexUnpackImage final : public TexUnpackBlob
{
public:
const RefPtr<layers::Image> mImage;
const bool mIsAlphaPremult;
TexUnpackImage(const WebGLContext* webgl, uint32_t imageHeight, uint32_t width,
uint32_t height, uint32_t depth, const RefPtr<layers::Image>& image,
TexUnpackImage(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
uint32_t height, uint32_t depth, layers::Image* image,
bool isAlphaPremult);
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const override;
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const override;
};
class TexUnpackSurface : public TexUnpackBlob
class TexUnpackSurface final : public TexUnpackBlob
{
public:
const RefPtr<gfx::SourceSurface> mSurf;
const bool mIsAlphaPremult;
const RefPtr<gfx::DataSourceSurface> mSurf;
TexUnpackSurface(const WebGLContext* webgl, uint32_t imageHeight, uint32_t width,
uint32_t height, uint32_t depth, gfx::SourceSurface* surf,
TexUnpackSurface(const WebGLContext* webgl, TexImageTarget target, uint32_t width,
uint32_t height, uint32_t depth, gfx::DataSourceSurface* surf,
bool isAlphaPremult);
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
@ -123,19 +130,6 @@ public:
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_error) const override;
protected:
static bool ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackInfo* dui,
gfx::DataSourceSurface* surf, bool isSurfAlphaPremult,
UniqueBuffer* const out_convertedBuffer,
uint8_t* const out_convertedAlignment,
bool* const out_wasTrivial, bool* const out_outOfMemory);
static bool UploadDataSurface(bool isSubImage, WebGLContext* webgl,
TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, gfx::DataSourceSurface* surf,
bool isSurfAlphaPremult, GLenum* const out_glError);
};
} // namespace webgl

View File

@ -288,6 +288,7 @@ public:
void ErrorInvalidEnumInfo(const char* info, const char* funcName,
GLenum enumValue);
void ErrorOutOfMemory(const char* fmt = 0, ...);
void ErrorImplementationBug(const char* fmt = 0, ...);
const char* ErrorName(GLenum error);
@ -963,10 +964,6 @@ protected:
WebGLTexture** const out_texture,
WebGLTexture::ImageInfo** const out_imageInfo);
bool GetUnpackValuesForImage(const char* funcName, uint32_t srcImageWidth,
uint32_t srcImageHeight, uint32_t* const out_rowLength,
uint32_t* const out_imageHeight);
bool ValidateUnpackInfo(const char* funcName, GLenum format, GLenum type,
webgl::PackingInfo* const out);
@ -1334,24 +1331,8 @@ protected:
WebGLTexelFormat dstFormat, bool dstPremultiplied,
size_t dstTexelSize);
public:
nsLayoutUtils::SurfaceFromElementResult
SurfaceFromElement(dom::Element* elem)
{
uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR;
//////
if (mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
if (!mPixelStore_PremultiplyAlpha)
flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
RefPtr<gfx::DrawTarget> idealDrawTarget = nullptr; // Don't care for now.
return nsLayoutUtils::SurfaceFromElement(elem, flags, idealDrawTarget);
}
protected:
// Returns false if `object` is null or not valid.
template<class ObjectType>
bool ValidateObject(const char* info, ObjectType* object);
@ -1629,6 +1610,7 @@ public:
friend class ScopedUnpackReset;
friend class webgl::TexUnpackBlob;
friend class webgl::TexUnpackBytes;
friend class webgl::TexUnpackImage;
friend class webgl::TexUnpackSurface;
friend class WebGLTexture;
friend class WebGLFBAttachPoint;

View File

@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContextUtils.h"
#include "WebGLContext.h"
#include "GLContext.h"
@ -23,7 +24,6 @@
#include "WebGLProgram.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
#include "WebGLContextUtils.h"
namespace mozilla {
@ -207,6 +207,22 @@ WebGLContext::ErrorOutOfMemory(const char* fmt, ...)
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
}
void
WebGLContext::ErrorImplementationBug(const char* fmt, ...)
{
const nsPrintfCString warning("Implementation bug, please file at %s! %s",
"https://bugzilla.mozilla.org/", fmt);
va_list va;
va_start(va, fmt);
GenerateWarning(warning.BeginReading(), va);
va_end(va);
MOZ_ASSERT(false, "WebGLContext::ErrorImplementationBug");
NS_ERROR("WebGLContext::ErrorImplementationBug");
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
}
const char*
WebGLContext::ErrorName(GLenum error)
{

View File

@ -412,6 +412,9 @@ TexImageTargetForTargetAndFace(TexTarget target, uint8_t face)
already_AddRefed<mozilla::layers::Image>
ImageFromVideo(dom::HTMLVideoElement* elem);
bool
IsTarget3D(TexImageTarget target);
GLenum
DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLsizei width, GLsizei height,

View File

@ -178,11 +178,12 @@ WebGLContext::ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
}
static UniquePtr<webgl::TexUnpackBlob>
BlobFromView(WebGLContext* webgl, const char* funcName, uint32_t width, uint32_t height,
uint32_t depth, const webgl::PackingInfo& pi,
BlobFromView(WebGLContext* webgl, const char* funcName, TexImageTarget target,
uint32_t width, uint32_t height, uint32_t depth,
const webgl::PackingInfo& pi,
const dom::Nullable<dom::ArrayBufferView>& maybeView)
{
const void* bytes = nullptr;
const uint8_t* bytes = nullptr;
uint32_t byteCount = 0;
if (!maybeView.IsNull()) {
@ -203,8 +204,8 @@ BlobFromView(WebGLContext* webgl, const char* funcName, uint32_t width, uint32_t
}
}
UniquePtr<webgl::TexUnpackBlob> blob(new webgl::TexUnpackBytes(webgl, width, height,
depth, bytes));
UniquePtr<webgl::TexUnpackBlob> blob(new webgl::TexUnpackBytes(webgl, target, width,
height, depth, bytes));
//////
@ -268,7 +269,7 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
return;
const auto blob = BlobFromView(mContext, funcName, width, height, depth, pi,
const auto blob = BlobFromView(mContext, funcName, target, width, height, depth, pi,
maybeView);
if (!blob)
return;
@ -280,7 +281,7 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
////////////////////////////////////////
// ImageData
static already_AddRefed<gfx::SourceSurface>
static already_AddRefed<gfx::DataSourceSurface>
FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
dom::ImageData* imageData, dom::Uint8ClampedArray* scopedArr)
{
@ -299,7 +300,7 @@ FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
uint8_t* wrappableData = (uint8_t*)data;
RefPtr<gfx::SourceSurface> surf =
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateWrappingDataSourceSurface(wrappableData,
stride,
size,
@ -312,35 +313,6 @@ FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
return surf.forget();
}
bool
WebGLContext::GetUnpackValuesForImage(const char* funcName, uint32_t srcImageWidth,
uint32_t srcImageHeight,
uint32_t* const out_rowLength,
uint32_t* const out_imageHeight)
{
uint32_t rowLength = mPixelStore_UnpackRowLength;
if (!rowLength) {
rowLength = srcImageWidth;
} else if (rowLength != srcImageWidth) {
ErrorInvalidOperation("%s: UNPACK_ROW_LENGTH, if set, must be == width of"
" object.");
return false;
}
uint32_t imageHeight = mPixelStore_UnpackImageHeight;
if (!imageHeight) {
imageHeight = srcImageHeight;
} else if (imageHeight > srcImageHeight) {
ErrorInvalidOperation("%s: UNPACK_IMAGE_HEIGHT, if set, must be <= height of"
" object");
return false;
}
*out_rowLength = rowLength;
*out_imageHeight = imageHeight;
return true;
}
void
WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset,
@ -362,27 +334,20 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
const uint32_t height = imageData->Height();
const uint32_t depth = 1;
uint32_t rowLength, imageHeight;
if (!mContext->GetUnpackValuesForImage(funcName, imageData->Width(),
imageData->Height(), &rowLength, &imageHeight))
{
return;
}
dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(
nsContentUtils::RootingCx());
const RefPtr<gfx::SourceSurface> surf = FromImageData(mContext, funcName, unpackType,
imageData, &scopedArr);
dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(nsContentUtils::RootingCx());
const RefPtr<gfx::DataSourceSurface> surf = FromImageData(mContext, funcName,
unpackType, imageData,
&scopedArr);
if (!surf)
return;
// WhatWG "HTML Living Standard" (30 October 2015):
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
// non-premultiplied alpha values."
const bool surfIsAlphaPremult = false;
const bool isAlphaPremult = false;
const webgl::TexUnpackSurface blob(mContext, imageHeight, width, height, depth, surf,
surfIsAlphaPremult);
const webgl::TexUnpackSurface blob(mContext, target, width, height, depth, surf,
isAlphaPremult);
const uint32_t fullRows = imageData->Height();
const uint32_t tailPixels = 0;
@ -407,7 +372,21 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
return;
auto sfer = mContext->SurfaceFromElement(elem);
//////
uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE |
nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR;
if (mContext->mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
if (!mContext->mPixelStore_PremultiplyAlpha)
flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
RefPtr<gfx::DrawTarget> idealDrawTarget = nullptr; // Don't care for now.
auto sfer = nsLayoutUtils::SurfaceFromElement(elem, flags, idealDrawTarget);
//////
uint32_t elemWidth = 0;
uint32_t elemHeight = 0;
@ -418,23 +397,25 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
elemHeight = layersImage->GetSize().height;
}
gfx::SourceSurface* surf = nullptr;
RefPtr<gfx::DataSourceSurface> dataSurf;
if (!layersImage && sfer.GetSourceSurface()) {
surf = sfer.GetSourceSurface();
const auto surf = sfer.GetSourceSurface();
elemWidth = surf->GetSize().width;
elemHeight = surf->GetSize().height;
// WARNING: OSX can lose our MakeCurrent here.
dataSurf = surf->GetDataSurface();
}
//////
// Eventually, these will be args.
const uint32_t width = elemWidth;
const uint32_t height = elemHeight;
const uint32_t depth = 1;
// While it's counter-intuitive, the shape of the SFEResult API means that we should
// try to pull out a surface first, and then, if we do pull out a surface, check
// CORS/write-only/etc..
if (!layersImage && !surf) {
webgl::TexUnpackBytes blob(mContext, width, height, depth, nullptr);
if (!layersImage && !dataSurf) {
const webgl::TexUnpackBytes blob(mContext, target, width, height, depth, nullptr);
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, pi, &blob);
return;
@ -442,6 +423,10 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
//////
// While it's counter-intuitive, the shape of the SFEResult API means that we should
// try to pull out a surface first, and then, if we do pull out a surface, check
// CORS/write-only/etc..
if (!sfer.mCORSUsed) {
auto& srcPrincipal = sfer.mPrincipal;
nsIPrincipal* dstPrincipal = mContext->GetCanvas()->NodePrincipal();
@ -468,23 +453,16 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
//////
// Ok, we're good!
uint32_t rowLength, imageHeight;
if (!mContext->GetUnpackValuesForImage(funcName, elemWidth, elemHeight, &rowLength,
&imageHeight))
{
return;
}
UniquePtr<const webgl::TexUnpackBlob> blob;
const bool isAlphaPremult = sfer.mIsPremultiplied;
if (layersImage) {
blob.reset(new webgl::TexUnpackImage(mContext, imageHeight, width, height, depth,
blob.reset(new webgl::TexUnpackImage(mContext, target, width, height, depth,
layersImage, isAlphaPremult));
} else {
MOZ_ASSERT(surf);
blob.reset(new webgl::TexUnpackSurface(mContext, imageHeight, width, height,
depth, surf, isAlphaPremult));
MOZ_ASSERT(dataSurf);
blob.reset(new webgl::TexUnpackSurface(mContext, target, width, height, depth,
dataSurf, isAlphaPremult));
}
const uint32_t fullRows = elemHeight;
@ -836,8 +814,8 @@ DoTexStorage(gl::GLContext* gl, TexTarget target, GLsizei levels, GLenum sizedFo
return errorScope.GetError();
}
static bool
Is3D(TexImageTarget target)
bool
IsTarget3D(TexImageTarget target)
{
switch (target.get()) {
case LOCAL_GL_TEXTURE_2D:
@ -867,7 +845,7 @@ DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
gl::GLContext::LocalErrorScope errorScope(*gl);
if (Is3D(target)) {
if (IsTarget3D(target)) {
gl->fTexImage3D(target.get(), level, dui->internalFormat, width, height, depth,
border, dui->unpackFormat, dui->unpackType, data);
} else {
@ -886,7 +864,7 @@ DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffs
{
gl::GLContext::LocalErrorScope errorScope(*gl);
if (Is3D(target)) {
if (IsTarget3D(target)) {
gl->fTexSubImage3D(target.get(), level, xOffset, yOffset, zOffset, width, height,
depth, pi.format, pi.type, data);
} else {
@ -908,7 +886,7 @@ DoCompressedTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
gl::GLContext::LocalErrorScope errorScope(*gl);
if (Is3D(target)) {
if (IsTarget3D(target)) {
gl->fCompressedTexImage3D(target.get(), level, internalFormat, width, height,
depth, border, dataSize, data);
} else {
@ -928,7 +906,7 @@ DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level,
{
gl::GLContext::LocalErrorScope errorScope(*gl);
if (Is3D(target)) {
if (IsTarget3D(target)) {
gl->fCompressedTexSubImage3D(target.get(), level, xOffset, yOffset, zOffset,
width, height, depth, sizedUnpackFormat, dataSize,
data);
@ -950,7 +928,7 @@ DoCopyTexImage2D(gl::GLContext* gl, TexImageTarget target, GLint level,
gl::GLContext::LocalErrorScope errorScope(*gl);
MOZ_ASSERT(!Is3D(target));
MOZ_ASSERT(!IsTarget3D(target));
gl->fCopyTexImage2D(target.get(), level, internalFormat, x, y, width, height,
border);
@ -964,7 +942,7 @@ DoCopyTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint x
{
gl::GLContext::LocalErrorScope errorScope(*gl);
if (Is3D(target)) {
if (IsTarget3D(target)) {
gl->fCopyTexSubImage3D(target.get(), level, xOffset, yOffset, zOffset, x, y,
width, height);
} else {
@ -1263,7 +1241,7 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
if (!mContext->IsWebGL2() && dstFormat->d) {
if (target != LOCAL_GL_TEXTURE_2D ||
blob->mHasData ||
blob->HasData() ||
level != 0)
{
mContext->ErrorInvalidOperation("%s: With format %s, this function may only"
@ -1284,7 +1262,7 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
// slower.
const ImageInfo newImageInfo(dstUsage, blob->mWidth, blob->mHeight, blob->mDepth,
blob->mHasData);
blob->HasData());
const bool isSubImage = false;
const bool needsRespec = (imageInfo->mWidth != newImageInfo.mWidth ||

View File

@ -123,7 +123,7 @@ function testColorConversions() {
testColorConversion("RGBA32", "GRAY8"),
testColorConversion("RGBA32", "YUV444P"),
testColorConversion("RGBA32", "YUV422P"),
testColorConversion("RGBA32", "YUV420P"),
testColorConversion("RGBA32", "YUV420P", 2),
testColorConversion("RGBA32", "YUV420SP_NV12"),
testColorConversion("RGBA32", "YUV420SP_NV21"),
testColorConversion("RGBA32", "HSV", 0.01),
@ -136,10 +136,10 @@ function testColorConversions() {
testColorConversion("BGRA32", "BGR24"),
testColorConversion("BGRA32", "GRAY8"),
testColorConversion("BGRA32", "YUV444P", 3),
testColorConversion("BGRA32", "YUV422P"),
testColorConversion("BGRA32", "YUV420P"),
testColorConversion("BGRA32", "YUV420SP_NV12"),
testColorConversion("BGRA32", "YUV420SP_NV21"),
testColorConversion("BGRA32", "YUV422P", 2),
testColorConversion("BGRA32", "YUV420P", 2),
testColorConversion("BGRA32", "YUV420SP_NV12", 2),
testColorConversion("BGRA32", "YUV420SP_NV21", 2),
testColorConversion("BGRA32", "HSV", 0.01),
testColorConversion("BGRA32", "Lab", 0.5),
@ -178,7 +178,7 @@ function testColorConversions() {
testColorConversion("YUV444P", "BGR24"),
testColorConversion("YUV444P", "GRAY8"),
testColorConversion("YUV444P", "YUV444P"),
testColorConversion("YUV444P", "YUV422P", 3),
testColorConversion("YUV444P", "YUV422P", 4),
testColorConversion("YUV444P", "YUV420P", 3),
testColorConversion("YUV444P", "YUV420SP_NV12", 3),
testColorConversion("YUV444P", "YUV420SP_NV21", 3),
@ -187,7 +187,7 @@ function testColorConversions() {
// From YUV422P
testColorConversion("YUV422P", "RGBA32"),
testColorConversion("YUV422P", "BGRA32"),
testColorConversion("YUV422P", "BGRA32", 2),
testColorConversion("YUV422P", "RGB24"),
testColorConversion("YUV422P", "BGR24"),
testColorConversion("YUV422P", "GRAY8"),
@ -200,13 +200,13 @@ function testColorConversions() {
testColorConversion("YUV422P", "Lab", 0.01),
// From YUV420P
testColorConversion("YUV420P", "RGBA32"),
testColorConversion("YUV420P", "BGRA32"),
testColorConversion("YUV420P", "RGBA32", 2),
testColorConversion("YUV420P", "BGRA32", 2),
testColorConversion("YUV420P", "RGB24"),
testColorConversion("YUV420P", "BGR24"),
testColorConversion("YUV420P", "GRAY8"),
testColorConversion("YUV420P", "YUV444P", 3),
testColorConversion("YUV420P", "YUV422P"),
testColorConversion("YUV420P", "YUV422P", 1),
testColorConversion("YUV420P", "YUV420P"),
testColorConversion("YUV420P", "YUV420SP_NV12"),
testColorConversion("YUV420P", "YUV420SP_NV21"),
@ -215,12 +215,12 @@ function testColorConversions() {
// From NV12
testColorConversion("YUV420SP_NV12", "RGBA32"),
testColorConversion("YUV420SP_NV12", "BGRA32"),
testColorConversion("YUV420SP_NV12", "BGRA32", 2),
testColorConversion("YUV420SP_NV12", "RGB24"),
testColorConversion("YUV420SP_NV12", "BGR24"),
testColorConversion("YUV420SP_NV12", "GRAY8"),
testColorConversion("YUV420SP_NV12", "YUV444P", 3),
testColorConversion("YUV420SP_NV12", "YUV422P"),
testColorConversion("YUV420SP_NV12", "YUV422P", 1),
testColorConversion("YUV420SP_NV12", "YUV420P"),
testColorConversion("YUV420SP_NV12", "YUV420SP_NV12"),
testColorConversion("YUV420SP_NV12", "YUV420SP_NV21"),
@ -229,12 +229,12 @@ function testColorConversions() {
// From NV21
testColorConversion("YUV420SP_NV21", "RGBA32"),
testColorConversion("YUV420SP_NV21", "BGRA32"),
testColorConversion("YUV420SP_NV21", "BGRA32", 2),
testColorConversion("YUV420SP_NV21", "RGB24"),
testColorConversion("YUV420SP_NV21", "BGR24"),
testColorConversion("YUV420SP_NV21", "GRAY8"),
testColorConversion("YUV420SP_NV21", "YUV444P", 3),
testColorConversion("YUV420SP_NV21", "YUV422P"),
testColorConversion("YUV420SP_NV21", "YUV422P", 1),
testColorConversion("YUV420SP_NV21", "YUV420P"),
testColorConversion("YUV420SP_NV21", "YUV420SP_NV12"),
testColorConversion("YUV420SP_NV21", "YUV420SP_NV21"),

View File

@ -10,6 +10,7 @@
#include "mozilla/Telemetry.h"
#include "nsAutoPtr.h"
#include "nsISettingsService.h"
#include "nsGeolocation.h"
#include "nsDOMClassInfoID.h"
@ -31,6 +32,7 @@
#include "mozilla/dom/Event.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/SettingChangeNotificationBinding.h"
#include "mozilla/dom/WakeLock.h"
class nsIPrincipal;
@ -56,6 +58,9 @@ class nsIPrincipal;
// that a window can make.
#define MAX_GEO_REQUESTS_PER_WINDOW 1500
// The settings key.
#define GEO_SETTINGS_ENABLED "geolocation.enabled"
using mozilla::Unused; // <snicker>
using namespace mozilla;
using namespace mozilla::dom;
@ -141,6 +146,53 @@ CreatePositionOptionsCopy(const PositionOptions& aOptions)
return geoOptions.forget();
}
class GeolocationSettingsCallback : public nsISettingsServiceCallback
{
virtual ~GeolocationSettingsCallback() {
MOZ_COUNT_DTOR(GeolocationSettingsCallback);
}
public:
NS_DECL_ISUPPORTS
GeolocationSettingsCallback() {
MOZ_COUNT_CTOR(GeolocationSettingsCallback);
}
NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult) override
{
MOZ_ASSERT(NS_IsMainThread());
// The geolocation is enabled by default:
bool value = true;
if (aResult.isBoolean()) {
value = aResult.toBoolean();
}
MozSettingValue(value);
return NS_OK;
}
NS_IMETHOD HandleError(const nsAString& aName) override
{
NS_WARNING("Unable to get value for '" GEO_SETTINGS_ENABLED "'");
// Default it's enabled:
MozSettingValue(true);
return NS_OK;
}
void MozSettingValue(const bool aValue)
{
RefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
if (gs) {
gs->HandleMozsettingValue(aValue);
}
}
};
NS_IMPL_ISUPPORTS(GeolocationSettingsCallback, nsISettingsServiceCallback)
class RequestPromptEvent : public Runnable
{
public:
@ -326,14 +378,12 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGeolocationRequest)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocationRequest)
NS_IMPL_CYCLE_COLLECTION(nsGeolocationRequest, mCallback, mErrorCallback, mLocator)
void
nsGeolocationRequest::Notify()
{
SetTimeoutTimer();
NotifyErrorAndShutdown(nsIDOMGeoPositionError::TIMEOUT);
}
void
nsGeolocationRequest::NotifyErrorAndShutdown(uint16_t aErrorCode)
{
@ -505,7 +555,6 @@ nsGeolocationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
@ -593,7 +642,6 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
MOZ_ASSERT(mShutdown || mIsWatchPositionRequest,
"non-shutdown getCurrentPosition request after callback!");
}
nsIPrincipal*
nsGeolocationRequest::GetPrincipal()
{
@ -610,7 +658,6 @@ nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition)
NS_DispatchToMainThread(ev);
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationRequest::NotifyError(uint16_t aErrorCode)
{
@ -652,7 +699,6 @@ nsGeolocationRequest::TimerCallbackHolder::Notify(nsITimer*)
RefPtr<nsGeolocationRequest> request(mRequest);
request->Notify();
}
return NS_OK;
}
@ -671,6 +717,7 @@ NS_IMPL_RELEASE(nsGeolocationService)
static bool sGeoEnabled = true;
static bool sGeoInitPending = true;
static int32_t sProviderTimeout = 6000; // Time, in milliseconds, to wait for the location provider to spin up.
nsresult nsGeolocationService::Init()
@ -683,9 +730,28 @@ nsresult nsGeolocationService::Init()
}
if (XRE_IsContentProcess()) {
sGeoInitPending = false;
return NS_OK;
}
// check if the geolocation service is enable from settings
nsCOMPtr<nsISettingsService> settings =
do_GetService("@mozilla.org/settingsService;1");
if (settings) {
nsCOMPtr<nsISettingsServiceLock> settingsLock;
nsresult rv = settings->CreateLock(nullptr, getter_AddRefs(settingsLock));
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<GeolocationSettingsCallback> callback = new GeolocationSettingsCallback();
rv = settingsLock->Get(GEO_SETTINGS_ENABLED, callback);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// If we cannot obtain the settings service, we continue
// assuming that the geolocation is enabled:
sGeoInitPending = false;
}
// geolocation service can be enabled -> now register observer
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
@ -693,6 +759,7 @@ nsresult nsGeolocationService::Init()
}
obs->AddObserver(this, "xpcom-shutdown", false);
obs->AddObserver(this, "mozsettings-changed", false);
#ifdef MOZ_WIDGET_ANDROID
mProvider = new AndroidLocationProvider();
@ -745,6 +812,47 @@ nsGeolocationService::~nsGeolocationService()
{
}
void
nsGeolocationService::HandleMozsettingChanged(nsISupports* aSubject)
{
// The string that we're interested in will be a JSON string that looks like:
// {"key":"gelocation.enabled","value":true}
RootedDictionary<SettingChangeNotification> setting(nsContentUtils::RootingCx());
if (!WrappedJSToDictionary(aSubject, setting)) {
return;
}
if (!setting.mKey.EqualsASCII(GEO_SETTINGS_ENABLED)) {
return;
}
if (!setting.mValue.isBoolean()) {
return;
}
HandleMozsettingValue(setting.mValue.toBoolean());
}
void
nsGeolocationService::HandleMozsettingValue(const bool aValue)
{
if (!aValue) {
// turn things off
StopDevice();
Update(nullptr);
mLastPosition.position = nullptr;
sGeoEnabled = false;
} else {
sGeoEnabled = true;
}
if (sGeoInitPending) {
sGeoInitPending = false;
for (uint32_t i = 0, length = mGeolocators.Length(); i < length; ++i) {
mGeolocators[i]->ServiceReady();
}
}
}
NS_IMETHODIMP
nsGeolocationService::Observe(nsISupports* aSubject,
const char* aTopic,
@ -754,6 +862,7 @@ nsGeolocationService::Observe(nsISupports* aSubject,
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "xpcom-shutdown");
obs->RemoveObserver(this, "mozsettings-changed");
}
for (uint32_t i = 0; i< mGeolocators.Length(); i++) {
@ -764,6 +873,11 @@ nsGeolocationService::Observe(nsISupports* aSubject,
return NS_OK;
}
if (!strcmp("mozsettings-changed", aTopic)) {
HandleMozsettingChanged(aSubject);
return NS_OK;
}
if (!strcmp("timer-callback", aTopic)) {
// decide if we can close down the service.
for (uint32_t i = 0; i< mGeolocators.Length(); i++)
@ -787,21 +901,17 @@ nsGeolocationService::Update(nsIDOMGeoPosition *aSomewhere)
if (aSomewhere) {
SetCachedPosition(aSomewhere);
}
for (uint32_t i = 0; i< mGeolocators.Length(); i++) {
mGeolocators[i]->Update(aSomewhere);
}
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationService::NotifyError(uint16_t aErrorCode)
{
for (uint32_t i = 0; i < mGeolocators.Length(); i++) {
mGeolocators[i]->NotifyError(aErrorCode);
}
return NS_OK;
}
@ -821,7 +931,7 @@ nsGeolocationService::GetCachedPosition()
nsresult
nsGeolocationService::StartDevice(nsIPrincipal *aPrincipal)
{
if (!sGeoEnabled) {
if (!sGeoEnabled || sGeoInitPending) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -872,6 +982,7 @@ nsGeolocationService::StopDisconnectTimer()
}
}
void
nsGeolocationService::SetDisconnectTimer()
{
@ -894,7 +1005,6 @@ nsGeolocationService::HighAccuracyRequested()
return true;
}
}
return false;
}
@ -908,11 +1018,17 @@ nsGeolocationService::UpdateAccuracy(bool aForceHigh)
if (cpc->IsAlive()) {
cpc->SendSetGeolocationHigherAccuracy(highRequired);
}
return;
}
mProvider->SetHighAccuracy(!mHigherAccuracy && highRequired);
if (!mHigherAccuracy && highRequired) {
mProvider->SetHighAccuracy(true);
}
if (mHigherAccuracy && !highRequired) {
mProvider->SetHighAccuracy(false);
}
mHigherAccuracy = highRequired;
}
@ -924,7 +1040,6 @@ nsGeolocationService::StopDevice()
if (XRE_IsContentProcess()) {
ContentChild* cpc = ContentChild::GetSingleton();
cpc->SendRemoveGeolocationListener();
return; // bail early
}
@ -960,10 +1075,8 @@ nsGeolocationService::GetGeolocationService()
if (NS_FAILED(result->Init())) {
return nullptr;
}
ClearOnShutdown(&nsGeolocationService::sService);
nsGeolocationService::sService = result;
return result.forget();
}
@ -1066,21 +1179,21 @@ Geolocation::Init(nsPIDOMWindowInner* aContentDom)
if (mService) {
mService->AddLocator(this);
}
return NS_OK;
}
bool
Geolocation::ContainsRequest(nsGeolocationRequest* aRequest)
{
if (aRequest->IsWatch() && mWatchingCallbacks.Contains(aRequest)) {
if (aRequest->IsWatch()) {
if (mWatchingCallbacks.Contains(aRequest)) {
return true;
}
} else {
if (mPendingCallbacks.Contains(aRequest)) {
return true;
}
}
if (mPendingCallbacks.Contains(aRequest)) {
return true;
}
return false;
}
@ -1104,27 +1217,23 @@ Geolocation::HandleEvent(nsIDOMEvent* aEvent)
MOZ_ASSERT(XRE_IsContentProcess());
ContentChild* cpc = ContentChild::GetSingleton();
if (!info.lockingProcesses().Contains(cpc->GetID())) {
cpc->SendRemoveGeolocationListener();
mService->StopDisconnectTimer();
}
} else {
mService->SetDisconnectTimer();
return NS_OK;
}
mService->SetDisconnectTimer();
// We will unconditionally allow all the requests in the callbacks
// because if a request is put into either of these two callbacks,
// it means that it has been allowed before.
// That's why when we resume them, we unconditionally allow them again.
for (uint32_t i = 0, length = mWatchingCallbacks.Length(); i < length; ++i) {
mWatchingCallbacks[i]->Allow(JS::UndefinedHandleValue);
}
for (uint32_t i = 0, length = mPendingCallbacks.Length(); i < length; ++i) {
mPendingCallbacks[i]->Allow(JS::UndefinedHandleValue);
// We will unconditionally allow all the requests in the callbacks
// because if a request is put into either of these two callbacks,
// it means that it has been allowed before.
// That's why when we resume them, we unconditionally allow them again.
for (uint32_t i = 0, length = mWatchingCallbacks.Length(); i < length; ++i) {
mWatchingCallbacks[i]->Allow(JS::UndefinedHandleValue);
}
for (uint32_t i = 0, length = mPendingCallbacks.Length(); i < length; ++i) {
mPendingCallbacks[i]->Allow(JS::UndefinedHandleValue);
}
}
return NS_OK;
@ -1225,10 +1334,8 @@ Geolocation::Update(nsIDOMGeoPosition *aSomewhere)
for (uint32_t i = 0; i < mWatchingCallbacks.Length(); i++) {
mWatchingCallbacks[i]->Update(aSomewhere);
}
return NS_OK;
}
NS_IMETHODIMP
Geolocation::NotifyError(uint16_t aErrorCode)
{
@ -1236,7 +1343,6 @@ Geolocation::NotifyError(uint16_t aErrorCode)
Shutdown();
return NS_OK;
}
mozilla::Telemetry::Accumulate(mozilla::Telemetry::GEOLOCATION_ERROR, true);
for (uint32_t i = mPendingCallbacks.Length(); i > 0; i--) {
@ -1260,7 +1366,6 @@ Geolocation::IsAlreadyCleared(nsGeolocationRequest* aRequest)
return true;
}
}
return false;
}
@ -1272,7 +1377,6 @@ Geolocation::ClearPendingRequest(nsGeolocationRequest* aRequest)
this->ClearWatch(aRequest->WatchId());
return true;
}
return false;
}
@ -1335,6 +1439,11 @@ Geolocation::GetCurrentPosition(GeoPositionCallback& callback,
return NS_ERROR_FAILURE;
}
if (sGeoInitPending) {
mPendingRequests.AppendElement(request);
return NS_OK;
}
return GetCurrentPositionReady(request);
}
@ -1424,6 +1533,11 @@ Geolocation::WatchPosition(GeoPositionCallback& aCallback,
return NS_ERROR_FAILURE;
}
if (sGeoInitPending) {
mPendingRequests.AppendElement(request);
return NS_OK;
}
return WatchPositionReady(request);
}

View File

@ -72,6 +72,9 @@ public:
nsresult Init();
void HandleMozsettingChanged(nsISupports* aSubject);
void HandleMozsettingValue(const bool aValue);
// Management of the Geolocation objects
void AddLocator(mozilla::dom::Geolocation* locator);
void RemoveLocator(mozilla::dom::Geolocation* locator);

View File

@ -154,13 +154,14 @@ function checkInputURL()
sendString("ttp://mozilla.org");
checkValidApplies(element);
for (var i=0; i<13; ++i) {
for (var i=0; i<10; ++i) {
synthesizeKey("VK_BACK_SPACE", {});
checkValidApplies(element);
}
synthesizeKey("VK_BACK_SPACE", {});
for (var i=0; i<4; ++i) {
// "http://" is now invalid
for (var i=0; i<7; ++i) {
checkInvalidApplies(element);
synthesizeKey("VK_BACK_SPACE", {});
}

View File

@ -8,10 +8,6 @@
#include <gtk/gtk.h>
#endif
#ifdef MOZ_WIDGET_QT
#include "nsQAppInstance.h"
#endif
#include "ContentChild.h"
#include "BlobChild.h"
@ -619,11 +615,6 @@ ContentChild::Init(MessageLoop* aIOLoop,
}
#endif
#ifdef MOZ_WIDGET_QT
// sigh, seriously
nsQAppInstance::AddRef();
#endif
#ifdef MOZ_X11
// Do this after initializing GDK, or GDK will install its own handler.
XRE_InstallX11ErrorHandler();
@ -1041,14 +1032,6 @@ ContentChild::InitXPCOM()
global->SetInitialProcessData(data);
}
// Loading the ServiceWorker configuration.
ServiceWorkerConfiguration configuration;
SendGetServiceWorkerConfiguration(&configuration);
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
swm->LoadRegistrations(configuration.serviceWorkerRegistrations());
InitOnContentProcessCreated();
}
@ -2642,6 +2625,15 @@ ContentChild::RecvAppInit()
return true;
}
bool
ContentChild::RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig)
{
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
swm->LoadRegistrations(aConfig.serviceWorkerRegistrations());
return true;
}
bool
ContentChild::RecvLastPrivateDocShellDestroyed()
{

View File

@ -457,6 +457,9 @@ public:
virtual bool RecvAppInit() override;
virtual bool
RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig) override;
virtual bool RecvLastPrivateDocShellDestroyed() override;
virtual bool RecvVolumes(InfallibleTArray<VolumeInfo>&& aVolumes) override;

View File

@ -2511,6 +2511,14 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
Unused << SendSetAudioSessionData(id, sessionName, iconPath);
}
#endif
RefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
MOZ_ASSERT(swr);
nsTArray<ServiceWorkerRegistrationData> registrations;
swr->GetRegistrations(registrations);
Unused << SendInitServiceWorkers(ServiceWorkerConfiguration(registrations));
}
bool
@ -5485,18 +5493,6 @@ ContentParent::PermissionManagerRelease(const ContentParentId& aCpId,
return false;
}
bool
ContentParent::RecvGetServiceWorkerConfiguration(ServiceWorkerConfiguration* aConfig)
{
MOZ_ASSERT(XRE_IsParentProcess());
RefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
MOZ_ASSERT(swr);
swr->GetRegistrations(aConfig->serviceWorkerRegistrations());
return true;
}
bool
ContentParent::RecvProfile(const nsCString& aProfile)
{

View File

@ -1135,9 +1135,6 @@ private:
virtual bool RecvUpdateDropEffect(const uint32_t& aDragAction,
const uint32_t& aDropEffect) override;
virtual bool
RecvGetServiceWorkerConfiguration(ServiceWorkerConfiguration* aConfig) override;
virtual bool RecvProfile(const nsCString& aProfile) override;
virtual bool RecvGetGraphicsDeviceInitData(DeviceInitData* aOut) override;

View File

@ -526,6 +526,11 @@ child:
nsCString ID, nsCString vendor);
async AppInit();
/**
* Send ServiceWorkerRegistrationData to child process.
*/
async InitServiceWorkers(ServiceWorkerConfiguration aConfig);
// Notify child that last-pb-context-exited notification was observed
async LastPrivateDocShellDestroyed();
@ -1084,12 +1089,6 @@ parent:
async PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal,
TabId tabId);
/**
* Send ServiceWorkerRegistrationData to child process.
*/
sync GetServiceWorkerConfiguration()
returns (ServiceWorkerConfiguration aConfig);
async Profile(nsCString aProfile);
/**

View File

@ -168,7 +168,7 @@ if CONFIG['OS_ARCH'] != 'WINNT':
DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG['BIN_SUFFIX']
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gonk', 'qt'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gonk'):
DEFINES['MOZ_ENABLE_FREETYPE'] = True
if CONFIG['MOZ_TOOLKIT_SEARCH']:

View File

@ -78,6 +78,15 @@ FullscreenDeniedNotDescendant=Request for fullscreen was denied because requesti
FullscreenDeniedNotFocusedTab=Request for fullscreen was denied because requesting element is not in the currently focused tab.
RemovedFullscreenElement=Exited fullscreen because fullscreen element was removed from document.
FocusedWindowedPluginWhileFullscreen=Exited fullscreen because windowed plugin was focused.
PointerLockDeniedDisabled=Request for pointer lock was denied because Pointer Lock API is disabled by user preference.
PointerLockDeniedInUse=Request for pointer lock was denied because the pointer is currently controlled by a different document.
PointerLockDeniedNotInDocument=Request for pointer lock was denied because the requesting element is not in a document.
PointerLockDeniedSandboxed=Request for pointer lock was denied because Pointer Lock API is restricted via sandbox.
PointerLockDeniedHidden=Request for pointer lock was denied because the document is not visible.
PointerLockDeniedNotFocused=Request for pointer lock was denied because the document is not focused.
PointerLockDeniedMovedDocument=Request for pointer lock was denied because the requesting element has moved document.
PointerLockDeniedNotInputDriven=Request for pointer lock was denied because Element.requestPointerLock() was not called from inside a short running user-generated event handler, and the document is not in full screen.
PointerLockDeniedFailedToLock=Request for pointer lock was denied because the browser failed to lock the pointer.
HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesnt implement nsIWritablePropertyBag2.
ResponseTypeSyncXHRWarning=Use of XMLHttpRequests responseType attribute is no longer supported in the synchronous mode in window context.

View File

@ -160,6 +160,6 @@ TEST_DIRS += [
'imptests',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'cocoa', 'windows', 'android', 'qt'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'cocoa', 'windows', 'android'):
TEST_DIRS += ['plugins/test']

View File

@ -77,10 +77,6 @@ else:
SOURCES += [
'nsPluginNativeWindowGtk.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt':
UNIFIED_SOURCES += [
'nsPluginNativeWindowQt.cpp',
]
else:
UNIFIED_SOURCES += [
'nsPluginNativeWindow.cpp',

View File

@ -1811,7 +1811,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
return NPERR_GENERIC_ERROR;
#endif
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
case NPNVnetscapeWindow: {
if (!npp || !npp->ndata)
return NPERR_INVALID_INSTANCE_ERROR;
@ -1860,10 +1860,6 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
*((NPNToolkitType*)result) = NPNVGtk2;
#endif
#ifdef MOZ_WIDGET_QT
/* Fake toolkit so flash plugin works */
*((NPNToolkitType*)result) = NPNVGtk2;
#endif
if (*(NPNToolkitType*)result)
return NPERR_NO_ERROR;
@ -1873,11 +1869,6 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
case NPNVSupportsXEmbedBool: {
#ifdef MOZ_WIDGET_GTK
*(NPBool*)result = true;
#elif defined(MOZ_WIDGET_QT)
// Desktop Flash fail to initialize if browser does not support NPNVSupportsXEmbedBool
// even when wmode!=windowed, lets return fake support
fprintf(stderr, "Fake support for XEmbed plugins in Qt port\n");
*(NPBool*)result = true;
#else
*(NPBool*)result = false;
#endif
@ -1898,7 +1889,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
case NPNVSupportsWindowless: {
#if defined(XP_WIN) || defined(XP_MACOSX) || \
(defined(MOZ_X11) && (defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)))
(defined(MOZ_X11) && defined(MOZ_WIDGET_GTK))
*(NPBool*)result = true;
#else
*(NPBool*)result = false;

View File

@ -763,7 +763,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
}
return NS_OK;
#elif (defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)) && defined(MOZ_X11)
#elif defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)
// X11 window managers want the toplevel window for WM_TRANSIENT_FOR.
nsIWidget* win = mPluginFrame->GetNearestWidget();
if (!win)
@ -2616,8 +2616,6 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
}
#ifdef MOZ_WIDGET_GTK
Window root = GDK_ROOT_WINDOW();
#elif defined(MOZ_WIDGET_QT)
Window root = RootWindowOfScreen(DefaultScreenOfDisplay(mozilla::DefaultXDisplay()));
#else
Window root = None; // Could XQueryTree, but this is not important.
#endif

View File

@ -46,12 +46,8 @@ class PuppetWidget;
using mozilla::widget::PuppetWidget;
#ifdef MOZ_X11
#ifdef MOZ_WIDGET_QT
#include "gfxQtNativeRenderer.h"
#else
#include "gfxXlibNativeRenderer.h"
#endif
#endif
class nsPluginInstanceOwner final : public nsIPluginInstanceOwner
, public nsIDOMEventListener
@ -395,12 +391,7 @@ private:
int mLastMouseDownButtonType;
#ifdef MOZ_X11
class Renderer
#if defined(MOZ_WIDGET_QT)
: public gfxQtNativeRenderer
#else
: public gfxXlibNativeRenderer
#endif
class Renderer : public gfxXlibNativeRenderer
{
public:
Renderer(NPWindow* aWindow, nsPluginInstanceOwner* aInstanceOwner,

View File

@ -1,89 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* This file is the Qt implementation of plugin native window.
*/
#include "nsDebug.h"
#include "nsPluginNativeWindow.h"
#include "npapi.h"
/**
* Qt implementation of plugin window
*/
class nsPluginNativeWindowQt : public nsPluginNativeWindow
{
public:
nsPluginNativeWindowQt();
virtual ~nsPluginNativeWindowQt();
virtual nsresult CallSetWindow(RefPtr<nsNPAPIPluginInstance> &aPluginInstance);
private:
NPSetWindowCallbackStruct mWsInfo;
};
nsPluginNativeWindowQt::nsPluginNativeWindowQt() : nsPluginNativeWindow()
{
//Initialize member variables
#ifdef DEBUG
fprintf(stderr,"\n\n\nCreating plugin native window %p\n\n\n", (void *) this);
#endif
window = nullptr;
x = 0;
y = 0;
width = 0;
height = 0;
memset(&clipRect, 0, sizeof(clipRect));
ws_info = &mWsInfo;
type = NPWindowTypeWindow;
mWsInfo.type = 0;
#if defined(MOZ_X11)
mWsInfo.display = nullptr;
mWsInfo.visual = nullptr;
mWsInfo.colormap = 0;
mWsInfo.depth = 0;
#endif
}
nsPluginNativeWindowQt::~nsPluginNativeWindowQt()
{
#ifdef DEBUG
fprintf(stderr,"\n\n\nDestoying plugin native window %p\n\n\n", (void *) this);
#endif
}
nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow **aPluginNativeWindow)
{
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
*aPluginNativeWindow = new nsPluginNativeWindowQt();
return NS_OK;
}
nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
{
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
nsPluginNativeWindowQt *p = (nsPluginNativeWindowQt *)aPluginNativeWindow;
delete p;
return NS_OK;
}
nsresult nsPluginNativeWindowQt::CallSetWindow(RefPtr<nsNPAPIPluginInstance> &aPluginInstance)
{
if (aPluginInstance) {
if (type == NPWindowTypeWindow) {
return NS_ERROR_FAILURE;
} // NPWindowTypeWindow
aPluginInstance->SetWindow(this);
}
else if (mPluginInstance)
mPluginInstance->SetWindow(nullptr);
SetPluginInstance(aPluginInstance);
return NS_OK;
}

View File

@ -841,7 +841,7 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
if (owner) {
NPWindow* window = nullptr;
owner->GetWindow(window);
#if (MOZ_WIDGET_GTK == 2) || defined(MOZ_WIDGET_QT)
#if (MOZ_WIDGET_GTK == 2)
// Should call GetPluginPort() here.
// This part is copied from nsPluginInstanceOwner::GetPluginPort().
nsCOMPtr<nsIWidget> widget;

View File

@ -1,16 +0,0 @@
/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef PluginHelperQt_h_
#define PluginHelperQt_h_
class PluginHelperQt
{
public:
static bool AnswerProcessSomeEvents();
};
#endif // PluginHelperQt_h_

View File

@ -54,9 +54,6 @@ using namespace std;
#include <gdk/gdk.h>
#include "gtk2xtbin.h"
#elif defined(MOZ_WIDGET_QT)
#undef KeyPress
#undef KeyRelease
#elif defined(OS_WIN)
#include <windows.h>
@ -1386,8 +1383,6 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
#elif defined(ANDROID)
// TODO: Need Android impl
#elif defined(MOZ_WIDGET_QT)
// TODO: Need QT-nonX impl
#elif defined(MOZ_WIDGET_UIKIT)
// Don't care
#else

View File

@ -287,9 +287,6 @@ PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(NativeWindowHandle*
#elif defined(ANDROID)
// TODO: Need Android impl
int id;
#elif defined(MOZ_WIDGET_QT)
// TODO: Need Qt non X impl
int id;
#else
#warning Implement me
#endif

View File

@ -102,7 +102,7 @@ struct NPRemoteWindow
typedef HWND NativeWindowHandle;
#elif defined(MOZ_X11)
typedef XID NativeWindowHandle;
#elif defined(XP_DARWIN) || defined(ANDROID) || defined(MOZ_WIDGET_QT)
#elif defined(XP_DARWIN) || defined(ANDROID)
typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
#else
#error Need NativeWindowHandle for this platform

View File

@ -4,12 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef MOZ_WIDGET_QT
#include <QtCore/QTimer>
#include "nsQAppInstance.h"
#include "NestedLoopTimer.h"
#endif
#include "mozilla/plugins/PluginModuleChild.h"
/* This must occur *after* plugins/PluginModuleChild.h to avoid typedefs conflicts. */
@ -73,12 +67,6 @@ namespace {
PluginModuleChild* gChromeInstance = nullptr;
} // namespace
#ifdef MOZ_WIDGET_QT
typedef void (*_gtk_init_fn)(int argc, char **argv);
static _gtk_init_fn s_gtk_init = nullptr;
static PRLibrary *sGtkLib = nullptr;
#endif
#ifdef XP_WIN
// Hooking CreateFileW for protected-mode magic
static WindowsDllInterceptor sKernel32Intercept;
@ -131,8 +119,6 @@ PluginModuleChild::PluginModuleChild(bool aIsChrome)
, mGetEntryPointsFunc(0)
#elif defined(MOZ_WIDGET_GTK)
, mNestedLoopTimerId(0)
#elif defined(MOZ_WIDGET_QT)
, mNestedLoopTimerObject(0)
#endif
#ifdef OS_WIN
, mNestedEventHook(nullptr)
@ -325,6 +311,7 @@ PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
}
#if defined(MOZ_WIDGET_GTK)
typedef void (*GObjectDisposeFn)(GObject*);
typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*);
typedef void (*GtkPlugEmbeddedFn)(GtkPlug*);
@ -548,26 +535,6 @@ PluginModuleChild::ExitedCxxStack()
g_source_remove(mNestedLoopTimerId);
mNestedLoopTimerId = 0;
}
#elif defined (MOZ_WIDGET_QT)
void
PluginModuleChild::EnteredCxxStack()
{
MOZ_ASSERT(mNestedLoopTimerObject == nullptr,
"previous timer not descheduled");
mNestedLoopTimerObject = new NestedLoopTimer(this);
QTimer::singleShot(kNestedLoopDetectorIntervalMs,
mNestedLoopTimerObject, SLOT(timeOut()));
}
void
PluginModuleChild::ExitedCxxStack()
{
MOZ_ASSERT(mNestedLoopTimerObject != nullptr,
"nested loop timeout not scheduled");
delete mNestedLoopTimerObject;
mNestedLoopTimerObject = nullptr;
}
#endif
@ -628,19 +595,6 @@ PluginModuleChild::InitGraphics()
real_gtk_plug_embedded = *embedded;
*embedded = wrap_gtk_plug_embedded;
#elif defined(MOZ_WIDGET_QT)
nsQAppInstance::AddRef();
// Work around plugins that don't interact well without gtk initialized
// see bug 566845
#if defined(MOZ_X11)
if (!sGtkLib)
sGtkLib = PR_LoadLibrary("libgtk-x11-2.0.so.0");
#endif
if (sGtkLib) {
s_gtk_init = (_gtk_init_fn)PR_FindFunctionSymbol(sGtkLib, "gtk_init");
if (s_gtk_init)
s_gtk_init(0, 0);
}
#else
// may not be necessary on all platforms
#endif
@ -654,15 +608,6 @@ PluginModuleChild::InitGraphics()
void
PluginModuleChild::DeinitGraphics()
{
#ifdef MOZ_WIDGET_QT
nsQAppInstance::Release();
if (sGtkLib) {
PR_UnloadLibrary(sGtkLib);
sGtkLib = nullptr;
s_gtk_init = nullptr;
}
#endif
#if defined(MOZ_X11) && defined(NS_FREE_PERMANENT_DATA)
// We free some data off of XDisplay close hooks, ensure they're
// run. Closing the display is pretty scary, so we only do it to
@ -1149,7 +1094,7 @@ _getvalue(NPP aNPP,
switch (aVariable) {
// Copied from nsNPAPIPlugin.cpp
case NPNVToolkit:
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
#if defined(MOZ_WIDGET_GTK)
*static_cast<NPNToolkitType*>(aValue) = NPNVGtk2;
return NPERR_NO_ERROR;
#endif

View File

@ -52,11 +52,6 @@ class PCrashReporterChild;
namespace plugins {
#ifdef MOZ_WIDGET_QT
class NestedLoopTimer;
static const int kNestedLoopDetectorIntervalMs = 90;
#endif
class PluginInstanceChild;
class PluginModuleChild : public PPluginModuleChild
@ -261,10 +256,6 @@ private:
static gboolean DetectNestedEventLoop(gpointer data);
static gboolean ProcessBrowserEvents(gpointer data);
virtual void EnteredCxxStack() override;
virtual void ExitedCxxStack() override;
#elif defined(MOZ_WIDGET_QT)
virtual void EnteredCxxStack() override;
virtual void ExitedCxxStack() override;
#endif
@ -328,8 +319,6 @@ private:
// MessagePumpForUI.
int mTopLoopDepth;
# endif
#elif defined (MOZ_WIDGET_QT)
NestedLoopTimer *mNestedLoopTimerObject;
#endif
public: // called by PluginInstanceChild

View File

@ -4,10 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef MOZ_WIDGET_QT
#include "PluginHelperQt.h"
#endif
#include "mozilla/plugins/PluginModuleParent.h"
#include "base/process_util.h"
@ -2859,18 +2855,7 @@ PluginModuleParent::ContentsScaleFactorChanged(NPP instance, double aContentsSca
}
#endif // #if defined(XP_MACOSX)
#if defined(MOZ_WIDGET_QT)
bool
PluginModuleParent::AnswerProcessSomeEvents()
{
PLUGIN_LOG_DEBUG(("Spinning mini nested loop ..."));
PluginHelperQt::AnswerProcessSomeEvents();
PLUGIN_LOG_DEBUG(("... quitting mini nested loop"));
return true;
}
#elif defined(XP_MACOSX)
#if defined(XP_MACOSX)
bool
PluginModuleParent::AnswerProcessSomeEvents()
{

View File

@ -90,17 +90,10 @@ PresentationConnection::Init()
return false;
}
nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(getter_AddRefs(loadGroup));
if(NS_WARN_IF(!loadGroup)) {
return false;
}
rv = loadGroup->AddRequest(this, nullptr);
rv = AddIntoLoadGroup();
if(NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
mWeakLoadGroup = do_GetWeakReference(loadGroup);
return true;
}
@ -117,11 +110,8 @@ PresentationConnection::Shutdown()
nsresult rv = service->UnregisterSessionListener(mId, mRole);
NS_WARN_IF(NS_FAILED(rv));
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
if (loadGroup) {
loadGroup->RemoveRequest(this, nullptr, NS_OK);
mWeakLoadGroup = nullptr;
}
rv = RemoveFromLoadGroup();
NS_WARN_IF(NS_FAILED(rv));
}
/* virtual */ void
@ -176,20 +166,31 @@ PresentationConnection::Send(const nsAString& aData,
void
PresentationConnection::Close(ErrorResult& aRv)
{
// It only works when the state is CONNECTED.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
// It only works when the state is CONNECTED or CONNECTING.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected &&
mState != PresentationConnectionState::Connecting)) {
return;
}
// TODO Bug 1210340 - Support close semantics.
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
return;
}
NS_WARN_IF(NS_FAILED(
service->CloseSession(mId,
mRole,
nsIPresentationService::CLOSED_REASON_CLOSED)));
}
void
PresentationConnection::Terminate(ErrorResult& aRv)
{
// It only works when the state is CONNECTED.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
// It only works when the state is CONNECTED or CONNECTING.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected &&
mState != PresentationConnectionState::Connecting)) {
return;
}
@ -276,7 +277,9 @@ PresentationConnection::ProcessStateChanged(nsresult aReason)
CopyUTF8toUTF16(message, errorMsg);
}
return DispatchConnectionClosedEvent(reason, errorMsg);
NS_WARN_IF(NS_FAILED(DispatchConnectionClosedEvent(reason, errorMsg)));
return RemoveFromLoadGroup();
}
case PresentationConnectionState::Terminated: {
nsCOMPtr<nsIPresentationService> service =
@ -292,7 +295,9 @@ PresentationConnection::ProcessStateChanged(nsresult aReason)
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("terminate"), false);
return asyncDispatcher->PostDOMEvent();
NS_WARN_IF(NS_FAILED(asyncDispatcher->PostDOMEvent()));
return RemoveFromLoadGroup();
}
default:
MOZ_CRASH("Unknown presentation session state.");
@ -475,3 +480,42 @@ PresentationConnection::SetLoadFlags(nsLoadFlags aLoadFlags)
{
return NS_OK;
}
nsresult
PresentationConnection::AddIntoLoadGroup()
{
// Avoid adding to loadgroup multiple times
if (mWeakLoadGroup) {
return NS_OK;
}
nsCOMPtr<nsILoadGroup> loadGroup;
nsresult rv = GetLoadGroup(getter_AddRefs(loadGroup));
if(NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = loadGroup->AddRequest(this, nullptr);
if(NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mWeakLoadGroup = do_GetWeakReference(loadGroup);
return NS_OK;
}
nsresult
PresentationConnection::RemoveFromLoadGroup()
{
if (!mWeakLoadGroup) {
return NS_OK;
}
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
if (loadGroup) {
mWeakLoadGroup = nullptr;
return loadGroup->RemoveRequest(this, nullptr, NS_OK);
}
return NS_OK;
}

View File

@ -79,6 +79,10 @@ private:
nsresult ProcessConnectionWentAway();
nsresult AddIntoLoadGroup();
nsresult RemoveFromLoadGroup();
nsString mId;
uint8_t mRole;
PresentationConnectionState mState;

View File

@ -105,9 +105,6 @@ function testSendMessage() {
});
}
// Currently, PresentationSessionInfo::NotifyTransportClosed only set the state to
// STATE_CLOSED. So, when sender call connection.terminate(), we can only get STATE_CLOSED
// at receiver side. This should be fixed in bu 1210340.
function testConnectionClosed() {
return new Promise(function(aResolve, aReject) {
info('Receiver: --- testConnectionClosed ---');
@ -116,7 +113,7 @@ function testConnectionClosed() {
is(connection.state, "closed", "Receiver: Connection should be closed.");
aResolve();
};
command('forward-command', JSON.stringify({ name: 'ready-to-terminate' }));
command('forward-command', JSON.stringify({ name: 'ready-to-close' }));
});
}

View File

@ -121,15 +121,15 @@ function testIncomingMessage() {
});
}
function testTerminateConnection() {
function testCloseConnection() {
return new Promise(function(aResolve, aReject) {
connection.onterminate = function() {
connection.onterminate = null;
is(connection.state, "terminated", "Connection should be terminated.");
connection.onclose = function() {
connection.onclose = null;
is(connection.state, "closed", "Connection should be closed.");
aResolve();
};
connection.terminate();
connection.close();
});
}
@ -139,7 +139,7 @@ then(testConnectionAvailableSameOriginInnerIframe).
then(testConnectionUnavailableDiffOriginInnerIframe).
then(testConnectionListSameObject).
then(testIncomingMessage).
then(testTerminateConnection).
then(testCloseConnection).
then(finish);
</script>

View File

@ -177,17 +177,17 @@ function testIncomingMessage() {
});
}
function testTerminateConnection() {
function testCloseConnection() {
return new Promise(function(aResolve, aReject) {
info('Sender: --- testTerminateConnection ---');
connection.onterminate = function() {
connection.onterminate = null;
is(connection.state, "terminated", "Sender: Connection should be terminated.");
info('Sender: --- testCloseConnection ---');
connection.onclose = function() {
connection.onclose = null;
is(connection.state, "closed", "Sender: Connection should be closed.");
aResolve();
};
gScript.addMessageListener('ready-to-terminate', function onReadyToTerminate() {
gScript.removeMessageListener('ready-to-terminate', onReadyToTerminate);
connection.terminate();
gScript.addMessageListener('ready-to-close', function onReadyToClose() {
gScript.removeMessageListener('ready-to-close', onReadyToClose);
connection.close();
});
});
}
@ -208,7 +208,7 @@ function runTests() {
.then(testStartConnection)
.then(testSendMessage)
.then(testIncomingMessage)
.then(testTerminateConnection);
.then(testCloseConnection);
}
SimpleTest.waitForExplicitFinish();

View File

@ -184,17 +184,17 @@ function testIncomingMessage() {
});
}
function testTerminateConnection() {
function testCloseConnection() {
return new Promise(function(aResolve, aReject) {
info('Sender: --- testTerminateConnection ---');
connection.onterminate = function() {
connection.onterminate = null;
is(connection.state, "terminated", "Sender: Connection should be terminated.");
info('Sender: --- testCloseConnection ---');
connection.onclose = function() {
connection.onclose = null;
is(connection.state, "closed", "Sender: Connection should be closed.");
aResolve();
};
gScript.addMessageListener('ready-to-terminate', function onReadyToTerminate() {
gScript.removeMessageListener('ready-to-terminate', onReadyToTerminate);
connection.terminate();
gScript.addMessageListener('ready-to-close', function onReadyToClose() {
gScript.removeMessageListener('ready-to-close', onReadyToClose);
connection.close();
});
});
}
@ -215,7 +215,7 @@ function runTests() {
.then(testStartConnection)
.then(testSendMessage)
.then(testIncomingMessage)
.then(testTerminateConnection);
.then(testCloseConnection);
}
SimpleTest.waitForExplicitFinish();

View File

@ -157,20 +157,20 @@ function testIncomingMessage() {
});
}
function testTerminateConnection() {
function testCloseConnection() {
return new Promise(function(aResolve, aReject) {
frameScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
frameScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
info("The data transport is closed. " + aReason);
});
connection.onterminate = function() {
connection.onterminate = null;
is(connection.state, "terminated", "Connection should be terminated.");
connection.onclose = function() {
connection.onclose = null;
is(connection.state, "closed", "Connection should be closed.");
aResolve();
};
connection.terminate();
connection.close();
});
}
@ -192,7 +192,7 @@ function runTests() {
then(testStartConnection).
then(testSend).
then(testIncomingMessage).
then(testTerminateConnection).
then(testCloseConnection).
then(teardown);
}

View File

@ -151,20 +151,20 @@ function testIncomingMessage() {
});
}
function testTerminateConnection() {
function testCloseConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
info("The data transport is closed. " + aReason);
});
connection.onterminate = function() {
connection.onterminate = null;
is(connection.state, "terminated", "Connection should be terminated.");
connection.onclose = function() {
connection.onclose = null;
is(connection.state, "closed", "Connection should be closed.");
aResolve();
};
connection.terminate();
connection.close();
});
}
@ -185,7 +185,7 @@ function runTests() {
then(testStartConnection).
then(testSend).
then(testIncomingMessage).
then(testTerminateConnection).
then(testCloseConnection).
then(teardown);
}

View File

@ -101,20 +101,20 @@ function testStartConnection() {
});
}
function testTerminateConnection() {
function testCloseConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
info("The data transport is closed. " + aReason);
});
connection.onterminate = function() {
connection.onterminate = null;
is(connection.state, "terminated", "Connection should be terminated.");
connection.onclose = function() {
connection.onclose = null;
is(connection.state, "closed", "Connection should be closed.");
aResolve();
};
connection.terminate();
connection.close();
});
}
@ -134,7 +134,7 @@ function runTests() {
testSetup().
then(testStartConnection).
then(testTerminateConnection).
then(testCloseConnection).
then(teardown);
}

View File

@ -648,7 +648,7 @@ nsCSPContext::SetRequestContext(nsIDOMDocument* aDOMDocument,
doc->SetHasCSP(true);
}
else {
NS_WARNING("No Document in SetRequestContext; can not query loadgroup; sending reports may fail.");
CSPCONTEXTLOG(("No Document in SetRequestContext; can not query loadgroup; sending reports may fail."));
mLoadingPrincipal = aPrincipal;
mLoadingPrincipal->GetURI(getter_AddRefs(mSelfURI));
// if no document is available, then it also does not make sense to queue console messages

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