зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c. a=merge
This commit is contained in:
Коммит
93534bdf01
7
CLOBBER
7
CLOBBER
|
@ -22,9 +22,4 @@
|
||||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||||
# don't change CLOBBER for WebIDL changes any more.
|
# don't change CLOBBER for WebIDL changes any more.
|
||||||
|
|
||||||
Bug 1105308 - Cleanup BluetoothUtils.{cpp,h}
|
Bug 1066383 - Clobber needed due to build system not reliably picking up an IDL removal.
|
||||||
|
|
||||||
This patch set moves some files around and requires a rebuild
|
|
||||||
of the build system's dependency information.
|
|
||||||
|
|
||||||
Merge day clobber
|
|
||||||
|
|
|
@ -401,6 +401,8 @@
|
||||||
@BINPATH@/components/nsSidebar.js
|
@BINPATH@/components/nsSidebar.js
|
||||||
@BINPATH@/components/nsAsyncShutdown.manifest
|
@BINPATH@/components/nsAsyncShutdown.manifest
|
||||||
@BINPATH@/components/nsAsyncShutdown.js
|
@BINPATH@/components/nsAsyncShutdown.js
|
||||||
|
@BINPATH@/components/htmlMenuBuilder.js
|
||||||
|
@BINPATH@/components/htmlMenuBuilder.manifest
|
||||||
|
|
||||||
; WiFi, NetworkManager, NetworkStats
|
; WiFi, NetworkManager, NetworkStats
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
|
|
@ -259,10 +259,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
|
||||||
"nsICrashReporter");
|
"nsICrashReporter");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {
|
XPCOMUtils.defineLazyGetter(this, "PageMenuParent", function() {
|
||||||
let tmp = {};
|
let tmp = {};
|
||||||
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
|
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
|
||||||
return new tmp.PageMenu();
|
return new tmp.PageMenuParent();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,6 +43,11 @@ XPCOMUtils.defineLazyGetter(this, "SimpleServiceDiscovery", function() {
|
||||||
});
|
});
|
||||||
return ssdp;
|
return ssdp;
|
||||||
});
|
});
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "PageMenuChild", function() {
|
||||||
|
let tmp = {};
|
||||||
|
Cu.import("resource://gre/modules/PageMenu.jsm", tmp);
|
||||||
|
return new tmp.PageMenuChild();
|
||||||
|
});
|
||||||
|
|
||||||
// TabChildGlobal
|
// TabChildGlobal
|
||||||
var global = this;
|
var global = this;
|
||||||
|
@ -102,6 +107,10 @@ addMessageListener("SecondScreen:tab-mirror", function(message) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addMessageListener("ContextMenu:DoCustomCommand", function(message) {
|
||||||
|
PageMenuChild.executeMenu(message.data);
|
||||||
|
});
|
||||||
|
|
||||||
addEventListener("DOMFormHasPassword", function(event) {
|
addEventListener("DOMFormHasPassword", function(event) {
|
||||||
InsecurePasswordUtils.checkForInsecurePasswords(event.target);
|
InsecurePasswordUtils.checkForInsecurePasswords(event.target);
|
||||||
LoginManagerContent.onFormPassword(event);
|
LoginManagerContent.onFormPassword(event);
|
||||||
|
@ -148,7 +157,8 @@ let handleContentContextMenu = function (event) {
|
||||||
InlineSpellCheckerContent.initContextMenu(event, editFlags, this);
|
InlineSpellCheckerContent.initContextMenu(event, editFlags, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSyncMessage("contextmenu", { editFlags, spellInfo, addonInfo }, { event, popupNode: event.target });
|
let customMenuItems = PageMenuChild.build(event.target);
|
||||||
|
sendSyncMessage("contextmenu", { editFlags, spellInfo, customMenuItems, addonInfo }, { event, popupNode: event.target });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Break out to the parent window and pass the add-on info along
|
// Break out to the parent window and pass the add-on info along
|
||||||
|
|
|
@ -24,10 +24,15 @@ nsContextMenu.prototype = {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.hasPageMenu = false;
|
this.hasPageMenu = false;
|
||||||
// FIXME (bug 1047751) - The page menu is disabled in e10s.
|
if (!aIsShift) {
|
||||||
if (!aIsShift && !this.isRemote) {
|
if (this.isRemote) {
|
||||||
this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(this.target,
|
this.hasPageMenu =
|
||||||
aXulMenu);
|
PageMenuParent.addToPopup(gContextMenuContentData.customMenuItems,
|
||||||
|
this.browser, aXulMenu);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.hasPageMenu = PageMenuParent.buildAndAddToPopup(this.target, aXulMenu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isFrameImage = document.getElementById("isFrameImage");
|
this.isFrameImage = document.getElementById("isFrameImage");
|
||||||
|
@ -1766,7 +1771,7 @@ nsContextMenu.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is a page menu item:
|
// Check if this is a page menu item:
|
||||||
if (e.target.hasAttribute(PageMenu.GENERATEDITEMID_ATTR)) {
|
if (e.target.hasAttribute(PageMenuParent.GENERATEDITEMID_ATTR)) {
|
||||||
this._telemetryClickID = "custom-page-item";
|
this._telemetryClickID = "custom-page-item";
|
||||||
} else {
|
} else {
|
||||||
this._telemetryClickID = (e.target.id || "unknown").replace(/^context-/i, "");
|
this._telemetryClickID = (e.target.id || "unknown").replace(/^context-/i, "");
|
||||||
|
|
|
@ -3175,6 +3175,7 @@
|
||||||
browser: browser,
|
browser: browser,
|
||||||
editFlags: aMessage.data.editFlags,
|
editFlags: aMessage.data.editFlags,
|
||||||
spellInfo: spellInfo,
|
spellInfo: spellInfo,
|
||||||
|
customMenuItems: aMessage.data.customMenuItems,
|
||||||
addonInfo: aMessage.data.addonInfo };
|
addonInfo: aMessage.data.addonInfo };
|
||||||
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
||||||
let event = gContextMenuContentData.event;
|
let event = gContextMenuContentData.event;
|
||||||
|
|
|
@ -72,6 +72,7 @@ support-files =
|
||||||
redirect_bug623155.sjs
|
redirect_bug623155.sjs
|
||||||
searchSuggestionEngine.sjs
|
searchSuggestionEngine.sjs
|
||||||
searchSuggestionEngine.xml
|
searchSuggestionEngine.xml
|
||||||
|
subtst_contextmenu.html
|
||||||
test-mixedcontent-securityerrors.html
|
test-mixedcontent-securityerrors.html
|
||||||
test_bug435035.html
|
test_bug435035.html
|
||||||
test_bug462673.html
|
test_bug462673.html
|
||||||
|
@ -486,4 +487,5 @@ skip-if = e10s # bug 1100687 - test directly manipulates content (content.docume
|
||||||
[browser_mcb_redirect.js]
|
[browser_mcb_redirect.js]
|
||||||
skip-if = e10s # bug 1084504 - [e10s] Mixed content detection does not take redirection into account
|
skip-if = e10s # bug 1084504 - [e10s] Mixed content detection does not take redirection into account
|
||||||
[browser_windowactivation.js]
|
[browser_windowactivation.js]
|
||||||
|
[browser_contextmenu_childprocess.js]
|
||||||
[browser_bug963945.js]
|
[browser_bug963945.js]
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
const gBaseURL = "https://example.com/browser/browser/base/content/test/general/";
|
||||||
|
|
||||||
|
add_task(function *() {
|
||||||
|
let tab = gBrowser.addTab();
|
||||||
|
let browser = gBrowser.getBrowserForTab(tab);
|
||||||
|
|
||||||
|
gBrowser.selectedTab = tab;
|
||||||
|
yield promiseTabLoadEvent(tab, gBaseURL + "subtst_contextmenu.html");
|
||||||
|
|
||||||
|
let popupShownPromise = promiseWaitForEvent(window, "popupshown", true);
|
||||||
|
|
||||||
|
// Get the point of the element with the page menu (test-pagemenu) and
|
||||||
|
// synthesize a right mouse click there.
|
||||||
|
let eventDetails = { type : "contextmenu", button : 2 };
|
||||||
|
let rect = browser.contentWindow.document.getElementById("test-pagemenu").getBoundingClientRect();
|
||||||
|
EventUtils.synthesizeMouse(browser, rect.x + rect.width / 2, rect.y + rect.height / 2, eventDetails, window);
|
||||||
|
|
||||||
|
let event = yield popupShownPromise;
|
||||||
|
|
||||||
|
let contextMenu = document.getElementById("contentAreaContextMenu");
|
||||||
|
checkMenu(contextMenu);
|
||||||
|
contextMenu.hidePopup();
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkItems(menuitem, arr)
|
||||||
|
{
|
||||||
|
for (let i = 0; i < arr.length; i += 2) {
|
||||||
|
let str = arr[i];
|
||||||
|
let details = arr[i + 1];
|
||||||
|
if (str == "---") {
|
||||||
|
is(menuitem.localName, "menuseparator", "menuseparator");
|
||||||
|
}
|
||||||
|
else if ("children" in details) {
|
||||||
|
is(menuitem.localName, "menu", "submenu");
|
||||||
|
is(menuitem.getAttribute("label"), str, str + " label");
|
||||||
|
checkItems(menuitem.firstChild.firstChild, details.children);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is(menuitem.localName, "menuitem", str + " menuitem");
|
||||||
|
|
||||||
|
is(menuitem.getAttribute("label"), str, str + " label");
|
||||||
|
is(menuitem.getAttribute("type"), details.type, str + " type");
|
||||||
|
is(menuitem.getAttribute("image"), details.icon ? gBaseURL + details.icon : "", str + " icon");
|
||||||
|
|
||||||
|
if (details.checked)
|
||||||
|
is(menuitem.getAttribute("checked"), "true", str + " checked");
|
||||||
|
else
|
||||||
|
ok(!menuitem.hasAttribute("checked"), str + " checked");
|
||||||
|
|
||||||
|
if (details.disabled)
|
||||||
|
is(menuitem.getAttribute("disabled"), "true", str + " disabled");
|
||||||
|
else
|
||||||
|
ok(!menuitem.hasAttribute("disabled"), str + " disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem = menuitem.nextSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkMenu(contextMenu)
|
||||||
|
{
|
||||||
|
let items = [ "Plain item", {type: "", icon: "", checked: false, disabled: false},
|
||||||
|
"Disabled item", {type: "", icon: "", checked: false, disabled: true},
|
||||||
|
"Item w/ textContent", {type: "", icon: "", checked: false, disabled: false},
|
||||||
|
"---", null,
|
||||||
|
"Checkbox", {type: "checkbox", icon: "", checked: true, disabled: false},
|
||||||
|
"---", null,
|
||||||
|
"Radio1", {type: "checkbox", icon: "", checked: true, disabled: false},
|
||||||
|
"Radio2", {type: "checkbox", icon: "", checked: false, disabled: false},
|
||||||
|
"Radio3", {type: "checkbox", icon: "", checked: false, disabled: false},
|
||||||
|
"---", null,
|
||||||
|
"Item w/ icon", {type: "", icon: "favicon.ico", checked: false, disabled: false},
|
||||||
|
"Item w/ bad icon", {type: "", icon: "", checked: false, disabled: false},
|
||||||
|
"---", null,
|
||||||
|
"Submenu", { children:
|
||||||
|
["Radio1", {type: "checkbox", icon: "", checked: false, disabled: false},
|
||||||
|
"Radio2", {type: "checkbox", icon: "", checked: true, disabled: false},
|
||||||
|
"Radio3", {type: "checkbox", icon: "", checked: false, disabled: false},
|
||||||
|
"---", null,
|
||||||
|
"Checkbox", {type: "checkbox", icon: "", checked: false, disabled: false}] }
|
||||||
|
];
|
||||||
|
checkItems(contextMenu.childNodes[2], items);
|
||||||
|
}
|
|
@ -495,7 +495,7 @@ function runTest(testNum) {
|
||||||
"context-viewinfo", true
|
"context-viewinfo", true
|
||||||
].concat(inspectItems));
|
].concat(inspectItems));
|
||||||
|
|
||||||
invokeItemAction("0");
|
invokeItemAction("1");
|
||||||
closeContextMenu();
|
closeContextMenu();
|
||||||
|
|
||||||
// run mozRequestFullScreen on the element we're testing
|
// run mozRequestFullScreen on the element we're testing
|
||||||
|
|
|
@ -542,6 +542,8 @@
|
||||||
@RESPATH@/components/Identity.manifest
|
@RESPATH@/components/Identity.manifest
|
||||||
@RESPATH@/components/recording-cmdline.js
|
@RESPATH@/components/recording-cmdline.js
|
||||||
@RESPATH@/components/recording-cmdline.manifest
|
@RESPATH@/components/recording-cmdline.manifest
|
||||||
|
@RESPATH@/components/htmlMenuBuilder.js
|
||||||
|
@RESPATH@/components/htmlMenuBuilder.manifest
|
||||||
|
|
||||||
@RESPATH@/components/PermissionSettings.js
|
@RESPATH@/components/PermissionSettings.js
|
||||||
@RESPATH@/components/PermissionSettings.manifest
|
@RESPATH@/components/PermissionSettings.manifest
|
||||||
|
|
|
@ -77,7 +77,7 @@ SEARCHPLUGINS_PATH := $(FINAL_TARGET)/searchplugins
|
||||||
# metro build call a searchplugins target for search engine plugins
|
# metro build call a searchplugins target for search engine plugins
|
||||||
.PHONY: searchplugins
|
.PHONY: searchplugins
|
||||||
SEARCHPLUGINS_TARGET := libs searchplugins
|
SEARCHPLUGINS_TARGET := libs searchplugins
|
||||||
SEARCHPLUGINS := $(foreach plugin,$(addsuffix .xml,$(SEARCHPLUGINS_NAMES)),$(or $(wildcard $(call MERGE_FILE,searchplugins/$(plugin))),$(info Missing searchplugin: $(plugin))))
|
SEARCHPLUGINS := $(foreach plugin,$(addsuffix .xml,$(SEARCHPLUGINS_NAMES)),$(or $(wildcard $(call EN_US_OR_L10N_FILE,searchplugins/$(plugin))),$(info Missing searchplugin: $(plugin))))
|
||||||
# Some locale-specific search plugins may have preprocessor directives, but the
|
# Some locale-specific search plugins may have preprocessor directives, but the
|
||||||
# default en-US ones do not.
|
# default en-US ones do not.
|
||||||
SEARCHPLUGINS_FLAGS := --silence-missing-directive-warnings
|
SEARCHPLUGINS_FLAGS := --silence-missing-directive-warnings
|
||||||
|
|
|
@ -614,6 +614,13 @@ MERGE_FILE = $(LOCALE_SRCDIR)/$(1)
|
||||||
endif
|
endif
|
||||||
MERGE_FILES = $(foreach f,$(1),$(call MERGE_FILE,$(f)))
|
MERGE_FILES = $(foreach f,$(1),$(call MERGE_FILE,$(f)))
|
||||||
|
|
||||||
|
# These marcros are similar to MERGE_FILE, but no merging, and en-US first.
|
||||||
|
# They're used for searchplugins, for example.
|
||||||
|
EN_US_OR_L10N_FILE = $(firstword \
|
||||||
|
$(wildcard $(srcdir)/en-US/$(1)) \
|
||||||
|
$(LOCALE_SRCDIR)/$(1) )
|
||||||
|
EN_US_OR_L10N_FILES = $(foreach f,$(1),$(call EN_US_OR_L10N_FILE,$(f)))
|
||||||
|
|
||||||
ifneq (WINNT,$(OS_ARCH))
|
ifneq (WINNT,$(OS_ARCH))
|
||||||
RUN_TEST_PROGRAM = $(LIBXUL_DIST)/bin/run-mozilla.sh
|
RUN_TEST_PROGRAM = $(LIBXUL_DIST)/bin/run-mozilla.sh
|
||||||
endif # ! WINNT
|
endif # ! WINNT
|
||||||
|
|
|
@ -22,48 +22,39 @@ include $(topsrcdir)/config/rules.mk
|
||||||
# As an optimization to reduce overall CPU usage, we process all .idl
|
# As an optimization to reduce overall CPU usage, we process all .idl
|
||||||
# belonging to a module with a single command invocation. This prevents
|
# belonging to a module with a single command invocation. This prevents
|
||||||
# redundant parsing of .idl files and significantly reduces CPU cycles.
|
# redundant parsing of .idl files and significantly reduces CPU cycles.
|
||||||
#
|
|
||||||
# Future improvement: Headers are currently written to a local directory then
|
|
||||||
# installed in the distribution directory. It is preferable to write headers
|
|
||||||
# directly into the distribution directory. However, PGO builds remove the dist
|
|
||||||
# directory via rm -rf (with no regards to manifests). Since the cost of
|
|
||||||
# processing XPIDL files is not trivial, it is preferrable to cache the headers
|
|
||||||
# and reinstall them rather than regenerate them. Ideally the dist pruning is
|
|
||||||
# performed with manifests. At that time we can write headers directly to the
|
|
||||||
# dist directory.
|
|
||||||
|
|
||||||
# For dependency files.
|
# For dependency files.
|
||||||
idl_deps_dir := .deps
|
idl_deps_dir := .deps
|
||||||
|
|
||||||
# Where we put our final, linked .xpt files.
|
|
||||||
idl_xpt_dir := xpt
|
|
||||||
|
|
||||||
dist_idl_dir := $(DIST)/idl
|
dist_idl_dir := $(DIST)/idl
|
||||||
dist_include_dir := $(DIST)/include
|
dist_include_dir := $(DIST)/include
|
||||||
process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
|
process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
|
||||||
|
|
||||||
# TODO we should use py_action, but that would require extra directories to be
|
|
||||||
# in the virtualenv.
|
|
||||||
idlprocess := $(PYTHON_PATH) $(PLY_INCLUDE) -I$(IDL_PARSER_DIR) -I$(IDL_PARSER_CACHE_DIR) \
|
|
||||||
$(process_py) --cache-dir $(IDL_PARSER_CACHE_DIR) $(dist_idl_dir) \
|
|
||||||
$(dist_include_dir) $(idl_xpt_dir) $(idl_deps_dir)
|
|
||||||
|
|
||||||
ifdef LIBXUL_SDK
|
ifdef LIBXUL_SDK
|
||||||
idlprocess += -I$(LIBXUL_SDK)/idl
|
libxul_sdk_includes := -I$(LIBXUL_SDK)/idl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# TODO we should use py_action, but that would require extra directories to be
|
||||||
|
# in the virtualenv.
|
||||||
|
%.xpt:
|
||||||
|
@echo "$(@F)"
|
||||||
|
$(PYTHON_PATH) $(PLY_INCLUDE) -I$(IDL_PARSER_DIR) -I$(IDL_PARSER_CACHE_DIR) \
|
||||||
|
$(process_py) --cache-dir $(IDL_PARSER_CACHE_DIR) $(dist_idl_dir) \
|
||||||
|
$(dist_include_dir) $(@D) $(idl_deps_dir) $(libxul_sdk_includes) \
|
||||||
|
$(basename $(notdir $@ $(filter %.idl,$^)))
|
||||||
|
|
||||||
xpidl_modules := @xpidl_modules@
|
xpidl_modules := @xpidl_modules@
|
||||||
|
xpt_files := @xpt_files@
|
||||||
|
|
||||||
@xpidl_rules@
|
@xpidl_rules@
|
||||||
|
|
||||||
linked_xpt_files := $(addprefix $(idl_xpt_dir)/,$(addsuffix .xpt,$(xpidl_modules)))
|
|
||||||
depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
|
depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
|
||||||
|
|
||||||
GARBAGE += $(linked_xpt_files) $(depends_files)
|
GARBAGE += $(xpt_files) $(depends_files)
|
||||||
|
|
||||||
xpidl:: $(linked_xpt_files)
|
xpidl:: $(xpt_files)
|
||||||
|
|
||||||
$(linked_xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(idl_xpt_dir))
|
$(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir))
|
||||||
|
|
||||||
$(call include_deps,$(depends_files))
|
$(call include_deps,$(depends_files))
|
||||||
|
|
||||||
|
|
|
@ -1157,11 +1157,6 @@ endif
|
||||||
ifdef XPT_NAME #{
|
ifdef XPT_NAME #{
|
||||||
|
|
||||||
ifndef NO_DIST_INSTALL
|
ifndef NO_DIST_INSTALL
|
||||||
_XPT_NAME_FILES := $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
|
|
||||||
_XPT_NAME_DEST := $(FINAL_TARGET)/components
|
|
||||||
_XPT_NAME_TARGET := misc
|
|
||||||
INSTALL_TARGETS += _XPT_NAME
|
|
||||||
|
|
||||||
ifndef NO_INTERFACES_MANIFEST
|
ifndef NO_INTERFACES_MANIFEST
|
||||||
misc:: $(call mkdir_deps,$(FINAL_TARGET)/components)
|
misc:: $(call mkdir_deps,$(FINAL_TARGET)/components)
|
||||||
$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest 'interfaces $(XPT_NAME)')
|
$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest 'interfaces $(XPT_NAME)')
|
||||||
|
|
|
@ -819,7 +819,12 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
nsresult rv = mLoader->ProcessOffThreadRequest(mRequest, &mToken);
|
// We want these to be dropped on the main thread, once we return from this
|
||||||
|
// function.
|
||||||
|
nsRefPtr<nsScriptLoadRequest> request = mRequest.forget();
|
||||||
|
nsRefPtr<nsScriptLoader> loader = mLoader.forget();
|
||||||
|
|
||||||
|
nsresult rv = loader->ProcessOffThreadRequest(request, &mToken);
|
||||||
|
|
||||||
if (mToken) {
|
if (mToken) {
|
||||||
// The result of the off thread parse was not actually needed to process
|
// The result of the off thread parse was not actually needed to process
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
#include "mozilla/EventDispatcher.h"
|
#include "mozilla/EventDispatcher.h"
|
||||||
#include "mozilla/dom/HTMLMenuElementBinding.h"
|
#include "mozilla/dom/HTMLMenuElementBinding.h"
|
||||||
#include "mozilla/dom/HTMLMenuItemElement.h"
|
#include "mozilla/dom/HTMLMenuItemElement.h"
|
||||||
|
#include "nsIMenuBuilder.h"
|
||||||
#include "nsAttrValueInlines.h"
|
#include "nsAttrValueInlines.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsXULContextMenuBuilder.h"
|
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
|
|
||||||
|
#define HTMLMENUBUILDER_CONTRACTID "@mozilla.org/content/html-menu-builder;1"
|
||||||
|
|
||||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Menu)
|
NS_IMPL_NS_NEW_HTML_ELEMENT(Menu)
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -97,12 +99,8 @@ HTMLMenuElement::CreateBuilder(nsIMenuBuilder** _retval)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
|
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
|
||||||
|
|
||||||
*_retval = nullptr;
|
nsCOMPtr<nsIMenuBuilder> builder = CreateBuilder();
|
||||||
|
builder.swap(*_retval);
|
||||||
if (mType == MENU_TYPE_CONTEXT) {
|
|
||||||
NS_ADDREF(*_retval = new nsXULContextMenuBuilder());
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,8 +111,9 @@ HTMLMenuElement::CreateBuilder()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIMenuBuilder> ret = new nsXULContextMenuBuilder();
|
nsCOMPtr<nsIMenuBuilder> builder = do_CreateInstance(HTMLMENUBUILDER_CONTRACTID);
|
||||||
return ret.forget();
|
NS_WARN_IF(!builder);
|
||||||
|
return builder.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/* 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 component is used to build the menus for the HTML contextmenu attribute.
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
|
||||||
|
// A global value that is used to identify each menu item. It is
|
||||||
|
// incremented with each one that is found.
|
||||||
|
var gGeneratedId = 1;
|
||||||
|
|
||||||
|
function HTMLMenuBuilder() {
|
||||||
|
this.currentNode = null;
|
||||||
|
this.root = null;
|
||||||
|
this.items = {};
|
||||||
|
this.nestedStack = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Building is done in two steps:
|
||||||
|
// The first generates a hierarchical JS object that contains the menu structure.
|
||||||
|
// This object is returned by toJSONString.
|
||||||
|
//
|
||||||
|
// The second step can take this structure and generate a XUL menu hierarchy or
|
||||||
|
// other UI from this object. The default UI is done in PageMenu.jsm.
|
||||||
|
//
|
||||||
|
// When a multi-process browser is used, the first step is performed by the child
|
||||||
|
// process and the second step is performed by the parent process.
|
||||||
|
|
||||||
|
HTMLMenuBuilder.prototype =
|
||||||
|
{
|
||||||
|
classID: Components.ID("{51c65f5d-0de5-4edc-9058-60e50cef77f8}"),
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMenuBuilder]),
|
||||||
|
|
||||||
|
currentNode: null,
|
||||||
|
root: null,
|
||||||
|
items: {},
|
||||||
|
nestedStack: [],
|
||||||
|
|
||||||
|
toJSONString: function() {
|
||||||
|
return JSON.stringify(this.root);
|
||||||
|
},
|
||||||
|
|
||||||
|
openContainer: function(aLabel) {
|
||||||
|
if (!this.currentNode) {
|
||||||
|
this.root = {
|
||||||
|
type: "menu",
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
this.currentNode = this.root;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let parent = this.currentNode;
|
||||||
|
this.currentNode = {
|
||||||
|
type: "menu",
|
||||||
|
label: aLabel,
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
parent.children.push(this.currentNode);
|
||||||
|
this.nestedStack.push(parent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addItemFor: function(aElement, aCanLoadIcon) {
|
||||||
|
if (!("children" in this.currentNode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = {
|
||||||
|
type: "menuitem",
|
||||||
|
label: aElement.label
|
||||||
|
};
|
||||||
|
|
||||||
|
let elementType = aElement.type;
|
||||||
|
if (elementType == "checkbox" || elementType == "radio") {
|
||||||
|
item.checkbox = true;
|
||||||
|
|
||||||
|
if (aElement.checked) {
|
||||||
|
item.checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let icon = aElement.icon;
|
||||||
|
if (icon.length > 0 && aCanLoadIcon) {
|
||||||
|
item.icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aElement.disabled) {
|
||||||
|
item.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.id = gGeneratedId++;
|
||||||
|
this.currentNode.children.push(item);
|
||||||
|
|
||||||
|
this.items[item.id] = aElement;
|
||||||
|
},
|
||||||
|
|
||||||
|
addSeparator: function() {
|
||||||
|
if (!("children" in this.currentNode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentNode.children.push({ type: "separator"});
|
||||||
|
},
|
||||||
|
|
||||||
|
undoAddSeparator: function() {
|
||||||
|
if (!("children" in this.currentNode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let children = this.currentNode.children;
|
||||||
|
if (children.length && children[children.length - 1].type == "separator") {
|
||||||
|
children.pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
closeContainer: function() {
|
||||||
|
this.currentNode = this.nestedStack.length ? this.nestedStack.pop() : this.root;
|
||||||
|
},
|
||||||
|
|
||||||
|
click: function(id) {
|
||||||
|
let item = this.items[id];
|
||||||
|
if (item) {
|
||||||
|
item.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HTMLMenuBuilder]);
|
|
@ -0,0 +1,3 @@
|
||||||
|
component {51c65f5d-0de5-4edc-9058-60e50cef77f8} htmlMenuBuilder.js
|
||||||
|
contract @mozilla.org/content/html-menu-builder;1 {51c65f5d-0de5-4edc-9058-60e50cef77f8}
|
||||||
|
|
|
@ -215,6 +215,11 @@ SOURCES += [
|
||||||
'PluginDocument.cpp',
|
'PluginDocument.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
EXTRA_COMPONENTS += [
|
||||||
|
'htmlMenuBuilder.js',
|
||||||
|
'htmlMenuBuilder.manifest'
|
||||||
|
]
|
||||||
|
|
||||||
FAIL_ON_WARNINGS = True
|
FAIL_ON_WARNINGS = True
|
||||||
|
|
||||||
MSVC_ENABLE_PGO = True
|
MSVC_ENABLE_PGO = True
|
||||||
|
|
|
@ -11,7 +11,7 @@ interface nsIDOMHTMLMenuItemElement;
|
||||||
* An interface used to construct native toolbar or context menus from <menu>
|
* An interface used to construct native toolbar or context menus from <menu>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[scriptable, uuid(12724737-f7db-43b4-94ab-708a7b86e115)]
|
[scriptable, uuid(93F4A48F-D043-4F45-97FD-9771EA1AF976)]
|
||||||
interface nsIMenuBuilder : nsISupports
|
interface nsIMenuBuilder : nsISupports
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -49,4 +49,28 @@ interface nsIMenuBuilder : nsISupports
|
||||||
*/
|
*/
|
||||||
void closeContainer();
|
void closeContainer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON string representing the menu hierarchy. For a context menu,
|
||||||
|
* it will be of the form:
|
||||||
|
* {
|
||||||
|
* type: "menu",
|
||||||
|
* children: [
|
||||||
|
* {
|
||||||
|
* type: "menuitem",
|
||||||
|
* label: "label",
|
||||||
|
* icon: "image.png"
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* type: "separator",
|
||||||
|
* },
|
||||||
|
* ];
|
||||||
|
*/
|
||||||
|
AString toJSONString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke the action of the menuitem with assigned id aGeneratedItemId.
|
||||||
|
*
|
||||||
|
* @param aGeneratedItemId the menuitem id
|
||||||
|
*/
|
||||||
|
void click(in DOMString aGeneratedItemId);
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,6 +70,7 @@ GStreamerReader::GStreamerReader(AbstractMediaDecoder* aDecoder)
|
||||||
mMP3FrameParser(aDecoder->GetResource()->GetLength()),
|
mMP3FrameParser(aDecoder->GetResource()->GetLength()),
|
||||||
mDataOffset(0),
|
mDataOffset(0),
|
||||||
mUseParserDuration(false),
|
mUseParserDuration(false),
|
||||||
|
mLastParserDuration(-1),
|
||||||
#if GST_VERSION_MAJOR >= 1
|
#if GST_VERSION_MAJOR >= 1
|
||||||
mAllocator(nullptr),
|
mAllocator(nullptr),
|
||||||
mBufferPool(nullptr),
|
mBufferPool(nullptr),
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "AudioBufferSourceNode.h"
|
#include "AudioBufferSourceNode.h"
|
||||||
#include "mozilla/dom/AudioBufferSourceNodeBinding.h"
|
#include "mozilla/dom/AudioBufferSourceNodeBinding.h"
|
||||||
#include "mozilla/dom/AudioParam.h"
|
#include "mozilla/dom/AudioParam.h"
|
||||||
|
#include "mozilla/FloatingPoint.h"
|
||||||
#include "nsMathUtils.h"
|
#include "nsMathUtils.h"
|
||||||
#include "AudioNodeEngine.h"
|
#include "AudioNodeEngine.h"
|
||||||
#include "AudioNodeStream.h"
|
#include "AudioNodeStream.h"
|
||||||
|
@ -110,7 +111,7 @@ public:
|
||||||
mBeginProcessing = mStart + 0.5;
|
mBeginProcessing = mStart + 0.5;
|
||||||
break;
|
break;
|
||||||
case AudioBufferSourceNode::DOPPLERSHIFT:
|
case AudioBufferSourceNode::DOPPLERSHIFT:
|
||||||
mDopplerShift = aParam > 0 && aParam == aParam ? aParam : 1.0;
|
mDopplerShift = (aParam <= 0 || mozilla::IsNaN(aParam)) ? 1.0 : aParam;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
NS_ERROR("Bad AudioBufferSourceNodeEngine double parameter.");
|
NS_ERROR("Bad AudioBufferSourceNodeEngine double parameter.");
|
||||||
|
@ -415,7 +416,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
playbackRate = mPlaybackRateTimeline.GetValueAtTime(mSource->GetCurrentPosition());
|
playbackRate = mPlaybackRateTimeline.GetValueAtTime(mSource->GetCurrentPosition());
|
||||||
}
|
}
|
||||||
if (playbackRate <= 0 || playbackRate != playbackRate) {
|
if (playbackRate <= 0 || mozilla::IsNaN(playbackRate)) {
|
||||||
playbackRate = 1.0f;
|
playbackRate = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,7 @@ namespace WebAudioUtils {
|
||||||
static_assert(mozilla::IsFloatingPoint<FloatType>::value == true,
|
static_assert(mozilla::IsFloatingPoint<FloatType>::value == true,
|
||||||
"FloatType must be a floating point type");
|
"FloatType must be a floating point type");
|
||||||
|
|
||||||
if (f != f) {
|
if (mozilla::IsNaN(f)) {
|
||||||
// It is the responsibility of the caller to deal with NaN values.
|
// It is the responsibility of the caller to deal with NaN values.
|
||||||
// If we ever get to this point, we have a serious bug to fix.
|
// If we ever get to this point, we have a serious bug to fix.
|
||||||
NS_RUNTIMEABORT("We should never see a NaN here");
|
NS_RUNTIMEABORT("We should never see a NaN here");
|
||||||
|
|
|
@ -691,40 +691,72 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
|
||||||
gfx::BackendType::NONE,
|
gfx::BackendType::NONE,
|
||||||
layers::TextureFlags::DEFAULT,
|
layers::TextureFlags::DEFAULT,
|
||||||
layers::ALLOC_DISALLOW_BUFFERTEXTURECLIENT);
|
layers::ALLOC_DISALLOW_BUFFERTEXTURECLIENT);
|
||||||
if (!textureClient) {
|
if (textureClient) {
|
||||||
return;
|
RefPtr<layers::GrallocTextureClientOGL> grallocTextureClient =
|
||||||
|
static_cast<layers::GrallocTextureClientOGL*>(textureClient.get());
|
||||||
|
|
||||||
|
android::sp<android::GraphicBuffer> destBuffer = grallocTextureClient->GetGraphicBuffer();
|
||||||
|
|
||||||
|
void* destMem = nullptr;
|
||||||
|
destBuffer->lock(android::GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destMem);
|
||||||
|
uint8_t* dstPtr = static_cast<uint8_t*>(destMem);
|
||||||
|
|
||||||
|
int32_t yStride = destBuffer->getStride();
|
||||||
|
// Align to 16 bytes boundary
|
||||||
|
int32_t uvStride = ((yStride / 2) + 15) & ~0x0F;
|
||||||
|
|
||||||
|
libyuv::ConvertToI420(srcPtr, size,
|
||||||
|
dstPtr, yStride,
|
||||||
|
dstPtr + (yStride * dstHeight + (uvStride * dstHeight / 2)), uvStride,
|
||||||
|
dstPtr + (yStride * dstHeight), uvStride,
|
||||||
|
0, 0,
|
||||||
|
aWidth, aHeight,
|
||||||
|
aWidth, aHeight,
|
||||||
|
static_cast<libyuv::RotationMode>(mRotation),
|
||||||
|
libyuv::FOURCC_NV21);
|
||||||
|
destBuffer->unlock();
|
||||||
|
|
||||||
|
layers::GrallocImage::GrallocData data;
|
||||||
|
|
||||||
|
data.mPicSize = gfx::IntSize(dstWidth, dstHeight);
|
||||||
|
data.mGraphicBuffer = textureClient;
|
||||||
|
videoImage->SetData(data);
|
||||||
|
} else {
|
||||||
|
// Handle out of gralloc case.
|
||||||
|
image = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
|
||||||
|
layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
|
||||||
|
uint8_t* dstPtr = videoImage->AllocateAndGetNewBuffer(size);
|
||||||
|
|
||||||
|
libyuv::ConvertToI420(srcPtr, size,
|
||||||
|
dstPtr, dstWidth,
|
||||||
|
dstPtr + (dstWidth * dstHeight), half_width,
|
||||||
|
dstPtr + (dstWidth * dstHeight * 5 / 4), half_width,
|
||||||
|
0, 0,
|
||||||
|
aWidth, aHeight,
|
||||||
|
aWidth, aHeight,
|
||||||
|
static_cast<libyuv::RotationMode>(mRotation),
|
||||||
|
ConvertPixelFormatToFOURCC(graphicBuffer->getPixelFormat()));
|
||||||
|
|
||||||
|
const uint8_t lumaBpp = 8;
|
||||||
|
const uint8_t chromaBpp = 4;
|
||||||
|
|
||||||
|
layers::PlanarYCbCrData data;
|
||||||
|
data.mYChannel = dstPtr;
|
||||||
|
data.mYSize = IntSize(dstWidth, dstHeight);
|
||||||
|
data.mYStride = dstWidth * lumaBpp / 8;
|
||||||
|
data.mCbCrStride = dstWidth * chromaBpp / 8;
|
||||||
|
data.mCbChannel = dstPtr + dstHeight * data.mYStride;
|
||||||
|
data.mCrChannel = data.mCbChannel + data.mCbCrStride * (dstHeight / 2);
|
||||||
|
data.mCbCrSize = IntSize(dstWidth / 2, dstHeight / 2);
|
||||||
|
data.mPicX = 0;
|
||||||
|
data.mPicY = 0;
|
||||||
|
data.mPicSize = IntSize(dstWidth, dstHeight);
|
||||||
|
data.mStereoMode = StereoMode::MONO;
|
||||||
|
|
||||||
|
videoImage->SetDataNoCopy(data);
|
||||||
}
|
}
|
||||||
RefPtr<layers::GrallocTextureClientOGL> grallocTextureClient =
|
|
||||||
static_cast<layers::GrallocTextureClientOGL*>(textureClient.get());
|
|
||||||
|
|
||||||
android::sp<android::GraphicBuffer> destBuffer = grallocTextureClient->GetGraphicBuffer();
|
|
||||||
|
|
||||||
void* destMem = nullptr;
|
|
||||||
destBuffer->lock(android::GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destMem);
|
|
||||||
uint8_t* dstPtr = static_cast<uint8_t*>(destMem);
|
|
||||||
|
|
||||||
int32_t yStride = destBuffer->getStride();
|
|
||||||
// Align to 16 bytes boundary
|
|
||||||
int32_t uvStride = ((yStride / 2) + 15) & ~0x0F;
|
|
||||||
|
|
||||||
libyuv::ConvertToI420(srcPtr, size,
|
|
||||||
dstPtr, yStride,
|
|
||||||
dstPtr + (yStride * dstHeight + (uvStride * dstHeight / 2)), uvStride,
|
|
||||||
dstPtr + (yStride * dstHeight), uvStride,
|
|
||||||
0, 0,
|
|
||||||
aWidth, aHeight,
|
|
||||||
aWidth, aHeight,
|
|
||||||
static_cast<libyuv::RotationMode>(mRotation),
|
|
||||||
libyuv::FOURCC_NV21);
|
|
||||||
destBuffer->unlock();
|
|
||||||
graphicBuffer->unlock();
|
graphicBuffer->unlock();
|
||||||
|
|
||||||
layers::GrallocImage::GrallocData data;
|
|
||||||
|
|
||||||
data.mPicSize = gfx::IntSize(dstWidth, dstHeight);
|
|
||||||
data.mGraphicBuffer = textureClient;
|
|
||||||
videoImage->SetData(data);
|
|
||||||
|
|
||||||
// Implicitly releases last preview image.
|
// Implicitly releases last preview image.
|
||||||
mImage = image.forget();
|
mImage = image.forget();
|
||||||
}
|
}
|
||||||
|
@ -767,9 +799,14 @@ MediaEngineGonkVideoSource::OnNewMediaBufferFrame(MediaBuffer* aBuffer)
|
||||||
|
|
||||||
MonitorAutoLock enter(mMonitor);
|
MonitorAutoLock enter(mMonitor);
|
||||||
if (mImage) {
|
if (mImage) {
|
||||||
GonkCameraImage* cameraImage = static_cast<GonkCameraImage*>(mImage.get());
|
if (mImage->AsGrallocImage()) {
|
||||||
|
// MediaEngineGonkVideoSource expects that GrallocImage is GonkCameraImage.
|
||||||
cameraImage->SetBuffer(aBuffer);
|
// See Bug 938034.
|
||||||
|
GonkCameraImage* cameraImage = static_cast<GonkCameraImage*>(mImage.get());
|
||||||
|
cameraImage->SetBuffer(aBuffer);
|
||||||
|
} else {
|
||||||
|
LOG(("mImage is non-GrallocImage"));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t len = mSources.Length();
|
uint32_t len = mSources.Length();
|
||||||
for (uint32_t i = 0; i < len; i++) {
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
@ -780,12 +817,15 @@ MediaEngineGonkVideoSource::OnNewMediaBufferFrame(MediaBuffer* aBuffer)
|
||||||
// Unfortunately, clock in gonk camera looks like is a different one
|
// Unfortunately, clock in gonk camera looks like is a different one
|
||||||
// comparing to MSG. As result, it causes time inaccurate. (frames be
|
// comparing to MSG. As result, it causes time inaccurate. (frames be
|
||||||
// queued in MSG longer and longer as time going by in device like Frame)
|
// queued in MSG longer and longer as time going by in device like Frame)
|
||||||
AppendToTrack(mSources[i], cameraImage, mTrackID, 1);
|
AppendToTrack(mSources[i], mImage, mTrackID, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clear MediaBuffer immediately, it prevents MediaBuffer is kept in
|
if (mImage->AsGrallocImage()) {
|
||||||
// MediaStreamGraph thread.
|
GonkCameraImage* cameraImage = static_cast<GonkCameraImage*>(mImage.get());
|
||||||
cameraImage->ClearBuffer();
|
// Clear MediaBuffer immediately, it prevents MediaBuffer is kept in
|
||||||
|
// MediaStreamGraph thread.
|
||||||
|
cameraImage->ClearBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -40,11 +40,11 @@ partial interface HTMLMenuElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a native menu builder. The builder type is dependent on menu type.
|
* Creates a native menu builder. The builder type is dependent on menu type.
|
||||||
* Currently, it returns nsXULContextMenuBuilder for context menus.
|
* Currently, it returns the @mozilla.org/content/html-menu-builder;1
|
||||||
* Toolbar menus are not yet supported (the method returns null).
|
* component. Toolbar menus are not yet supported (the method returns null).
|
||||||
*/
|
*/
|
||||||
[ChromeOnly]
|
[ChromeOnly]
|
||||||
MenuBuilder createBuilder();
|
MenuBuilder? createBuilder();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Builds a menu by iterating over menu children.
|
* Builds a menu by iterating over menu children.
|
||||||
|
|
|
@ -12,7 +12,6 @@ if CONFIG['MOZ_XUL']:
|
||||||
DIRS += ['templates']
|
DIRS += ['templates']
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
'nsIXULContextMenuBuilder.idl',
|
|
||||||
'nsIXULOverlayProvider.idl',
|
'nsIXULOverlayProvider.idl',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -23,7 +22,6 @@ if CONFIG['MOZ_XUL']:
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'nsXULCommandDispatcher.cpp',
|
'nsXULCommandDispatcher.cpp',
|
||||||
'nsXULContentSink.cpp',
|
'nsXULContentSink.cpp',
|
||||||
'nsXULContextMenuBuilder.cpp',
|
|
||||||
'nsXULElement.cpp',
|
'nsXULElement.cpp',
|
||||||
'nsXULPopupListener.cpp',
|
'nsXULPopupListener.cpp',
|
||||||
'nsXULPrototypeCache.cpp',
|
'nsXULPrototypeCache.cpp',
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIDOMDocumentFragment;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface for initialization of XUL context menu builder
|
|
||||||
* and for triggering of menuitem actions with assigned identifiers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
[scriptable, uuid(eb6b42c0-2f1c-4760-b5ca-bdc9b3ec77d4)]
|
|
||||||
interface nsIXULContextMenuBuilder : nsISupports
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize builder before building.
|
|
||||||
*
|
|
||||||
* @param aDocumentFragment the fragment that will be used to append top
|
|
||||||
* level elements
|
|
||||||
*
|
|
||||||
* @param aGeneratedItemIdAttrName the name of the attribute that will be
|
|
||||||
* used to mark elements as generated and for menuitem identification
|
|
||||||
*/
|
|
||||||
void init(in nsIDOMDocumentFragment aDocumentFragment,
|
|
||||||
in AString aGeneratedItemIdAttrName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoke the action of the menuitem with assigned id aGeneratedItemId.
|
|
||||||
*
|
|
||||||
* @param aGeneratedItemId the menuitem id
|
|
||||||
*/
|
|
||||||
void click(in DOMString aGeneratedItemId);
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,230 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "nsContentCreatorFunctions.h"
|
|
||||||
#include "nsIContent.h"
|
|
||||||
#include "nsIDOMDocumentFragment.h"
|
|
||||||
#include "nsIDOMHTMLElement.h"
|
|
||||||
#include "nsIDOMHTMLMenuItemElement.h"
|
|
||||||
#include "nsXULContextMenuBuilder.h"
|
|
||||||
#include "nsIDocument.h"
|
|
||||||
#include "mozilla/dom/Element.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
|
||||||
nsXULContextMenuBuilder::nsXULContextMenuBuilder()
|
|
||||||
: mCurrentGeneratedItemId(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
nsXULContextMenuBuilder::~nsXULContextMenuBuilder()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION(nsXULContextMenuBuilder, mFragment, mDocument,
|
|
||||||
mCurrentNode, mElements)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULContextMenuBuilder)
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULContextMenuBuilder)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULContextMenuBuilder)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIMenuBuilder)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIXULContextMenuBuilder)
|
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMenuBuilder)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXULContextMenuBuilder::OpenContainer(const nsAString& aLabel)
|
|
||||||
{
|
|
||||||
if (!mFragment) {
|
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mCurrentNode) {
|
|
||||||
mCurrentNode = mFragment;
|
|
||||||
} else {
|
|
||||||
nsCOMPtr<Element> menu;
|
|
||||||
nsresult rv = CreateElement(nsGkAtoms::menu, nullptr, getter_AddRefs(menu));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
menu->SetAttr(kNameSpaceID_None, nsGkAtoms::label, aLabel, false);
|
|
||||||
|
|
||||||
nsCOMPtr<Element> menuPopup;
|
|
||||||
rv = CreateElement(nsGkAtoms::menupopup, nullptr,
|
|
||||||
getter_AddRefs(menuPopup));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = menu->AppendChildTo(menuPopup, false);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = mCurrentNode->AppendChildTo(menu, false);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
mCurrentNode = menuPopup;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXULContextMenuBuilder::AddItemFor(nsIDOMHTMLMenuItemElement* aElement,
|
|
||||||
bool aCanLoadIcon)
|
|
||||||
{
|
|
||||||
if (!mFragment) {
|
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<Element> menuitem;
|
|
||||||
nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(aElement);
|
|
||||||
nsresult rv = CreateElement(nsGkAtoms::menuitem, element,
|
|
||||||
getter_AddRefs(menuitem));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoString type;
|
|
||||||
aElement->GetType(type);
|
|
||||||
if (type.EqualsLiteral("checkbox") || type.EqualsLiteral("radio")) {
|
|
||||||
// The menu is only temporary, so we don't need to handle
|
|
||||||
// the radio type precisely.
|
|
||||||
menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
|
||||||
NS_LITERAL_STRING("checkbox"), false);
|
|
||||||
bool checked;
|
|
||||||
aElement->GetChecked(&checked);
|
|
||||||
if (checked) {
|
|
||||||
menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::checked,
|
|
||||||
NS_LITERAL_STRING("true"), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoString label;
|
|
||||||
aElement->GetLabel(label);
|
|
||||||
menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::label, label, false);
|
|
||||||
|
|
||||||
nsAutoString icon;
|
|
||||||
aElement->GetIcon(icon);
|
|
||||||
if (!icon.IsEmpty()) {
|
|
||||||
menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
|
||||||
NS_LITERAL_STRING("menuitem-iconic"), false);
|
|
||||||
if (aCanLoadIcon) {
|
|
||||||
menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::image, icon, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool disabled;
|
|
||||||
aElement->GetDisabled(&disabled);
|
|
||||||
if (disabled) {
|
|
||||||
menuitem->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
|
|
||||||
NS_LITERAL_STRING("true"), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mCurrentNode->AppendChildTo(menuitem, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXULContextMenuBuilder::AddSeparator()
|
|
||||||
{
|
|
||||||
if (!mFragment) {
|
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<Element> menuseparator;
|
|
||||||
nsresult rv = CreateElement(nsGkAtoms::menuseparator, nullptr,
|
|
||||||
getter_AddRefs(menuseparator));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return mCurrentNode->AppendChildTo(menuseparator, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXULContextMenuBuilder::UndoAddSeparator()
|
|
||||||
{
|
|
||||||
if (!mFragment) {
|
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t count = mCurrentNode->GetChildCount();
|
|
||||||
if (!count ||
|
|
||||||
mCurrentNode->GetChildAt(count - 1)->Tag() != nsGkAtoms::menuseparator) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurrentNode->RemoveChildAt(count - 1, false);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXULContextMenuBuilder::CloseContainer()
|
|
||||||
{
|
|
||||||
if (!mFragment) {
|
|
||||||
return NS_ERROR_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCurrentNode == mFragment) {
|
|
||||||
mCurrentNode = nullptr;
|
|
||||||
} else {
|
|
||||||
nsIContent* parent = mCurrentNode->GetParent();
|
|
||||||
mCurrentNode = parent->GetParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXULContextMenuBuilder::Init(nsIDOMDocumentFragment* aDocumentFragment,
|
|
||||||
const nsAString& aGeneratedItemIdAttrName)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aDocumentFragment);
|
|
||||||
|
|
||||||
mFragment = do_QueryInterface(aDocumentFragment);
|
|
||||||
mDocument = mFragment->GetOwnerDocument();
|
|
||||||
mGeneratedItemIdAttr = do_GetAtom(aGeneratedItemIdAttrName);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXULContextMenuBuilder::Click(const nsAString& aGeneratedItemId)
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
int32_t idx = nsString(aGeneratedItemId).ToInteger(&rv);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
nsCOMPtr<nsIDOMHTMLElement> element = mElements.SafeObjectAt(idx);
|
|
||||||
if (element) {
|
|
||||||
element->DOMClick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXULContextMenuBuilder::CreateElement(nsIAtom* aTag,
|
|
||||||
nsIDOMHTMLElement* aHTMLElement,
|
|
||||||
Element** aResult)
|
|
||||||
{
|
|
||||||
*aResult = nullptr;
|
|
||||||
|
|
||||||
nsRefPtr<mozilla::dom::NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
|
|
||||||
aTag, nullptr, kNameSpaceID_XUL, nsIDOMNode::ELEMENT_NODE);
|
|
||||||
|
|
||||||
nsresult rv = NS_NewElement(aResult, nodeInfo.forget(), NOT_FROM_PARSER);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoString generateditemid;
|
|
||||||
|
|
||||||
if (aHTMLElement) {
|
|
||||||
mElements.AppendObject(aHTMLElement);
|
|
||||||
generateditemid.AppendInt(mCurrentGeneratedItemId++);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*aResult)->SetAttr(kNameSpaceID_None, mGeneratedItemIdAttr, generateditemid,
|
|
||||||
false);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsCOMArray.h"
|
|
||||||
#include "nsIMenuBuilder.h"
|
|
||||||
#include "nsIXULContextMenuBuilder.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
|
|
||||||
class nsIAtom;
|
|
||||||
class nsIContent;
|
|
||||||
class nsIDocument;
|
|
||||||
class nsIDOMHTMLElement;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
class Element;
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
class nsXULContextMenuBuilder : public nsIMenuBuilder,
|
|
||||||
public nsIXULContextMenuBuilder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
nsXULContextMenuBuilder();
|
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULContextMenuBuilder,
|
|
||||||
nsIMenuBuilder)
|
|
||||||
NS_DECL_NSIMENUBUILDER
|
|
||||||
|
|
||||||
NS_DECL_NSIXULCONTEXTMENUBUILDER
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~nsXULContextMenuBuilder();
|
|
||||||
|
|
||||||
nsresult CreateElement(nsIAtom* aTag,
|
|
||||||
nsIDOMHTMLElement* aHTMLElement,
|
|
||||||
mozilla::dom::Element** aResult);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> mFragment;
|
|
||||||
nsCOMPtr<nsIDocument> mDocument;
|
|
||||||
nsCOMPtr<nsIAtom> mGeneratedItemIdAttr;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> mCurrentNode;
|
|
||||||
int32_t mCurrentGeneratedItemId;
|
|
||||||
|
|
||||||
nsCOMArray<nsIDOMHTMLElement> mElements;
|
|
||||||
};
|
|
|
@ -216,7 +216,7 @@ SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
|
||||||
fabsf(contentMetrics.mDisplayPort.x - compositorMetrics.mDisplayPort.x) <= 2 &&
|
fabsf(contentMetrics.mDisplayPort.x - compositorMetrics.mDisplayPort.x) <= 2 &&
|
||||||
fabsf(contentMetrics.mDisplayPort.y - compositorMetrics.mDisplayPort.y) <= 2 &&
|
fabsf(contentMetrics.mDisplayPort.y - compositorMetrics.mDisplayPort.y) <= 2 &&
|
||||||
fabsf(contentMetrics.mDisplayPort.width - compositorMetrics.mDisplayPort.width) <= 2 &&
|
fabsf(contentMetrics.mDisplayPort.width - compositorMetrics.mDisplayPort.width) <= 2 &&
|
||||||
fabsf(contentMetrics.mDisplayPort.height - compositorMetrics.mDisplayPort.height)) {
|
fabsf(contentMetrics.mDisplayPort.height - compositorMetrics.mDisplayPort.height) <= 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,150 +96,6 @@ TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL* aCompositor,
|
|
||||||
GrallocTextureHostOGL* aTextureHost,
|
|
||||||
android::GraphicBuffer* aGraphicBuffer,
|
|
||||||
gfx::SurfaceFormat aFormat)
|
|
||||||
: mCompositor(aCompositor)
|
|
||||||
, mTextureHost(aTextureHost)
|
|
||||||
, mGraphicBuffer(aGraphicBuffer)
|
|
||||||
, mEGLImage(0)
|
|
||||||
, mFormat(aFormat)
|
|
||||||
, mNeedsReset(true)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mGraphicBuffer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
|
|
||||||
{
|
|
||||||
DeallocateDeviceData();
|
|
||||||
mCompositor = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The job of this function is to ensure that the texture is tied to the
|
|
||||||
* android::GraphicBuffer, so that texturing will source the GraphicBuffer.
|
|
||||||
*
|
|
||||||
* To this effect we create an EGLImage wrapping this GraphicBuffer,
|
|
||||||
* using EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
|
|
||||||
* texture using fEGLImageTargetTexture2D.
|
|
||||||
*/
|
|
||||||
MOZ_ASSERT(gl());
|
|
||||||
if (!IsValid() || !gl()->MakeCurrent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint tex = GetGLTexture();
|
|
||||||
GLuint textureTarget = GetTextureTarget();
|
|
||||||
|
|
||||||
gl()->fActiveTexture(aTextureUnit);
|
|
||||||
gl()->fBindTexture(textureTarget, tex);
|
|
||||||
|
|
||||||
ApplyFilterToBoundTexture(gl(), aFilter, textureTarget);
|
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
|
||||||
if (mTextureHost) {
|
|
||||||
// Wait until it's ready.
|
|
||||||
mTextureHost->WaitAcquireFenceSyncComplete();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GrallocTextureSourceOGL::Lock()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(IsValid());
|
|
||||||
if (!IsValid()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!gl()->MakeCurrent()) {
|
|
||||||
NS_WARNING("Failed to make the gl context current");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mTexture = mCompositor->GetTemporaryTexture(GetTextureTarget(), LOCAL_GL_TEXTURE0);
|
|
||||||
|
|
||||||
GLuint textureTarget = GetTextureTarget();
|
|
||||||
|
|
||||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
|
||||||
gl()->fBindTexture(textureTarget, mTexture);
|
|
||||||
if (!mEGLImage) {
|
|
||||||
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
|
|
||||||
}
|
|
||||||
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GrallocTextureSourceOGL::IsValid() const
|
|
||||||
{
|
|
||||||
return !!gl() && !!mGraphicBuffer.get() && !!mCompositor;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl::GLContext*
|
|
||||||
GrallocTextureSourceOGL::gl() const
|
|
||||||
{
|
|
||||||
return mCompositor ? mCompositor->gl() : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GrallocTextureSourceOGL::SetCompositor(Compositor* aCompositor)
|
|
||||||
{
|
|
||||||
if (mCompositor && !aCompositor) {
|
|
||||||
DeallocateDeviceData();
|
|
||||||
}
|
|
||||||
mCompositor = static_cast<CompositorOGL*>(aCompositor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GLenum
|
|
||||||
GrallocTextureSourceOGL::GetTextureTarget() const
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(gl());
|
|
||||||
MOZ_ASSERT(mGraphicBuffer.get());
|
|
||||||
|
|
||||||
if (!gl() || !mGraphicBuffer.get()) {
|
|
||||||
return LOCAL_GL_TEXTURE_EXTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SGX has a quirk that only TEXTURE_EXTERNAL works and any other value will
|
|
||||||
// result in black pixels when trying to draw from bound textures.
|
|
||||||
// Unfortunately, using TEXTURE_EXTERNAL on Adreno has a terrible effect on
|
|
||||||
// performance.
|
|
||||||
// See Bug 950050.
|
|
||||||
if (gl()->Renderer() == gl::GLRenderer::SGX530 ||
|
|
||||||
gl()->Renderer() == gl::GLRenderer::SGX540) {
|
|
||||||
return LOCAL_GL_TEXTURE_EXTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx::IntSize
|
|
||||||
GrallocTextureSourceOGL::GetSize() const
|
|
||||||
{
|
|
||||||
if (!IsValid()) {
|
|
||||||
NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
|
|
||||||
return gfx::IntSize(0, 0);
|
|
||||||
}
|
|
||||||
return gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GrallocTextureSourceOGL::DeallocateDeviceData()
|
|
||||||
{
|
|
||||||
if (mEGLImage) {
|
|
||||||
MOZ_ASSERT(mCompositor);
|
|
||||||
if (!gl() || !gl()->MakeCurrent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EGLImageDestroy(gl(), mEGLImage);
|
|
||||||
mEGLImage = EGL_NO_IMAGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
|
GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
|
||||||
const NewSurfaceDescriptorGralloc& aDescriptor)
|
const NewSurfaceDescriptorGralloc& aDescriptor)
|
||||||
: TextureHost(aFlags)
|
: TextureHost(aFlags)
|
||||||
|
@ -272,9 +128,6 @@ void
|
||||||
GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
|
GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
|
||||||
{
|
{
|
||||||
mCompositor = static_cast<CompositorOGL*>(aCompositor);
|
mCompositor = static_cast<CompositorOGL*>(aCompositor);
|
||||||
if (mTilingTextureSource) {
|
|
||||||
mTilingTextureSource->SetCompositor(mCompositor);
|
|
||||||
}
|
|
||||||
if (mGLTextureSource) {
|
if (mGLTextureSource) {
|
||||||
mGLTextureSource->SetCompositor(mCompositor);
|
mGLTextureSource->SetCompositor(mCompositor);
|
||||||
}
|
}
|
||||||
|
@ -312,10 +165,6 @@ GrallocTextureHostOGL::GetFormat() const
|
||||||
void
|
void
|
||||||
GrallocTextureHostOGL::DeallocateSharedData()
|
GrallocTextureHostOGL::DeallocateSharedData()
|
||||||
{
|
{
|
||||||
if (mTilingTextureSource) {
|
|
||||||
mTilingTextureSource->ForgetBuffer();
|
|
||||||
mTilingTextureSource = nullptr;
|
|
||||||
}
|
|
||||||
if (mGLTextureSource) {
|
if (mGLTextureSource) {
|
||||||
mGLTextureSource = nullptr;
|
mGLTextureSource = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -339,10 +188,6 @@ GrallocTextureHostOGL::DeallocateSharedData()
|
||||||
void
|
void
|
||||||
GrallocTextureHostOGL::ForgetSharedData()
|
GrallocTextureHostOGL::ForgetSharedData()
|
||||||
{
|
{
|
||||||
if (mTilingTextureSource) {
|
|
||||||
mTilingTextureSource->ForgetBuffer();
|
|
||||||
mTilingTextureSource = nullptr;
|
|
||||||
}
|
|
||||||
if (mGLTextureSource) {
|
if (mGLTextureSource) {
|
||||||
mGLTextureSource = nullptr;
|
mGLTextureSource = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -351,9 +196,6 @@ GrallocTextureHostOGL::ForgetSharedData()
|
||||||
void
|
void
|
||||||
GrallocTextureHostOGL::DeallocateDeviceData()
|
GrallocTextureHostOGL::DeallocateDeviceData()
|
||||||
{
|
{
|
||||||
if (mTilingTextureSource) {
|
|
||||||
mTilingTextureSource->DeallocateDeviceData();
|
|
||||||
}
|
|
||||||
if (mGLTextureSource) {
|
if (mGLTextureSource) {
|
||||||
mGLTextureSource = nullptr;
|
mGLTextureSource = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -387,77 +229,24 @@ GrallocTextureHostOGL::GetRenderState()
|
||||||
|
|
||||||
TemporaryRef<gfx::DataSourceSurface>
|
TemporaryRef<gfx::DataSourceSurface>
|
||||||
GrallocTextureHostOGL::GetAsSurface() {
|
GrallocTextureHostOGL::GetAsSurface() {
|
||||||
if (mTilingTextureSource) {
|
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
||||||
return mTilingTextureSource->GetAsSurface();
|
|
||||||
} else {
|
|
||||||
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
|
||||||
uint8_t* grallocData;
|
|
||||||
int32_t rv = graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&grallocData));
|
|
||||||
RefPtr<gfx::DataSourceSurface> grallocTempSurf =
|
|
||||||
gfx::Factory::CreateWrappingDataSourceSurface(grallocData,
|
|
||||||
graphicBuffer->getStride() * android::bytesPerPixel(graphicBuffer->getPixelFormat()),
|
|
||||||
GetSize(), GetFormat());
|
|
||||||
RefPtr<gfx::DataSourceSurface> surf = CreateDataSourceSurfaceByCloning(grallocTempSurf);
|
|
||||||
|
|
||||||
graphicBuffer->unlock();
|
|
||||||
|
|
||||||
return surf.forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TemporaryRef<gfx::DataSourceSurface>
|
|
||||||
GrallocTextureSourceOGL::GetAsSurface() {
|
|
||||||
if (!IsValid()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* grallocData;
|
uint8_t* grallocData;
|
||||||
int32_t rv = mGraphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&grallocData));
|
int32_t rv = graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&grallocData));
|
||||||
if (rv) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<gfx::DataSourceSurface> grallocTempSurf =
|
RefPtr<gfx::DataSourceSurface> grallocTempSurf =
|
||||||
gfx::Factory::CreateWrappingDataSourceSurface(grallocData,
|
gfx::Factory::CreateWrappingDataSourceSurface(grallocData,
|
||||||
mGraphicBuffer->getStride() * android::bytesPerPixel(mGraphicBuffer->getPixelFormat()),
|
graphicBuffer->getStride() * android::bytesPerPixel(graphicBuffer->getPixelFormat()),
|
||||||
GetSize(), GetFormat());
|
GetSize(), GetFormat());
|
||||||
|
|
||||||
RefPtr<gfx::DataSourceSurface> surf = CreateDataSourceSurfaceByCloning(grallocTempSurf);
|
RefPtr<gfx::DataSourceSurface> surf = CreateDataSourceSurfaceByCloning(grallocTempSurf);
|
||||||
|
|
||||||
mGraphicBuffer->unlock();
|
graphicBuffer->unlock();
|
||||||
|
|
||||||
return surf.forget();
|
return surf.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint
|
|
||||||
GrallocTextureSourceOGL::GetGLTexture()
|
|
||||||
{
|
|
||||||
return mTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GrallocTextureSourceOGL::BindEGLImage()
|
|
||||||
{
|
|
||||||
gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureSource*
|
TextureSource*
|
||||||
GrallocTextureHostOGL::GetTextureSources()
|
GrallocTextureHostOGL::GetTextureSources()
|
||||||
{
|
{
|
||||||
// This is now only used with tiled layers, and will eventually be removed.
|
return nullptr;
|
||||||
// Other layer types use BindTextureSource instead.
|
|
||||||
MOZ_ASSERT(!mGLTextureSource);
|
|
||||||
if (!mTilingTextureSource) {
|
|
||||||
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
|
||||||
MOZ_ASSERT(graphicBuffer);
|
|
||||||
if (!graphicBuffer) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
mTilingTextureSource = new GrallocTextureSourceOGL(mCompositor, this,
|
|
||||||
graphicBuffer, mFormat);
|
|
||||||
}
|
|
||||||
mTilingTextureSource->Lock();
|
|
||||||
return mTilingTextureSource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -529,8 +318,6 @@ GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextu
|
||||||
// because otherwise we would be modifying the content of every layer that uses
|
// because otherwise we would be modifying the content of every layer that uses
|
||||||
// the TextureSource in question, even thoug they don't use this TextureHost.
|
// the TextureSource in question, even thoug they don't use this TextureHost.
|
||||||
|
|
||||||
MOZ_ASSERT(!mTilingTextureSource);
|
|
||||||
|
|
||||||
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
|
||||||
|
|
||||||
MOZ_ASSERT(graphicBuffer);
|
MOZ_ASSERT(graphicBuffer);
|
||||||
|
|
|
@ -15,74 +15,6 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class GrallocTextureHostOGL;
|
|
||||||
|
|
||||||
// Progressively getting replaced by GLTextureSource
|
|
||||||
class GrallocTextureSourceOGL : public TextureSource
|
|
||||||
, public TextureSourceOGL
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
friend class GrallocTextureHostOGL;
|
|
||||||
|
|
||||||
GrallocTextureSourceOGL(CompositorOGL* aCompositor,
|
|
||||||
GrallocTextureHostOGL* aTextureHost,
|
|
||||||
android::GraphicBuffer* aGraphicBuffer,
|
|
||||||
gfx::SurfaceFormat aFormat);
|
|
||||||
|
|
||||||
virtual ~GrallocTextureSourceOGL();
|
|
||||||
|
|
||||||
virtual bool IsValid() const MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual void BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
|
|
||||||
|
|
||||||
virtual GLenum GetTextureTarget() const MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
|
|
||||||
|
|
||||||
virtual GLenum GetWrapMode() const MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
return LOCAL_GL_CLAMP_TO_EDGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeallocateDeviceData();
|
|
||||||
|
|
||||||
gl::GLContext* gl() const;
|
|
||||||
|
|
||||||
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
void ForgetBuffer()
|
|
||||||
{
|
|
||||||
mGraphicBuffer = nullptr;
|
|
||||||
mTextureHost = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
TemporaryRef<gfx::DataSourceSurface> GetAsSurface();
|
|
||||||
|
|
||||||
GLuint GetGLTexture();
|
|
||||||
|
|
||||||
void BindEGLImage();
|
|
||||||
|
|
||||||
EGLImage GetEGLImage()
|
|
||||||
{
|
|
||||||
return mEGLImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Lock();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
RefPtr<CompositorOGL> mCompositor;
|
|
||||||
GrallocTextureHostOGL* mTextureHost;
|
|
||||||
android::sp<android::GraphicBuffer> mGraphicBuffer;
|
|
||||||
EGLImage mEGLImage;
|
|
||||||
GLuint mTexture;
|
|
||||||
gfx::SurfaceFormat mFormat;
|
|
||||||
bool mNeedsReset;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GrallocTextureHostOGL : public TextureHost
|
class GrallocTextureHostOGL : public TextureHost
|
||||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
||||||
, public TextureHostOGL
|
, public TextureHostOGL
|
||||||
|
@ -144,8 +76,6 @@ private:
|
||||||
NewSurfaceDescriptorGralloc mGrallocHandle;
|
NewSurfaceDescriptorGralloc mGrallocHandle;
|
||||||
RefPtr<GLTextureSource> mGLTextureSource;
|
RefPtr<GLTextureSource> mGLTextureSource;
|
||||||
RefPtr<CompositorOGL> mCompositor;
|
RefPtr<CompositorOGL> mCompositor;
|
||||||
// only used for tiling, will be removed.
|
|
||||||
RefPtr<GrallocTextureSourceOGL> mTilingTextureSource;
|
|
||||||
// Size reported by the GraphicBuffer
|
// Size reported by the GraphicBuffer
|
||||||
gfx::IntSize mSize;
|
gfx::IntSize mSize;
|
||||||
// Size reported by TextureClient, can be different in some cases (video?),
|
// Size reported by TextureClient, can be different in some cases (video?),
|
||||||
|
|
|
@ -27,11 +27,7 @@
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#if ANDROID_VERSION >= 21
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
|
||||||
#else
|
|
||||||
#include <asm/page.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
|
|
||||||
|
@ -1321,6 +1317,8 @@ EnsureKernelLowMemKillerParamsSet()
|
||||||
int32_t lowerBoundOfNextKillUnderKB = 0;
|
int32_t lowerBoundOfNextKillUnderKB = 0;
|
||||||
int32_t countOfLowmemorykillerParametersSets = 0;
|
int32_t countOfLowmemorykillerParametersSets = 0;
|
||||||
|
|
||||||
|
long page_size = sysconf(_SC_PAGESIZE);
|
||||||
|
|
||||||
for (int i = NUM_PROCESS_PRIORITY - 1; i >= 0; i--) {
|
for (int i = NUM_PROCESS_PRIORITY - 1; i >= 0; i--) {
|
||||||
// The system doesn't function correctly if we're missing these prefs, so
|
// The system doesn't function correctly if we're missing these prefs, so
|
||||||
// crash loudly.
|
// crash loudly.
|
||||||
|
@ -1358,7 +1356,7 @@ EnsureKernelLowMemKillerParamsSet()
|
||||||
adjParams.AppendPrintf("%d,", OomAdjOfOomScoreAdj(oomScoreAdj));
|
adjParams.AppendPrintf("%d,", OomAdjOfOomScoreAdj(oomScoreAdj));
|
||||||
|
|
||||||
// minfree is in pages.
|
// minfree is in pages.
|
||||||
minfreeParams.AppendPrintf("%d,", killUnderKB * 1024 / PAGE_SIZE);
|
minfreeParams.AppendPrintf("%ld,", killUnderKB * 1024 / page_size);
|
||||||
|
|
||||||
lowerBoundOfNextOomScoreAdj = oomScoreAdj;
|
lowerBoundOfNextOomScoreAdj = oomScoreAdj;
|
||||||
lowerBoundOfNextKillUnderKB = killUnderKB;
|
lowerBoundOfNextKillUnderKB = killUnderKB;
|
||||||
|
@ -1381,7 +1379,7 @@ EnsureKernelLowMemKillerParamsSet()
|
||||||
|
|
||||||
// notify_trigger is in pages.
|
// notify_trigger is in pages.
|
||||||
WriteToFile("/sys/module/lowmemorykiller/parameters/notify_trigger",
|
WriteToFile("/sys/module/lowmemorykiller/parameters/notify_trigger",
|
||||||
nsPrintfCString("%d", lowMemNotifyThresholdKB * 1024 / PAGE_SIZE).get());
|
nsPrintfCString("%ld", lowMemNotifyThresholdKB * 1024 / page_size).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure OOM events appear in logcat
|
// Ensure OOM events appear in logcat
|
||||||
|
|
|
@ -2242,7 +2242,7 @@ LIRGenerator::visitLoadSlot(MLoadSlot *ins)
|
||||||
MOZ_CRASH("typed load must have a payload");
|
MOZ_CRASH("typed load must have a payload");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
define(new(alloc()) LLoadSlotT(useRegisterAtStart(ins->slots())), ins);
|
define(new(alloc()) LLoadSlotT(useRegisterForTypedLoad(ins->slots(), ins->type())), ins);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3088,13 +3088,16 @@ LIRGenerator::visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole *ins)
|
||||||
void
|
void
|
||||||
LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot *ins)
|
LIRGenerator::visitLoadFixedSlot(MLoadFixedSlot *ins)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(ins->object()->type() == MIRType_Object);
|
MDefinition *obj = ins->object();
|
||||||
|
MOZ_ASSERT(obj->type() == MIRType_Object);
|
||||||
|
|
||||||
if (ins->type() == MIRType_Value) {
|
MIRType type = ins->type();
|
||||||
LLoadFixedSlotV *lir = new(alloc()) LLoadFixedSlotV(useRegisterAtStart(ins->object()));
|
|
||||||
|
if (type == MIRType_Value) {
|
||||||
|
LLoadFixedSlotV *lir = new(alloc()) LLoadFixedSlotV(useRegisterAtStart(obj));
|
||||||
defineBox(lir, ins);
|
defineBox(lir, ins);
|
||||||
} else {
|
} else {
|
||||||
LLoadFixedSlotT *lir = new(alloc()) LLoadFixedSlotT(useRegisterAtStart(ins->object()));
|
LLoadFixedSlotT *lir = new(alloc()) LLoadFixedSlotT(useRegisterForTypedLoad(obj, type));
|
||||||
define(lir, ins);
|
define(lir, ins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,6 +482,23 @@ LIRGeneratorShared::fillBoxUses(LInstruction *lir, size_t n, MDefinition *mir)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LUse
|
||||||
|
LIRGeneratorShared::useRegisterForTypedLoad(MDefinition *mir, MIRType type)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(type != MIRType_Value && type != MIRType_None);
|
||||||
|
MOZ_ASSERT(mir->type() == MIRType_Object || mir->type() == MIRType_Slots);
|
||||||
|
|
||||||
|
#ifdef JS_PUNBOX64
|
||||||
|
// On x64, masm.loadUnboxedValue emits slightly less efficient code when
|
||||||
|
// the input and output use the same register and we're not loading an
|
||||||
|
// int32/bool/double, so we just call useRegister in this case.
|
||||||
|
if (type != MIRType_Int32 && type != MIRType_Boolean && type != MIRType_Double)
|
||||||
|
return useRegister(mir);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return useRegisterAtStart(mir);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,8 @@ class LIRGeneratorShared : public MDefinitionVisitor
|
||||||
inline LAllocation useRegisterOrNonNegativeConstantAtStart(MDefinition *mir);
|
inline LAllocation useRegisterOrNonNegativeConstantAtStart(MDefinition *mir);
|
||||||
inline LAllocation useRegisterOrNonDoubleConstant(MDefinition *mir);
|
inline LAllocation useRegisterOrNonDoubleConstant(MDefinition *mir);
|
||||||
|
|
||||||
|
inline LUse useRegisterForTypedLoad(MDefinition *mir, MIRType type);
|
||||||
|
|
||||||
#ifdef JS_NUNBOX32
|
#ifdef JS_NUNBOX32
|
||||||
inline LUse useType(MDefinition *mir, LUse::Policy policy);
|
inline LUse useType(MDefinition *mir, LUse::Policy policy);
|
||||||
inline LUse usePayload(MDefinition *mir, LUse::Policy policy);
|
inline LUse usePayload(MDefinition *mir, LUse::Policy policy);
|
||||||
|
|
|
@ -1,11 +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/.
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
|
||||||
|
|
||||||
componentdir = js/xpconnect/tests/components
|
|
||||||
libs:: $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
|
|
||||||
$(INSTALL) $^ $(testxpcobjdir)/$(componentdir)/native
|
|
||||||
$(INSTALL) $^ $(testxpcobjdir)/$(componentdir)/js
|
|
|
@ -14,3 +14,11 @@ XPIDL_SOURCES += [
|
||||||
|
|
||||||
XPIDL_MODULE = 'xpctest'
|
XPIDL_MODULE = 'xpctest'
|
||||||
|
|
||||||
|
# XXX: This relies on xpctest.xpt being created in dist/bin/components/ during
|
||||||
|
# the export tier AND TEST_HARNESS_FILES being processed after that.
|
||||||
|
TEST_HARNESS_FILES.xpcshell.js.xpconnect.tests.components.native += [
|
||||||
|
'!/dist/bin/components/xpctest.xpt',
|
||||||
|
]
|
||||||
|
TEST_HARNESS_FILES.xpcshell.js.xpconnect.tests.components.js += [
|
||||||
|
'!/dist/bin/components/xpctest.xpt',
|
||||||
|
]
|
||||||
|
|
|
@ -146,7 +146,7 @@ Abs<long double>(const long double aLongDouble)
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#if defined(_WIN32) && \
|
#if defined(_MSC_VER) && \
|
||||||
(defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
|
(defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
|
||||||
# define MOZ_BITSCAN_WINDOWS
|
# define MOZ_BITSCAN_WINDOWS
|
||||||
|
|
||||||
|
|
|
@ -408,6 +408,8 @@
|
||||||
@BINPATH@/components/Webapps.manifest
|
@BINPATH@/components/Webapps.manifest
|
||||||
@BINPATH@/components/AppsService.js
|
@BINPATH@/components/AppsService.js
|
||||||
@BINPATH@/components/AppsService.manifest
|
@BINPATH@/components/AppsService.manifest
|
||||||
|
@BINPATH@/components/htmlMenuBuilder.js
|
||||||
|
@BINPATH@/components/htmlMenuBuilder.manifest
|
||||||
|
|
||||||
@BINPATH@/components/Activities.manifest
|
@BINPATH@/components/Activities.manifest
|
||||||
@BINPATH@/components/ActivitiesGlue.js
|
@BINPATH@/components/ActivitiesGlue.js
|
||||||
|
|
|
@ -9233,7 +9233,7 @@ githubusercontent.com
|
||||||
ro.com
|
ro.com
|
||||||
|
|
||||||
// Google, Inc.
|
// Google, Inc.
|
||||||
// Submitted by Eduardo Vela <evn@google.com> 2012-10-24
|
// Submitted by Eduardo Vela <evn@google.com> 2014-12-19
|
||||||
appspot.com
|
appspot.com
|
||||||
blogspot.ae
|
blogspot.ae
|
||||||
blogspot.be
|
blogspot.be
|
||||||
|
@ -9281,6 +9281,7 @@ blogspot.tw
|
||||||
codespot.com
|
codespot.com
|
||||||
googleapis.com
|
googleapis.com
|
||||||
googlecode.com
|
googlecode.com
|
||||||
|
pagespeedmobilizer.com
|
||||||
withgoogle.com
|
withgoogle.com
|
||||||
|
|
||||||
// Heroku : https://www.heroku.com/
|
// Heroku : https://www.heroku.com/
|
||||||
|
|
|
@ -2377,13 +2377,15 @@ nsHttpConnectionMgr::OnMsgCancelTransaction(int32_t reason, void *param)
|
||||||
LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]\n", param));
|
LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]\n", param));
|
||||||
|
|
||||||
nsresult closeCode = static_cast<nsresult>(reason);
|
nsresult closeCode = static_cast<nsresult>(reason);
|
||||||
nsHttpTransaction *trans = (nsHttpTransaction *) param;
|
nsRefPtr<nsHttpTransaction> trans =
|
||||||
|
dont_AddRef(static_cast<nsHttpTransaction *>(param));
|
||||||
|
|
||||||
//
|
//
|
||||||
// if the transaction owns a connection and the transaction is not done,
|
// if the transaction owns a connection and the transaction is not done,
|
||||||
// then ask the connection to close the transaction. otherwise, close the
|
// then ask the connection to close the transaction. otherwise, close the
|
||||||
// transaction directly (removing it from the pending queue first).
|
// transaction directly (removing it from the pending queue first).
|
||||||
//
|
//
|
||||||
nsAHttpConnection *conn = trans->Connection();
|
nsRefPtr<nsAHttpConnection> conn(trans->Connection());
|
||||||
if (conn && !trans->IsDone()) {
|
if (conn && !trans->IsDone()) {
|
||||||
conn->CloseTransaction(trans, closeCode);
|
conn->CloseTransaction(trans, closeCode);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2394,7 +2396,7 @@ nsHttpConnectionMgr::OnMsgCancelTransaction(int32_t reason, void *param)
|
||||||
int32_t index = ent->mPendingQ.IndexOf(trans);
|
int32_t index = ent->mPendingQ.IndexOf(trans);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]"
|
LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p]"
|
||||||
" found in pending queue\n", trans));
|
" found in pending queue\n", trans.get()));
|
||||||
ent->mPendingQ.RemoveElementAt(index);
|
ent->mPendingQ.RemoveElementAt(index);
|
||||||
nsHttpTransaction *temp = trans;
|
nsHttpTransaction *temp = trans;
|
||||||
NS_RELEASE(temp); // b/c NS_RELEASE nulls its argument!
|
NS_RELEASE(temp); // b/c NS_RELEASE nulls its argument!
|
||||||
|
@ -2429,12 +2431,11 @@ nsHttpConnectionMgr::OnMsgCancelTransaction(int32_t reason, void *param)
|
||||||
if (liveTransaction && liveTransaction->IsNullTransaction()) {
|
if (liveTransaction && liveTransaction->IsNullTransaction()) {
|
||||||
LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p] "
|
LOG(("nsHttpConnectionMgr::OnMsgCancelTransaction [trans=%p] "
|
||||||
"also canceling Null Transaction %p on conn %p\n",
|
"also canceling Null Transaction %p on conn %p\n",
|
||||||
trans, liveTransaction, activeConn));
|
trans.get(), liveTransaction, activeConn));
|
||||||
activeConn->CloseTransaction(liveTransaction, closeCode);
|
activeConn->CloseTransaction(liveTransaction, closeCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_RELEASE(trans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -39,7 +39,7 @@ class XPIDLManager(object):
|
||||||
self.idls = {}
|
self.idls = {}
|
||||||
self.modules = {}
|
self.modules = {}
|
||||||
|
|
||||||
def register_idl(self, source, module, allow_existing=False):
|
def register_idl(self, source, module, install_target, allow_existing=False):
|
||||||
"""Registers an IDL file with this instance.
|
"""Registers an IDL file with this instance.
|
||||||
|
|
||||||
The IDL file will be built, installed, etc.
|
The IDL file will be built, installed, etc.
|
||||||
|
@ -58,7 +58,8 @@ class XPIDLManager(object):
|
||||||
raise Exception('IDL already registered: %' % entry['basename'])
|
raise Exception('IDL already registered: %' % entry['basename'])
|
||||||
|
|
||||||
self.idls[entry['basename']] = entry
|
self.idls[entry['basename']] = entry
|
||||||
self.modules.setdefault(entry['module'], set()).add(entry['root'])
|
t = self.modules.setdefault(entry['module'], (install_target, set()))
|
||||||
|
t[1].add(entry['root'])
|
||||||
|
|
||||||
|
|
||||||
class WebIDLCollection(object):
|
class WebIDLCollection(object):
|
||||||
|
@ -181,7 +182,8 @@ class CommonBackend(BuildBackend):
|
||||||
topsrcdir=obj.topsrcdir)
|
topsrcdir=obj.topsrcdir)
|
||||||
|
|
||||||
elif isinstance(obj, XPIDLFile):
|
elif isinstance(obj, XPIDLFile):
|
||||||
self._idl_manager.register_idl(obj.source_path, obj.module)
|
self._idl_manager.register_idl(obj.source_path, obj.module,
|
||||||
|
obj.install_target)
|
||||||
|
|
||||||
elif isinstance(obj, ConfigFileSubstitution):
|
elif isinstance(obj, ConfigFileSubstitution):
|
||||||
# Do not handle ConfigFileSubstitution for Makefiles. Leave that
|
# Do not handle ConfigFileSubstitution for Makefiles. Leave that
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import errno
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
@ -15,11 +16,11 @@ from collections import (
|
||||||
defaultdict,
|
defaultdict,
|
||||||
namedtuple,
|
namedtuple,
|
||||||
)
|
)
|
||||||
|
from StringIO import StringIO
|
||||||
|
|
||||||
import mozwebidlcodegen
|
import mozwebidlcodegen
|
||||||
from reftest import ReftestManifest
|
from reftest import ReftestManifest
|
||||||
|
|
||||||
import mozbuild.makeutil as mozmakeutil
|
|
||||||
from mozpack.copier import FilePurger
|
from mozpack.copier import FilePurger
|
||||||
from mozpack.manifests import (
|
from mozpack.manifests import (
|
||||||
InstallManifest,
|
InstallManifest,
|
||||||
|
@ -751,7 +752,7 @@ class RecursiveMakeBackend(CommonBackend):
|
||||||
|
|
||||||
# Write out a master list of all IPDL source files.
|
# Write out a master list of all IPDL source files.
|
||||||
ipdl_dir = mozpath.join(self.environment.topobjdir, 'ipc', 'ipdl')
|
ipdl_dir = mozpath.join(self.environment.topobjdir, 'ipc', 'ipdl')
|
||||||
mk = mozmakeutil.Makefile()
|
mk = Makefile()
|
||||||
|
|
||||||
sorted_ipdl_sources = list(sorted(self._ipdl_sources))
|
sorted_ipdl_sources = list(sorted(self._ipdl_sources))
|
||||||
mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources))
|
mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources))
|
||||||
|
@ -983,8 +984,7 @@ INSTALL_TARGETS += %(prefix)s
|
||||||
def _handle_idl_manager(self, manager):
|
def _handle_idl_manager(self, manager):
|
||||||
build_files = self._install_manifests['xpidl']
|
build_files = self._install_manifests['xpidl']
|
||||||
|
|
||||||
for p in ('Makefile', 'backend.mk', '.deps/.mkdir.done',
|
for p in ('Makefile', 'backend.mk', '.deps/.mkdir.done'):
|
||||||
'xpt/.mkdir.done'):
|
|
||||||
build_files.add_optional_exists(p)
|
build_files.add_optional_exists(p)
|
||||||
|
|
||||||
for idl in manager.idls.values():
|
for idl in manager.idls.values():
|
||||||
|
@ -994,34 +994,44 @@ INSTALL_TARGETS += %(prefix)s
|
||||||
% idl['root'])
|
% idl['root'])
|
||||||
|
|
||||||
for module in manager.modules:
|
for module in manager.modules:
|
||||||
build_files.add_optional_exists(mozpath.join('xpt',
|
|
||||||
'%s.xpt' % module))
|
|
||||||
build_files.add_optional_exists(mozpath.join('.deps',
|
build_files.add_optional_exists(mozpath.join('.deps',
|
||||||
'%s.pp' % module))
|
'%s.pp' % module))
|
||||||
|
|
||||||
modules = manager.modules
|
modules = manager.modules
|
||||||
xpt_modules = sorted(modules.keys())
|
xpt_modules = sorted(modules.keys())
|
||||||
rules = []
|
xpt_files = set()
|
||||||
|
|
||||||
|
mk = Makefile()
|
||||||
|
|
||||||
for module in xpt_modules:
|
for module in xpt_modules:
|
||||||
deps = sorted(modules[module])
|
install_target, sources = modules[module]
|
||||||
idl_deps = ['$(dist_idl_dir)/%s.idl' % dep for dep in deps]
|
deps = sorted(sources)
|
||||||
rules.extend([
|
|
||||||
# It may seem strange to have the .idl files listed as
|
# It may seem strange to have the .idl files listed as
|
||||||
# prerequisites both here and in the auto-generated .pp files.
|
# prerequisites both here and in the auto-generated .pp files.
|
||||||
# It is necessary to list them here to handle the case where a
|
# It is necessary to list them here to handle the case where a
|
||||||
# new .idl is added to an xpt. If we add a new .idl and nothing
|
# new .idl is added to an xpt. If we add a new .idl and nothing
|
||||||
# else has changed, the new .idl won't be referenced anywhere
|
# else has changed, the new .idl won't be referenced anywhere
|
||||||
# except in the command invocation. Therefore, the .xpt won't
|
# except in the command invocation. Therefore, the .xpt won't
|
||||||
# be rebuilt because the dependencies say it is up to date. By
|
# be rebuilt because the dependencies say it is up to date. By
|
||||||
# listing the .idls here, we ensure the make file has a
|
# listing the .idls here, we ensure the make file has a
|
||||||
# reference to the new .idl. Since the new .idl presumably has
|
# reference to the new .idl. Since the new .idl presumably has
|
||||||
# an mtime newer than the .xpt, it will trigger xpt generation.
|
# an mtime newer than the .xpt, it will trigger xpt generation.
|
||||||
'$(idl_xpt_dir)/%s.xpt: %s' % (module, ' '.join(idl_deps)),
|
xpt_path = '$(DEPTH)/%s/components/%s.xpt' % (install_target, module)
|
||||||
'\t@echo "$(notdir $@)"',
|
xpt_files.add(xpt_path)
|
||||||
'\t$(idlprocess) $(basename $(notdir $@)) %s' % ' '.join(deps),
|
rule = mk.create_rule([xpt_path])
|
||||||
'',
|
rule.add_dependencies(['$(call mkdir_deps,%s)' % mozpath.dirname(xpt_path)])
|
||||||
])
|
rule.add_dependencies(manager.idls['%s.idl' % dep]['source'] for dep in deps)
|
||||||
|
|
||||||
|
if install_target.startswith('dist/'):
|
||||||
|
path = mozpath.relpath(xpt_path, '$(DEPTH)/dist')
|
||||||
|
prefix, subpath = path.split('/', 1)
|
||||||
|
key = 'dist_%s' % prefix
|
||||||
|
|
||||||
|
self._install_manifests[key].add_optional_exists(subpath)
|
||||||
|
|
||||||
|
rules = StringIO()
|
||||||
|
mk.dump(rules, removal_guard=False)
|
||||||
|
|
||||||
# Create dependency for output header so we force regeneration if the
|
# Create dependency for output header so we force regeneration if the
|
||||||
# header was deleted. This ideally should not be necessary. However,
|
# header was deleted. This ideally should not be necessary. However,
|
||||||
|
@ -1037,8 +1047,9 @@ INSTALL_TARGETS += %(prefix)s
|
||||||
obj.topobjdir = self.environment.topobjdir
|
obj.topobjdir = self.environment.topobjdir
|
||||||
obj.config = self.environment
|
obj.config = self.environment
|
||||||
self._create_makefile(obj, extra=dict(
|
self._create_makefile(obj, extra=dict(
|
||||||
xpidl_rules='\n'.join(rules),
|
xpidl_rules=rules.getvalue(),
|
||||||
xpidl_modules=' '.join(xpt_modules),
|
xpidl_modules=' '.join(xpt_modules),
|
||||||
|
xpt_files=' '.join(sorted(xpt_files)),
|
||||||
))
|
))
|
||||||
|
|
||||||
def _process_program(self, program, backend_file):
|
def _process_program(self, program, backend_file):
|
||||||
|
|
|
@ -1161,7 +1161,7 @@ VARIABLES = {
|
||||||
Files from topsrcdir and the objdir can also be installed by prefixing
|
Files from topsrcdir and the objdir can also be installed by prefixing
|
||||||
the path(s) with a '/' character and a '!' character, respectively::
|
the path(s) with a '/' character and a '!' character, respectively::
|
||||||
TEST_HARNESS_FILES.path += ['/build/bar.py', '!quux.py']
|
TEST_HARNESS_FILES.path += ['/build/bar.py', '!quux.py']
|
||||||
""", None),
|
""", 'libs'),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sanity check: we don't want any variable above to have a list as storage type.
|
# Sanity check: we don't want any variable above to have a list as storage type.
|
||||||
|
|
|
@ -157,6 +157,7 @@ class XPIDLFile(ContextDerived):
|
||||||
|
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
'basename',
|
'basename',
|
||||||
|
'install_target',
|
||||||
'source_path',
|
'source_path',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -167,6 +168,8 @@ class XPIDLFile(ContextDerived):
|
||||||
self.basename = mozpath.basename(source)
|
self.basename = mozpath.basename(source)
|
||||||
self.module = module
|
self.module = module
|
||||||
|
|
||||||
|
self.install_target = context['FINAL_TARGET']
|
||||||
|
|
||||||
class Defines(ContextDerived):
|
class Defines(ContextDerived):
|
||||||
"""Context derived container object for DEFINES, which is an OrderedDict.
|
"""Context derived container object for DEFINES, which is an OrderedDict.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -345,6 +345,14 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||||
|
|
||||||
This is a generator of mozbuild.frontend.data.ContextDerived instances.
|
This is a generator of mozbuild.frontend.data.ContextDerived instances.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# We only want to emit an InstallationTarget if one of the consulted
|
||||||
|
# variables is defined. Later on, we look up FINAL_TARGET, which has
|
||||||
|
# the side-effect of populating it. So, we need to do this lookup
|
||||||
|
# early.
|
||||||
|
if any(k in context for k in ('FINAL_TARGET', 'XPI_NAME', 'DIST_SUBDIR')):
|
||||||
|
yield InstallationTarget(context)
|
||||||
|
|
||||||
# We always emit a directory traversal descriptor. This is needed by
|
# We always emit a directory traversal descriptor. This is needed by
|
||||||
# the recursive make backend.
|
# the recursive make backend.
|
||||||
for o in self._emit_directory_traversal_from_context(context): yield o
|
for o in self._emit_directory_traversal_from_context(context): yield o
|
||||||
|
@ -523,9 +531,9 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||||
for s in strings:
|
for s in strings:
|
||||||
if context.is_objdir_path(s):
|
if context.is_objdir_path(s):
|
||||||
if s.startswith('!/'):
|
if s.startswith('!/'):
|
||||||
raise SandboxValidationError(
|
objdir_files[path].append('$(DEPTH)/%s' % s[2:])
|
||||||
'Topobjdir-relative file not allowed in TEST_HARNESS_FILES: %s' % s, context)
|
else:
|
||||||
objdir_files[path].append(s[1:])
|
objdir_files[path].append(s[1:])
|
||||||
else:
|
else:
|
||||||
resolved = context.resolve_path(s)
|
resolved = context.resolve_path(s)
|
||||||
if '*' in s:
|
if '*' in s:
|
||||||
|
@ -616,10 +624,6 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||||
'does not exist: %s (resolved to %s)' % (local_include, actual_include), context)
|
'does not exist: %s (resolved to %s)' % (local_include, actual_include), context)
|
||||||
yield LocalInclude(context, local_include)
|
yield LocalInclude(context, local_include)
|
||||||
|
|
||||||
if context.get('FINAL_TARGET') or context.get('XPI_NAME') or \
|
|
||||||
context.get('DIST_SUBDIR'):
|
|
||||||
yield InstallationTarget(context)
|
|
||||||
|
|
||||||
final_target_files = context.get('FINAL_TARGET_FILES')
|
final_target_files = context.get('FINAL_TARGET_FILES')
|
||||||
if final_target_files:
|
if final_target_files:
|
||||||
yield FinalTargetFiles(context, final_target_files, context['FINAL_TARGET'])
|
yield FinalTargetFiles(context, final_target_files, context['FINAL_TARGET'])
|
||||||
|
|
|
@ -443,7 +443,9 @@ class TestRecursiveMakeBackend(BackendTester):
|
||||||
|
|
||||||
m = InstallManifest(path=mozpath.join(install_dir, 'xpidl'))
|
m = InstallManifest(path=mozpath.join(install_dir, 'xpidl'))
|
||||||
self.assertIn('.deps/my_module.pp', m)
|
self.assertIn('.deps/my_module.pp', m)
|
||||||
self.assertIn('xpt/my_module.xpt', m)
|
|
||||||
|
m = InstallManifest(path=os.path.join(install_dir, 'dist_bin'))
|
||||||
|
self.assertIn('components/my_module.xpt', m)
|
||||||
|
|
||||||
m = InstallManifest(path=mozpath.join(install_dir, 'dist_include'))
|
m = InstallManifest(path=mozpath.join(install_dir, 'dist_include'))
|
||||||
self.assertIn('foo.h', m)
|
self.assertIn('foo.h', m)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["PageMenu"];
|
this.EXPORTED_SYMBOLS = ["PageMenuParent", "PageMenuChild"];
|
||||||
|
|
||||||
this.PageMenu = function PageMenu() {
|
this.PageMenu = function PageMenu() {
|
||||||
}
|
}
|
||||||
|
@ -11,46 +11,71 @@ PageMenu.prototype = {
|
||||||
PAGEMENU_ATTR: "pagemenu",
|
PAGEMENU_ATTR: "pagemenu",
|
||||||
GENERATEDITEMID_ATTR: "generateditemid",
|
GENERATEDITEMID_ATTR: "generateditemid",
|
||||||
|
|
||||||
popup: null,
|
_popup: null,
|
||||||
builder: null,
|
|
||||||
|
|
||||||
maybeBuildAndAttachMenu: function(aTarget, aPopup) {
|
// Only one of builder or browser will end up getting set.
|
||||||
var pageMenu = null;
|
_builder: null,
|
||||||
var target = aTarget;
|
_browser: null,
|
||||||
|
|
||||||
|
// Given a target node, get the context menu for it or its ancestor.
|
||||||
|
getContextMenu: function(aTarget) {
|
||||||
|
let pageMenu = null;
|
||||||
|
let target = aTarget;
|
||||||
while (target) {
|
while (target) {
|
||||||
var contextMenu = target.contextMenu;
|
let contextMenu = target.contextMenu;
|
||||||
if (contextMenu) {
|
if (contextMenu) {
|
||||||
pageMenu = contextMenu;
|
return contextMenu;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
target = target.parentNode;
|
target = target.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pageMenu) {
|
return null;
|
||||||
return false;
|
},
|
||||||
}
|
|
||||||
|
|
||||||
var insertionPoint = this.getInsertionPoint(aPopup);
|
// Given a target node, generate a JSON object for any context menu
|
||||||
if (!insertionPoint) {
|
// associated with it, or null if there is no context menu.
|
||||||
return false;
|
maybeBuild: function(aTarget) {
|
||||||
|
let pageMenu = this.getContextMenu(aTarget);
|
||||||
|
if (!pageMenu) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pageMenu.QueryInterface(Components.interfaces.nsIHTMLMenu);
|
pageMenu.QueryInterface(Components.interfaces.nsIHTMLMenu);
|
||||||
pageMenu.sendShowEvent();
|
pageMenu.sendShowEvent();
|
||||||
// the show event is not cancelable, so no need to check a result here
|
// the show event is not cancelable, so no need to check a result here
|
||||||
|
|
||||||
var fragment = aPopup.ownerDocument.createDocumentFragment();
|
this._builder = pageMenu.createBuilder();
|
||||||
|
if (!this._builder) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var builder = pageMenu.createBuilder();
|
pageMenu.build(this._builder);
|
||||||
if (!builder) {
|
|
||||||
|
// This serializes then parses again, however this could be avoided in
|
||||||
|
// the single-process case with further improvement.
|
||||||
|
let menuString = this._builder.toJSONString();
|
||||||
|
if (!menuString) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(menuString);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Given a JSON menu object and popup, add the context menu to the popup.
|
||||||
|
buildAndAttachMenuWithObject: function(aMenu, aBrowser, aPopup) {
|
||||||
|
if (!aMenu) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
builder.QueryInterface(Components.interfaces.nsIXULContextMenuBuilder);
|
|
||||||
builder.init(fragment, this.GENERATEDITEMID_ATTR);
|
|
||||||
|
|
||||||
pageMenu.build(builder);
|
let insertionPoint = this.getInsertionPoint(aPopup);
|
||||||
|
if (!insertionPoint) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var pos = insertionPoint.getAttribute(this.PAGEMENU_ATTR);
|
let fragment = aPopup.ownerDocument.createDocumentFragment();
|
||||||
|
this.buildXULMenu(aMenu, fragment);
|
||||||
|
|
||||||
|
let pos = insertionPoint.getAttribute(this.PAGEMENU_ATTR);
|
||||||
if (pos == "start") {
|
if (pos == "start") {
|
||||||
insertionPoint.insertBefore(fragment,
|
insertionPoint.insertBefore(fragment,
|
||||||
insertionPoint.firstChild);
|
insertionPoint.firstChild);
|
||||||
|
@ -60,33 +85,101 @@ PageMenu.prototype = {
|
||||||
insertionPoint.appendChild(fragment);
|
insertionPoint.appendChild(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.builder = builder;
|
this._browser = aBrowser;
|
||||||
this.popup = aPopup;
|
this._popup = aPopup;
|
||||||
|
|
||||||
this.popup.addEventListener("command", this);
|
this._popup.addEventListener("command", this);
|
||||||
this.popup.addEventListener("popuphidden", this);
|
this._popup.addEventListener("popuphidden", this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEvent: function(event) {
|
// Construct the XUL menu structure for a given JSON object.
|
||||||
var type = event.type;
|
buildXULMenu: function(aNode, aElementForAppending) {
|
||||||
var target = event.target;
|
let document = aElementForAppending.ownerDocument;
|
||||||
if (type == "command" && target.hasAttribute(this.GENERATEDITEMID_ATTR)) {
|
|
||||||
this.builder.click(target.getAttribute(this.GENERATEDITEMID_ATTR));
|
|
||||||
} else if (type == "popuphidden" && this.popup == target) {
|
|
||||||
this.removeGeneratedContent(this.popup);
|
|
||||||
|
|
||||||
this.popup.removeEventListener("popuphidden", this);
|
let children = aNode.children;
|
||||||
this.popup.removeEventListener("command", this);
|
for (let child of children) {
|
||||||
|
let menuitem;
|
||||||
|
switch (child.type) {
|
||||||
|
case "menuitem":
|
||||||
|
if (!child.id) {
|
||||||
|
continue; // Ignore children without ids
|
||||||
|
}
|
||||||
|
|
||||||
this.popup = null;
|
menuitem = document.createElement("menuitem");
|
||||||
this.builder = null;
|
if (child.checkbox) {
|
||||||
|
menuitem.setAttribute("type", "checkbox");
|
||||||
|
if (child.checked) {
|
||||||
|
menuitem.setAttribute("checked", "true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child.label) {
|
||||||
|
menuitem.setAttribute("label", child.label);
|
||||||
|
}
|
||||||
|
if (child.icon) {
|
||||||
|
menuitem.setAttribute("image", child.icon);
|
||||||
|
menuitem.className = "menuitem-iconic";
|
||||||
|
}
|
||||||
|
if (child.disabled) {
|
||||||
|
menuitem.setAttribute("disabled", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "separator":
|
||||||
|
menuitem = document.createElement("menuseparator");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "menu":
|
||||||
|
menuitem = document.createElement("menu");
|
||||||
|
if (child.label) {
|
||||||
|
menuitem.setAttribute("label", child.label);
|
||||||
|
}
|
||||||
|
|
||||||
|
let menupopup = document.createElement("menupopup");
|
||||||
|
menuitem.appendChild(menupopup);
|
||||||
|
|
||||||
|
this.buildXULMenu(child, menupopup);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitem.setAttribute(this.GENERATEDITEMID_ATTR, child.id ? child.id : 0);
|
||||||
|
aElementForAppending.appendChild(menuitem);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Called when the generated menuitem is executed.
|
||||||
|
handleEvent: function(event) {
|
||||||
|
let type = event.type;
|
||||||
|
let target = event.target;
|
||||||
|
if (type == "command" && target.hasAttribute(this.GENERATEDITEMID_ATTR)) {
|
||||||
|
// If a builder is assigned, call click on it directly. Otherwise, this is
|
||||||
|
// likely a menu with data from another process, so send a message to the
|
||||||
|
// browser to execute the menuitem.
|
||||||
|
if (this._builder) {
|
||||||
|
this._builder.click(target.getAttribute(this.GENERATEDITEMID_ATTR));
|
||||||
|
}
|
||||||
|
else if (this._browser) {
|
||||||
|
this._browser.messageManager.sendAsyncMessage("ContextMenu:DoCustomCommand",
|
||||||
|
target.getAttribute(this.GENERATEDITEMID_ATTR));
|
||||||
|
}
|
||||||
|
} else if (type == "popuphidden" && this._popup == target) {
|
||||||
|
this.removeGeneratedContent(this._popup);
|
||||||
|
|
||||||
|
this._popup.removeEventListener("popuphidden", this);
|
||||||
|
this._popup.removeEventListener("command", this);
|
||||||
|
|
||||||
|
this._popup = null;
|
||||||
|
this._builder = null;
|
||||||
|
this._browser = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get the first child of the given element with the given tag name.
|
||||||
getImmediateChild: function(element, tag) {
|
getImmediateChild: function(element, tag) {
|
||||||
var child = element.firstChild;
|
let child = element.firstChild;
|
||||||
while (child) {
|
while (child) {
|
||||||
if (child.localName == tag) {
|
if (child.localName == tag) {
|
||||||
return child;
|
return child;
|
||||||
|
@ -96,16 +189,19 @@ PageMenu.prototype = {
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Return the location where the generated items should be inserted into the
|
||||||
|
// given popup. They should be inserted as the next sibling of the returned
|
||||||
|
// element.
|
||||||
getInsertionPoint: function(aPopup) {
|
getInsertionPoint: function(aPopup) {
|
||||||
if (aPopup.hasAttribute(this.PAGEMENU_ATTR))
|
if (aPopup.hasAttribute(this.PAGEMENU_ATTR))
|
||||||
return aPopup;
|
return aPopup;
|
||||||
|
|
||||||
var element = aPopup.firstChild;
|
let element = aPopup.firstChild;
|
||||||
while (element) {
|
while (element) {
|
||||||
if (element.localName == "menu") {
|
if (element.localName == "menu") {
|
||||||
var popup = this.getImmediateChild(element, "menupopup");
|
let popup = this.getImmediateChild(element, "menupopup");
|
||||||
if (popup) {
|
if (popup) {
|
||||||
var result = this.getInsertionPoint(popup);
|
let result = this.getInsertionPoint(popup);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -117,19 +213,20 @@ PageMenu.prototype = {
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Remove the generated content from the given popup.
|
||||||
removeGeneratedContent: function(aPopup) {
|
removeGeneratedContent: function(aPopup) {
|
||||||
var ungenerated = [];
|
let ungenerated = [];
|
||||||
ungenerated.push(aPopup);
|
ungenerated.push(aPopup);
|
||||||
|
|
||||||
var count;
|
let count;
|
||||||
while (0 != (count = ungenerated.length)) {
|
while (0 != (count = ungenerated.length)) {
|
||||||
var last = count - 1;
|
let last = count - 1;
|
||||||
var element = ungenerated[last];
|
let element = ungenerated[last];
|
||||||
ungenerated.splice(last, 1);
|
ungenerated.splice(last, 1);
|
||||||
|
|
||||||
var i = element.childNodes.length;
|
let i = element.childNodes.length;
|
||||||
while (i-- > 0) {
|
while (i-- > 0) {
|
||||||
var child = element.childNodes[i];
|
let child = element.childNodes[i];
|
||||||
if (!child.hasAttribute(this.GENERATEDITEMID_ATTR)) {
|
if (!child.hasAttribute(this.GENERATEDITEMID_ATTR)) {
|
||||||
ungenerated.push(child);
|
ungenerated.push(child);
|
||||||
continue;
|
continue;
|
||||||
|
@ -139,3 +236,78 @@ PageMenu.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This object is expected to be used from a parent process.
|
||||||
|
this.PageMenuParent = function PageMenuParent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
PageMenuParent.prototype = {
|
||||||
|
__proto__ : PageMenu.prototype,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a target node and popup, add the context menu to the popup. This is
|
||||||
|
* intended to be called when a single process is used. This is equivalent to
|
||||||
|
* calling PageMenuChild.build and PageMenuParent.addToPopup in sequence.
|
||||||
|
*
|
||||||
|
* Returns true if custom menu items were present.
|
||||||
|
*/
|
||||||
|
buildAndAddToPopup: function(aTarget, aPopup) {
|
||||||
|
let menuObject = this.maybeBuild(aTarget);
|
||||||
|
if (!menuObject) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.buildAndAttachMenuWithObject(menuObject, null, aPopup);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a JSON menu object and popup, add the context menu to the popup. This
|
||||||
|
* is intended to be called when the child page is in a different process.
|
||||||
|
* aBrowser should be the browser containing the page the context menu is
|
||||||
|
* displayed for, which may be null.
|
||||||
|
*
|
||||||
|
* Returns true if custom menu items were present.
|
||||||
|
*/
|
||||||
|
addToPopup: function(aMenu, aBrowser, aPopup) {
|
||||||
|
return this.buildAndAttachMenuWithObject(aMenu, aBrowser, aPopup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This object is expected to be used from a child process.
|
||||||
|
this.PageMenuChild = function PageMenuChild() {
|
||||||
|
}
|
||||||
|
|
||||||
|
PageMenuChild.prototype = {
|
||||||
|
__proto__ : PageMenu.prototype,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a target node, return a JSON object for the custom menu commands. The
|
||||||
|
* object will consist of a hierarchical structure of menus, menuitems or
|
||||||
|
* separators. Supported properties of each are:
|
||||||
|
* Menu: children, label, type="menu"
|
||||||
|
* Menuitems: checkbox, checked, disabled, icon, label, type="menuitem"
|
||||||
|
* Separators: type="separator"
|
||||||
|
*
|
||||||
|
* In addition, the id of each item will be used to identify the item
|
||||||
|
* when it is executed. The type will either be 'menu', 'menuitem' or
|
||||||
|
* 'separator'. The toplevel node will be a menu with a children property. The
|
||||||
|
* children property of a menu is an array of zero or more other items.
|
||||||
|
*
|
||||||
|
* If there is no menu associated with aTarget, null will be returned.
|
||||||
|
*/
|
||||||
|
build: function(aTarget) {
|
||||||
|
return this.maybeBuild(aTarget);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the id of a menu, execute the command associated with that menu. It
|
||||||
|
* is assumed that only one command will be executed so the builder is
|
||||||
|
* cleared afterwards.
|
||||||
|
*/
|
||||||
|
executeMenu: function(aId) {
|
||||||
|
if (this._builder) {
|
||||||
|
this._builder.click(aId);
|
||||||
|
this._builder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче