Merge m-c to mozilla-inbound
@ -64,6 +64,7 @@ tools repackage:: $(libs-preqs)
|
|||||||
sed -e 's/%MOZ_APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MOZ_APP_NAME%/$(MOZ_APP_NAME)/' -e 's/%APP_VERSION%/$(APP_VERSION)/' -e 's/%APP_NAME%/$(APP_NAME)/' -e 's/%APP_BINARY%/$(APP_BINARY)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
|
sed -e 's/%MOZ_APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MOZ_APP_NAME%/$(MOZ_APP_NAME)/' -e 's/%APP_VERSION%/$(APP_VERSION)/' -e 's/%APP_NAME%/$(APP_NAME)/' -e 's/%APP_BINARY%/$(APP_BINARY)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
|
||||||
sed -e 's/%APP_VERSION%/$(APP_VERSION)/' -e 's/%APP_NAME%/$(APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
|
sed -e 's/%APP_VERSION%/$(APP_VERSION)/' -e 's/%APP_NAME%/$(APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
|
||||||
rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
|
rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
|
||||||
|
mv $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/dependentlibs.list $(DIST)/$(APP_NAME).app/Contents/Resources
|
||||||
$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
|
$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
|
||||||
ifdef LIBXUL_SDK
|
ifdef LIBXUL_SDK
|
||||||
cp $(LIBXUL_DIST)/bin/xulrunner$(BIN_SUFFIX) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(APP_BINARY)
|
cp $(LIBXUL_DIST)/bin/xulrunner$(BIN_SUFFIX) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(APP_BINARY)
|
||||||
|
@ -42,6 +42,15 @@ endif
|
|||||||
|
|
||||||
MOZ_PACKAGER_MINIFY=1
|
MOZ_PACKAGER_MINIFY=1
|
||||||
|
|
||||||
|
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||||
|
ifndef _APPNAME
|
||||||
|
_APPNAME = $(MOZ_MACBUNDLE_NAME)
|
||||||
|
endif
|
||||||
|
ifndef _BINPATH
|
||||||
|
_BINPATH = /$(_APPNAME)/Contents/MacOS
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
||||||
|
|
||||||
# Note that JS_BINARY can be defined in packager.mk, so this test must come after
|
# Note that JS_BINARY can be defined in packager.mk, so this test must come after
|
||||||
|
@ -42,7 +42,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
[xpcom]
|
[xpcom]
|
||||||
|
#ifndef XP_MACOSX
|
||||||
@BINPATH@/dependentlibs.list
|
@BINPATH@/dependentlibs.list
|
||||||
|
#endif
|
||||||
#ifdef GKMEDIAS_SHARED_LIBRARY
|
#ifdef GKMEDIAS_SHARED_LIBRARY
|
||||||
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,24 +1,45 @@
|
|||||||
README.txt
|
# Due to Apple Mac OS X packaging requirements files that are in the same
|
||||||
@DLL_PREFIX@mozutils@DLL_SUFFIX@
|
# directory on other platforms must be located in different directories on
|
||||||
jssubloader/
|
# Mac OS X. The following defines allow specifying the Mac OS X bundle
|
||||||
|
# location which also work on other platforms.
|
||||||
|
#
|
||||||
|
# @DIR_MACOS@
|
||||||
|
# Equals Contents/MacOS/ on Mac OX X and is an empty string on other platforms.
|
||||||
|
#
|
||||||
|
# @DIR_RESOURCES@
|
||||||
|
# Equals Contents/Resources/ on Mac OX X and is an empty string on other
|
||||||
|
# platforms.
|
||||||
|
|
||||||
|
# Mac OS X v2 signing removals
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
run-mozilla.sh
|
@DIR_MACOS@active-update.xml
|
||||||
|
@DIR_MACOS@update-settings.ini
|
||||||
|
@DIR_MACOS@updates.xml
|
||||||
|
@DIR_MACOS@defaults/*
|
||||||
|
@DIR_MACOS@updates/*
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@DIR_MACOS@README.txt
|
||||||
|
@DIR_MACOS@@DLL_PREFIX@mozutils@DLL_SUFFIX@
|
||||||
|
@DIR_MACOS@jssubloader/
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@DIR_MACOS@run-mozilla.sh
|
||||||
#endif
|
#endif
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
mozcrt19.dll
|
mozcrt19.dll
|
||||||
mozcpp19.dll
|
mozcpp19.dll
|
||||||
#endif
|
#endif
|
||||||
defaults/preferences/services-sync.js
|
@DIR_MACOS@defaults/preferences/services-sync.js
|
||||||
defaults/preferences/healthreport-prefs.js
|
@DIR_MACOS@defaults/preferences/healthreport-prefs.js
|
||||||
components/dom_sms.xpt
|
@DIR_MACOS@components/dom_sms.xpt
|
||||||
components/dom_webspeech.xpt
|
@DIR_MACOS@components/dom_webspeech.xpt
|
||||||
#ifdef MOZ_FOLD_LIBS
|
#ifdef MOZ_FOLD_LIBS
|
||||||
@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
||||||
@DLL_PREFIX@plds4@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@plds4@DLL_SUFFIX@
|
||||||
@DLL_PREFIX@plc4@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@plc4@DLL_SUFFIX@
|
||||||
@DLL_PREFIX@ssl3@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@ssl3@DLL_SUFFIX@
|
||||||
@DLL_PREFIX@smime3@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@smime3@DLL_SUFFIX@
|
||||||
@DLL_PREFIX@nssutil3@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@nssutil3@DLL_SUFFIX@
|
||||||
@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
@DLL_PREFIX@xpcom@DLL_SUFFIX@
|
@DIR_MACOS@@DLL_PREFIX@xpcom@DLL_SUFFIX@
|
||||||
|
@ -76,7 +76,7 @@ ifndef LIBXUL_SDK
|
|||||||
# channel-prefs.js is handled separate from other prefs due to bug 756325
|
# channel-prefs.js is handled separate from other prefs due to bug 756325
|
||||||
libs:: $(srcdir)/profile/channel-prefs.js
|
libs:: $(srcdir)/profile/channel-prefs.js
|
||||||
$(NSINSTALL) -D $(DIST)/bin/defaults/pref
|
$(NSINSTALL) -D $(DIST)/bin/defaults/pref
|
||||||
$(call py_action,preprocessor,$(PREF_PPFLAGS) $(ACDEFINES) $^ -o $(DIST)/bin/defaults/pref/channel-prefs.js)
|
$(call py_action,preprocessor,-Fsubstitution $(PREF_PPFLAGS) $(ACDEFINES) $^ -o $(DIST)/bin/defaults/pref/channel-prefs.js)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libs:: $(srcdir)/blocklist.xml
|
libs:: $(srcdir)/blocklist.xml
|
||||||
@ -97,12 +97,6 @@ AB := $(firstword $(subst -, ,$(AB_CD)))
|
|||||||
clean clobber repackage::
|
clean clobber repackage::
|
||||||
$(RM) -r $(dist_dest)
|
$(RM) -r $(dist_dest)
|
||||||
|
|
||||||
ifdef LIBXUL_SDK
|
|
||||||
APPFILES = Resources
|
|
||||||
else
|
|
||||||
APPFILES = MacOS
|
|
||||||
endif
|
|
||||||
|
|
||||||
MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/config/buildid)
|
MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/config/buildid)
|
||||||
|
|
||||||
.PHONY: repackage
|
.PHONY: repackage
|
||||||
@ -113,7 +107,8 @@ tools repackage:: $(PROGRAM)
|
|||||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
|
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
|
||||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
||||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
|
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
|
||||||
rsync -a $(DIST)/bin/ $(dist_dest)/Contents/$(APPFILES)
|
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(dist_dest)/Contents/Resources
|
||||||
|
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(dist_dest)/Contents/MacOS
|
||||||
$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)
|
$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)
|
||||||
rsync -aL $(PROGRAM) $(dist_dest)/Contents/MacOS
|
rsync -aL $(PROGRAM) $(dist_dest)/Contents/MacOS
|
||||||
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
|
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
|
||||||
|
@ -1 +0,0 @@
|
|||||||
_CodeSignature/CodeResources
|
|
@ -147,7 +147,7 @@
|
|||||||
<key>CFBundleGetInfoString</key>
|
<key>CFBundleGetInfoString</key>
|
||||||
<string>%MAC_APP_NAME% %APP_VERSION%</string>
|
<string>%MAC_APP_NAME% %APP_VERSION%</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>firefox</string>
|
<string>firefox.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>%MOZ_MACBUNDLE_ID%</string>
|
<string>%MOZ_MACBUNDLE_ID%</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
9
browser/app/macbuild/Contents/MacOS-files.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/*.app/***
|
||||||
|
/*.dylib
|
||||||
|
/certutil
|
||||||
|
/firefox-bin
|
||||||
|
/pk12util
|
||||||
|
/ssltunnel
|
||||||
|
/webapprt-stub
|
||||||
|
/xpcshell
|
||||||
|
/XUL
|
@ -1,71 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>rules</key>
|
|
||||||
<dict>
|
|
||||||
<key>^Info.plist$</key>
|
|
||||||
<true/>
|
|
||||||
<key>^PkgInfo$</key>
|
|
||||||
<true/>
|
|
||||||
<key>^MacOS/</key>
|
|
||||||
<true/>
|
|
||||||
<key>^Resources/</key>
|
|
||||||
<true/>
|
|
||||||
<key>^MacOS/distribution/.*</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^MacOS/override.ini</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^MacOS/updates/.*</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^MacOS/active-update.xml$</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^MacOS/defaults/.*</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^MacOS/removed-files$</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^MacOS/updates.xml$</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^Updated.app/.*</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
<key>^updating/.*</key><dict>
|
|
||||||
<key>omit</key>
|
|
||||||
<true/>
|
|
||||||
<key>weight</key>
|
|
||||||
<real>10</real>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
@ -50,6 +50,9 @@
|
|||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
#define kOSXResourcesFolder "Resources"
|
||||||
|
#endif
|
||||||
#define kDesktopFolder "browser"
|
#define kDesktopFolder "browser"
|
||||||
#define kMetroFolder "metro"
|
#define kMetroFolder "metro"
|
||||||
#define kMetroAppIniFilename "metroapp.ini"
|
#define kMetroAppIniFilename "metroapp.ini"
|
||||||
@ -270,7 +273,12 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
|
|||||||
|
|
||||||
nsCOMPtr<nsIFile> greDir;
|
nsCOMPtr<nsIFile> greDir;
|
||||||
exeFile->GetParent(getter_AddRefs(greDir));
|
exeFile->GetParent(getter_AddRefs(greDir));
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
nsCOMPtr<nsIFile> parent;
|
||||||
|
greDir->GetParent(getter_AddRefs(parent));
|
||||||
|
greDir = parent.forget();
|
||||||
|
greDir->AppendNative(NS_LITERAL_CSTRING(kOSXResourcesFolder));
|
||||||
|
#endif
|
||||||
nsCOMPtr<nsIFile> appSubdir;
|
nsCOMPtr<nsIFile> appSubdir;
|
||||||
greDir->Clone(getter_AddRefs(appSubdir));
|
greDir->Clone(getter_AddRefs(appSubdir));
|
||||||
appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
|
appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
|
||||||
@ -564,6 +572,10 @@ InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
|
|||||||
|
|
||||||
// chop XPCOM_DLL off exePath
|
// chop XPCOM_DLL off exePath
|
||||||
*lastSlash = '\0';
|
*lastSlash = '\0';
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
|
||||||
|
strcpy(lastSlash + 1, kOSXResourcesFolder);
|
||||||
|
#endif
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
|
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
|
||||||
xreDirectory);
|
xreDirectory);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#filter substitution
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
||||||
|
@ -1730,3 +1730,5 @@ pref("experiments.supported", true);
|
|||||||
|
|
||||||
// Enable the OpenH264 plugin support in the addon manager.
|
// Enable the OpenH264 plugin support in the addon manager.
|
||||||
pref("media.gmp-gmpopenh264.provider.enabled", true);
|
pref("media.gmp-gmpopenh264.provider.enabled", true);
|
||||||
|
|
||||||
|
pref("browser.apps.URL", "https://marketplace.firefox.com/discovery/");
|
||||||
|
@ -470,6 +470,10 @@
|
|||||||
accesskey="&addons.accesskey;"
|
accesskey="&addons.accesskey;"
|
||||||
key="key_openAddons"
|
key="key_openAddons"
|
||||||
command="Tools:Addons"/>
|
command="Tools:Addons"/>
|
||||||
|
<menuitem id="menu_openApps"
|
||||||
|
label="&webapps.label;"
|
||||||
|
accesskey="&webapps.accesskey;"
|
||||||
|
oncommand="BrowserOpenApps();"/>
|
||||||
#ifdef MOZ_SERVICES_SYNC
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
<!-- only one of sync-setup or sync-menu will be showing at once -->
|
<!-- only one of sync-setup or sync-menu will be showing at once -->
|
||||||
<menuitem id="sync-setup"
|
<menuitem id="sync-setup"
|
||||||
|
@ -6092,6 +6092,11 @@ function BrowserOpenAddonsMgr(aView) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function BrowserOpenApps() {
|
||||||
|
let appsURL = Services.urlFormatter.formatURLPref("browser.apps.URL");
|
||||||
|
switchToTabHavingURI(appsURL, true)
|
||||||
|
}
|
||||||
|
|
||||||
function GetSearchFieldBookmarkData(node) {
|
function GetSearchFieldBookmarkData(node) {
|
||||||
var charset = node.ownerDocument.characterSet;
|
var charset = node.ownerDocument.characterSet;
|
||||||
|
|
||||||
|
@ -201,6 +201,11 @@ function test_multiple_windows() {
|
|||||||
ok(true, "Advanced preferences opened on info bar button press.");
|
ok(true, "Advanced preferences opened on info bar button press.");
|
||||||
executeSoon(function soon() {
|
executeSoon(function soon() {
|
||||||
prefWindowOpened = true;
|
prefWindowOpened = true;
|
||||||
|
// If the prefs are being displayed in a dialog we need to close it.
|
||||||
|
// If in a tab (ie, in-content prefs) it closes with the window.
|
||||||
|
if (!Services.prefs.getBoolPref("browser.preferences.inContent")) {
|
||||||
|
prefWin.close();
|
||||||
|
}
|
||||||
maybeFinish();
|
maybeFinish();
|
||||||
});
|
});
|
||||||
}, "advanced-pane-loaded", false);
|
}, "advanced-pane-loaded", false);
|
||||||
|
@ -150,7 +150,8 @@ function clearSubview(aSubview) {
|
|||||||
parent.appendChild(aSubview);
|
parent.appendChild(aSubview);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomizableWidgets = [{
|
const CustomizableWidgets = [
|
||||||
|
{
|
||||||
id: "history-panelmenu",
|
id: "history-panelmenu",
|
||||||
type: "view",
|
type: "view",
|
||||||
viewId: "PanelUI-history",
|
viewId: "PanelUI-history",
|
||||||
@ -923,6 +924,18 @@ const CustomizableWidgets = [{
|
|||||||
});
|
});
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
id: "web-apps-button",
|
||||||
|
label: "web-apps-button.label",
|
||||||
|
tooltiptext: "web-apps-button.tooltiptext",
|
||||||
|
onCommand: function(aEvent) {
|
||||||
|
let win = aEvent.target &&
|
||||||
|
aEvent.target.ownerDocument &&
|
||||||
|
aEvent.target.ownerDocument.defaultView;
|
||||||
|
if (win && typeof win.BrowserOpenApps == "function") {
|
||||||
|
win.BrowserOpenApps();
|
||||||
|
}
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
@ -125,12 +125,11 @@ static void
|
|||||||
AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
|
AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIFile> searchPlugins;
|
nsCOMPtr<nsIFile> searchPlugins;
|
||||||
nsresult rv = aDirSvc->Get(XRE_EXECUTABLE_FILE,
|
nsresult rv = aDirSvc->Get(XRE_APP_DISTRIBUTION_DIR,
|
||||||
NS_GET_IID(nsIFile),
|
NS_GET_IID(nsIFile),
|
||||||
getter_AddRefs(searchPlugins));
|
getter_AddRefs(searchPlugins));
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return;
|
return;
|
||||||
searchPlugins->SetNativeLeafName(NS_LITERAL_CSTRING("distribution"));
|
|
||||||
searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins"));
|
searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins"));
|
||||||
|
|
||||||
bool exists;
|
bool exists;
|
||||||
|
@ -26,12 +26,16 @@ this.DistributionCustomizer = function DistributionCustomizer() {
|
|||||||
} catch(ex) {}
|
} catch(ex) {}
|
||||||
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||||
getService(Ci.nsIProperties);
|
getService(Ci.nsIProperties);
|
||||||
let iniFile = loadFromProfile ? dirSvc.get("ProfD", Ci.nsIFile)
|
try {
|
||||||
: dirSvc.get("XREExeF", Ci.nsIFile);
|
let iniFile = loadFromProfile ? dirSvc.get("ProfD", Ci.nsIFile)
|
||||||
iniFile.leafName = "distribution";
|
: dirSvc.get("XREAppDist", Ci.nsIFile);
|
||||||
iniFile.append("distribution.ini");
|
if (loadFromProfile) {
|
||||||
if (iniFile.exists())
|
iniFile.leafName = "distribution";
|
||||||
this._iniFile = iniFile;
|
}
|
||||||
|
iniFile.append("distribution.ini");
|
||||||
|
if (iniFile.exists())
|
||||||
|
this._iniFile = iniFile;
|
||||||
|
} catch(ex) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
DistributionCustomizer.prototype = {
|
DistributionCustomizer.prototype = {
|
||||||
|
@ -93,7 +93,7 @@ FontInspector.prototype = {
|
|||||||
|
|
||||||
// We don't get fonts for a node, but for a range
|
// We don't get fonts for a node, but for a range
|
||||||
let rng = contentDocument.createRange();
|
let rng = contentDocument.createRange();
|
||||||
rng.selectNode(node);
|
rng.selectNodeContents(node);
|
||||||
let fonts = DOMUtils.getUsedFontFaces(rng);
|
let fonts = DOMUtils.getUsedFontFaces(rng);
|
||||||
let fontsArray = [];
|
let fontsArray = [];
|
||||||
for (let i = 0; i < fonts.length; i++) {
|
for (let i = 0; i < fonts.length; i++) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
const {Cu, Ci} = require("chrome");
|
const {Cu, Ci} = require("chrome");
|
||||||
let EventEmitter = require("devtools/toolkit/event-emitter");
|
let EventEmitter = require("devtools/toolkit/event-emitter");
|
||||||
|
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API
|
* API
|
||||||
@ -225,11 +226,18 @@ Selection.prototype = {
|
|||||||
if (rawNode) {
|
if (rawNode) {
|
||||||
try {
|
try {
|
||||||
let doc = this.document;
|
let doc = this.document;
|
||||||
return (doc && doc.defaultView && doc.documentElement.contains(rawNode));
|
if (doc && doc.defaultView) {
|
||||||
|
let docEl = doc.documentElement;
|
||||||
|
let bindingParent = LayoutHelpers.getRootBindingParent(rawNode);
|
||||||
|
|
||||||
|
if (docEl.contains(bindingParent)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// "can't access dead object" error
|
// "can't access dead object" error
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(node) {
|
while(node) {
|
||||||
@ -252,6 +260,14 @@ Selection.prototype = {
|
|||||||
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ELEMENT_NODE;
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ELEMENT_NODE;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isPseudoElementNode: function() {
|
||||||
|
return this.isNode() && this.nodeFront.isPseudoElement;
|
||||||
|
},
|
||||||
|
|
||||||
|
isAnonymousNode: function() {
|
||||||
|
return this.isNode() && this.nodeFront.isAnonymous;
|
||||||
|
},
|
||||||
|
|
||||||
isAttributeNode: function() {
|
isAttributeNode: function() {
|
||||||
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ATTRIBUTE_NODE;
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ATTRIBUTE_NODE;
|
||||||
},
|
},
|
||||||
|
@ -156,6 +156,10 @@ HTMLBreadcrumbs.prototype = {
|
|||||||
prettyPrintNodeAsText: function BC_prettyPrintNodeText(aNode)
|
prettyPrintNodeAsText: function BC_prettyPrintNodeText(aNode)
|
||||||
{
|
{
|
||||||
let text = aNode.tagName.toLowerCase();
|
let text = aNode.tagName.toLowerCase();
|
||||||
|
if (aNode.isPseudoElement) {
|
||||||
|
text = aNode.isBeforePseudoElement ? "::before" : "::after";
|
||||||
|
}
|
||||||
|
|
||||||
if (aNode.id) {
|
if (aNode.id) {
|
||||||
text += "#" + aNode.id;
|
text += "#" + aNode.id;
|
||||||
}
|
}
|
||||||
@ -201,6 +205,9 @@ HTMLBreadcrumbs.prototype = {
|
|||||||
pseudosLabel.className = "breadcrumbs-widget-item-pseudo-classes plain";
|
pseudosLabel.className = "breadcrumbs-widget-item-pseudo-classes plain";
|
||||||
|
|
||||||
let tagText = aNode.tagName.toLowerCase();
|
let tagText = aNode.tagName.toLowerCase();
|
||||||
|
if (aNode.isPseudoElement) {
|
||||||
|
tagText = aNode.isBeforePseudoElement ? "::before" : "::after";
|
||||||
|
}
|
||||||
let idText = aNode.id ? ("#" + aNode.id) : "";
|
let idText = aNode.id ? ("#" + aNode.id) : "";
|
||||||
let classesText = "";
|
let classesText = "";
|
||||||
|
|
||||||
|
@ -584,7 +584,10 @@ InspectorPanel.prototype = {
|
|||||||
* Disable the delete item if needed. Update the pseudo classes.
|
* Disable the delete item if needed. Update the pseudo classes.
|
||||||
*/
|
*/
|
||||||
_setupNodeMenu: function InspectorPanel_setupNodeMenu() {
|
_setupNodeMenu: function InspectorPanel_setupNodeMenu() {
|
||||||
let isSelectionElement = this.selection.isElementNode();
|
let isSelectionElement = this.selection.isElementNode() &&
|
||||||
|
!this.selection.isPseudoElementNode();
|
||||||
|
let isEditableElement = isSelectionElement &&
|
||||||
|
!this.selection.isAnonymousNode();
|
||||||
|
|
||||||
// Set the pseudo classes
|
// Set the pseudo classes
|
||||||
for (let name of ["hover", "active", "focus"]) {
|
for (let name of ["hover", "active", "focus"]) {
|
||||||
@ -601,10 +604,10 @@ InspectorPanel.prototype = {
|
|||||||
|
|
||||||
// Disable delete item if needed
|
// Disable delete item if needed
|
||||||
let deleteNode = this.panelDoc.getElementById("node-menu-delete");
|
let deleteNode = this.panelDoc.getElementById("node-menu-delete");
|
||||||
if (this.selection.isRoot() || this.selection.isDocumentTypeNode()) {
|
if (isEditableElement) {
|
||||||
deleteNode.setAttribute("disabled", "true");
|
|
||||||
} else {
|
|
||||||
deleteNode.removeAttribute("disabled");
|
deleteNode.removeAttribute("disabled");
|
||||||
|
} else {
|
||||||
|
deleteNode.setAttribute("disabled", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable / enable "Copy Unique Selector", "Copy inner HTML" &
|
// Disable / enable "Copy Unique Selector", "Copy inner HTML" &
|
||||||
@ -625,7 +628,7 @@ InspectorPanel.prototype = {
|
|||||||
// Enable the "edit HTML" item if the selection is an element and the root
|
// Enable the "edit HTML" item if the selection is an element and the root
|
||||||
// actor has the appropriate trait (isOuterHTMLEditable)
|
// actor has the appropriate trait (isOuterHTMLEditable)
|
||||||
let editHTML = this.panelDoc.getElementById("node-menu-edithtml");
|
let editHTML = this.panelDoc.getElementById("node-menu-edithtml");
|
||||||
if (this.isOuterHTMLEditable && isSelectionElement) {
|
if (isEditableElement && this.isOuterHTMLEditable) {
|
||||||
editHTML.removeAttribute("disabled");
|
editHTML.removeAttribute("disabled");
|
||||||
} else {
|
} else {
|
||||||
editHTML.setAttribute("disabled", "true");
|
editHTML.setAttribute("disabled", "true");
|
||||||
@ -635,7 +638,7 @@ InspectorPanel.prototype = {
|
|||||||
// the root actor has the appropriate trait (isOuterHTMLEditable) and if
|
// the root actor has the appropriate trait (isOuterHTMLEditable) and if
|
||||||
// the clipbard content is appropriate.
|
// the clipbard content is appropriate.
|
||||||
let pasteOuterHTML = this.panelDoc.getElementById("node-menu-pasteouterhtml");
|
let pasteOuterHTML = this.panelDoc.getElementById("node-menu-pasteouterhtml");
|
||||||
if (this.isOuterHTMLEditable && isSelectionElement &&
|
if (isEditableElement && this.isOuterHTMLEditable &&
|
||||||
this._getClipboardContentForOuterHTML()) {
|
this._getClipboardContentForOuterHTML()) {
|
||||||
pasteOuterHTML.removeAttribute("disabled");
|
pasteOuterHTML.removeAttribute("disabled");
|
||||||
} else {
|
} else {
|
||||||
@ -646,7 +649,7 @@ InspectorPanel.prototype = {
|
|||||||
// which essentially checks if it's an image or canvas tag
|
// which essentially checks if it's an image or canvas tag
|
||||||
let copyImageData = this.panelDoc.getElementById("node-menu-copyimagedatauri");
|
let copyImageData = this.panelDoc.getElementById("node-menu-copyimagedatauri");
|
||||||
let markupContainer = this.markup.getContainer(this.selection.nodeFront);
|
let markupContainer = this.markup.getContainer(this.selection.nodeFront);
|
||||||
if (markupContainer && markupContainer.isPreviewable()) {
|
if (isSelectionElement && markupContainer && markupContainer.isPreviewable()) {
|
||||||
copyImageData.removeAttribute("disabled");
|
copyImageData.removeAttribute("disabled");
|
||||||
} else {
|
} else {
|
||||||
copyImageData.setAttribute("disabled", "true");
|
copyImageData.setAttribute("disabled", "true");
|
||||||
|
@ -51,4 +51,26 @@ let test = asyncTest(function*() {
|
|||||||
is(labelId.textContent, "#" + id,
|
is(labelId.textContent, "#" + id,
|
||||||
"Node #" + node.nodeId + ": selection matches");
|
"Node #" + node.nodeId + ": selection matches");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yield testPseudoElements(inspector, container);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function *testPseudoElements(inspector, container) {
|
||||||
|
info ("Checking for pseudo elements");
|
||||||
|
|
||||||
|
let pseudoParent = getNodeFront(getNode("#pseudo-container"));
|
||||||
|
let children = yield inspector.walker.children(pseudoParent);
|
||||||
|
is (children.nodes.length, 2, "Pseudo children returned from walker");
|
||||||
|
|
||||||
|
let beforeElement = children.nodes[0];
|
||||||
|
let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||||
|
let nodeSelected = selectNode(beforeElement, inspector);
|
||||||
|
yield Promise.all([breadcrumbsUpdated, nodeSelected]);
|
||||||
|
is(container.childNodes[3].textContent, "::before", "::before shows up in breadcrumb");
|
||||||
|
|
||||||
|
let afterElement = children.nodes[1];
|
||||||
|
breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||||
|
nodeSelected = selectNode(afterElement, inspector);
|
||||||
|
yield Promise.all([breadcrumbsUpdated, nodeSelected]);
|
||||||
|
is(container.childNodes[3].textContent, "::after", "::before shows up in breadcrumb");
|
||||||
|
}
|
||||||
|
@ -7,6 +7,12 @@
|
|||||||
border: 1px solid red;
|
border: 1px solid red;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
#pseudo-container::before {
|
||||||
|
content: 'before';
|
||||||
|
}
|
||||||
|
#pseudo-container::after {
|
||||||
|
content: 'after';
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -36,5 +42,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
<div id='pseudo-container'></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -155,7 +155,7 @@ function selectAndHighlightNode(nodeOrSelector, inspector) {
|
|||||||
/**
|
/**
|
||||||
* Set the inspector's current selection to a node or to the first match of the
|
* Set the inspector's current selection to a node or to the first match of the
|
||||||
* given css selector.
|
* given css selector.
|
||||||
* @param {String|DOMNode} nodeOrSelector
|
* @param {String|DOMNode|NodeFront} nodeOrSelector
|
||||||
* @param {InspectorPanel} inspector
|
* @param {InspectorPanel} inspector
|
||||||
* The instance of InspectorPanel currently loaded in the toolbox
|
* The instance of InspectorPanel currently loaded in the toolbox
|
||||||
* @param {String} reason
|
* @param {String} reason
|
||||||
@ -169,7 +169,11 @@ function selectNode(nodeOrSelector, inspector, reason="test") {
|
|||||||
|
|
||||||
let node = getNode(nodeOrSelector);
|
let node = getNode(nodeOrSelector);
|
||||||
let updated = inspector.once("inspector-updated");
|
let updated = inspector.once("inspector-updated");
|
||||||
inspector.selection.setNode(node, reason);
|
if (node._form) {
|
||||||
|
inspector.selection.setNodeFront(node, reason);
|
||||||
|
} else {
|
||||||
|
inspector.selection.setNode(node, reason);
|
||||||
|
}
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@
|
|||||||
transition: background .5s;
|
transition: background .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-line .open, .tag-line .close, .comment {
|
.tag-line {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ const {HTMLEditor} = require("devtools/markupview/html-editor");
|
|||||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||||
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||||
|
const Heritage = require("sdk/core/heritage");
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||||
Cu.import("resource://gre/modules/devtools/Templater.jsm");
|
Cu.import("resource://gre/modules/devtools/Templater.jsm");
|
||||||
@ -40,6 +41,9 @@ loader.lazyGetter(this, "AutocompletePopup", () => {
|
|||||||
*
|
*
|
||||||
* MarkupContainer - the structure that holds an editor and its
|
* MarkupContainer - the structure that holds an editor and its
|
||||||
* immediate children in the markup panel.
|
* immediate children in the markup panel.
|
||||||
|
* - MarkupElementContainer: markup container for element nodes
|
||||||
|
* - MarkupTextContainer: markup container for text / comment nodes
|
||||||
|
* - MarkupReadonlyContainer: markup container for other nodes
|
||||||
* Node - A content node.
|
* Node - A content node.
|
||||||
* object.elt - A UI element in the markup panel.
|
* object.elt - A UI element in the markup panel.
|
||||||
*/
|
*/
|
||||||
@ -186,7 +190,7 @@ MarkupView.prototype = {
|
|||||||
parentNode = parentNode.parentNode;
|
parentNode = parentNode.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container) {
|
if (container instanceof MarkupElementContainer) {
|
||||||
// With the newly found container, delegate the tooltip content creation
|
// With the newly found container, delegate the tooltip content creation
|
||||||
// and decision to show or not the tooltip
|
// and decision to show or not the tooltip
|
||||||
container._buildEventTooltipContent(event.target, this.tooltip);
|
container._buildEventTooltipContent(event.target, this.tooltip);
|
||||||
@ -301,7 +305,7 @@ MarkupView.prototype = {
|
|||||||
* tooltip.
|
* tooltip.
|
||||||
* Delegates the actual decision to the corresponding MarkupContainer instance
|
* Delegates the actual decision to the corresponding MarkupContainer instance
|
||||||
* if one is found.
|
* if one is found.
|
||||||
* @return the promise returned by MarkupContainer._isImagePreviewTarget
|
* @return the promise returned by MarkupElementContainer._isImagePreviewTarget
|
||||||
*/
|
*/
|
||||||
_isImagePreviewTarget: function(target) {
|
_isImagePreviewTarget: function(target) {
|
||||||
// From the target passed here, let's find the parent MarkupContainer
|
// From the target passed here, let's find the parent MarkupContainer
|
||||||
@ -315,10 +319,10 @@ MarkupView.prototype = {
|
|||||||
parent = parent.parentNode;
|
parent = parent.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container) {
|
if (container instanceof MarkupElementContainer) {
|
||||||
// With the newly found container, delegate the tooltip content creation
|
// With the newly found container, delegate the tooltip content creation
|
||||||
// and decision to show or not the tooltip
|
// and decision to show or not the tooltip
|
||||||
return container._isImagePreviewTarget(target, this.tooltip);
|
return container.isImagePreviewTarget(target, this.tooltip);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -507,7 +511,8 @@ MarkupView.prototype = {
|
|||||||
*/
|
*/
|
||||||
deleteNode: function(aNode) {
|
deleteNode: function(aNode) {
|
||||||
if (aNode.isDocumentElement ||
|
if (aNode.isDocumentElement ||
|
||||||
aNode.nodeType == Ci.nsIDOMNode.DOCUMENT_TYPE_NODE) {
|
aNode.nodeType == Ci.nsIDOMNode.DOCUMENT_TYPE_NODE ||
|
||||||
|
aNode.isAnonymous) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +573,7 @@ MarkupView.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Make sure a node is included in the markup tool.
|
* Make sure a node is included in the markup tool.
|
||||||
*
|
*
|
||||||
* @param DOMNode aNode
|
* @param NodeFront aNode
|
||||||
* The node in the content document.
|
* The node in the content document.
|
||||||
* @param boolean aFlashNode
|
* @param boolean aFlashNode
|
||||||
* Whether the newly imported node should be flashed
|
* Whether the newly imported node should be flashed
|
||||||
@ -583,15 +588,23 @@ MarkupView.prototype = {
|
|||||||
return this.getContainer(aNode);
|
return this.getContainer(aNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let container;
|
||||||
|
let {nodeType, isPseudoElement} = aNode;
|
||||||
if (aNode === this.walker.rootNode) {
|
if (aNode === this.walker.rootNode) {
|
||||||
var container = new RootContainer(this, aNode);
|
container = new RootContainer(this, aNode);
|
||||||
this._elt.appendChild(container.elt);
|
this._elt.appendChild(container.elt);
|
||||||
this._rootNode = aNode;
|
this._rootNode = aNode;
|
||||||
|
} else if (nodeType == Ci.nsIDOMNode.ELEMENT_NODE && !isPseudoElement) {
|
||||||
|
container = new MarkupElementContainer(this, aNode, this._inspector);
|
||||||
|
} else if (nodeType == Ci.nsIDOMNode.COMMENT_NODE ||
|
||||||
|
nodeType == Ci.nsIDOMNode.TEXT_NODE) {
|
||||||
|
container = new MarkupTextContainer(this, aNode, this._inspector);
|
||||||
} else {
|
} else {
|
||||||
var container = new MarkupContainer(this, aNode, this._inspector);
|
container = new MarkupReadOnlyContainer(this, aNode, this._inspector);
|
||||||
if (aFlashNode) {
|
}
|
||||||
container.flashMutation();
|
|
||||||
}
|
if (aFlashNode) {
|
||||||
|
container.flashMutation();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._containers.set(aNode, container);
|
this._containers.set(aNode, container);
|
||||||
@ -961,7 +974,7 @@ MarkupView.prototype = {
|
|||||||
let parentContainer = this.getContainer(parent);
|
let parentContainer = this.getContainer(parent);
|
||||||
if (parentContainer) {
|
if (parentContainer) {
|
||||||
parentContainer.childrenDirty = true;
|
parentContainer.childrenDirty = true;
|
||||||
this._updateChildren(parentContainer, {expand: node});
|
this._updateChildren(parentContainer, {expand: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1306,74 +1319,69 @@ MarkupView.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main structure for storing a document node in the markup
|
* The main structure for storing a document node in the markup
|
||||||
* tree. Manages creation of the editor for the node and
|
* tree. Manages creation of the editor for the node and
|
||||||
* a <ul> for placing child elements, and expansion/collapsing
|
* a <ul> for placing child elements, and expansion/collapsing
|
||||||
* of the element.
|
* of the element.
|
||||||
*
|
*
|
||||||
* @param MarkupView aMarkupView
|
* This should not be instantiated directly, instead use one of:
|
||||||
* The markup view that owns this container.
|
* MarkupReadOnlyContainer
|
||||||
* @param DOMNode aNode
|
* MarkupTextContainer
|
||||||
* The node to display.
|
* MarkupElementContainer
|
||||||
* @param Inspector aInspector
|
|
||||||
* The inspector tool container the markup-view
|
|
||||||
*/
|
*/
|
||||||
function MarkupContainer(aMarkupView, aNode, aInspector) {
|
function MarkupContainer() { }
|
||||||
this.markup = aMarkupView;
|
|
||||||
this.doc = this.markup.doc;
|
|
||||||
this.undo = this.markup.undo;
|
|
||||||
this.node = aNode;
|
|
||||||
this._inspector = aInspector;
|
|
||||||
|
|
||||||
if (aNode.nodeType == Ci.nsIDOMNode.TEXT_NODE) {
|
|
||||||
this.editor = new TextEditor(this, aNode, "text");
|
|
||||||
} else if (aNode.nodeType == Ci.nsIDOMNode.COMMENT_NODE) {
|
|
||||||
this.editor = new TextEditor(this, aNode, "comment");
|
|
||||||
} else if (aNode.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) {
|
|
||||||
this.editor = new ElementEditor(this, aNode);
|
|
||||||
} else if (aNode.nodeType == Ci.nsIDOMNode.DOCUMENT_TYPE_NODE) {
|
|
||||||
this.editor = new DoctypeEditor(this, aNode);
|
|
||||||
} else {
|
|
||||||
this.editor = new GenericEditor(this, aNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The template will fill the following properties
|
|
||||||
this.elt = null;
|
|
||||||
this.expander = null;
|
|
||||||
this.tagState = null;
|
|
||||||
this.tagLine = null;
|
|
||||||
this.children = null;
|
|
||||||
this.markup.template("container", this);
|
|
||||||
this.elt.container = this;
|
|
||||||
this.children.container = this;
|
|
||||||
|
|
||||||
// Expanding/collapsing the node on dblclick of the whole tag-line element
|
|
||||||
this._onToggle = this._onToggle.bind(this);
|
|
||||||
this.elt.addEventListener("dblclick", this._onToggle, false);
|
|
||||||
this.expander.addEventListener("click", this._onToggle, false);
|
|
||||||
|
|
||||||
// Appending the editor element and attaching event listeners
|
|
||||||
this.tagLine.appendChild(this.editor.elt);
|
|
||||||
|
|
||||||
this._onMouseDown = this._onMouseDown.bind(this);
|
|
||||||
this.elt.addEventListener("mousedown", this._onMouseDown, false);
|
|
||||||
|
|
||||||
// Prepare the image preview tooltip data if any
|
|
||||||
this._prepareImagePreview();
|
|
||||||
|
|
||||||
// Marking the node as shown or hidden
|
|
||||||
this.isDisplayed = this.node.isDisplayed;
|
|
||||||
}
|
|
||||||
|
|
||||||
MarkupContainer.prototype = {
|
MarkupContainer.prototype = {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the MarkupContainer. Should be called while one
|
||||||
|
* of the other contain classes is instantiated.
|
||||||
|
*
|
||||||
|
* @param MarkupView markupView
|
||||||
|
* The markup view that owns this container.
|
||||||
|
* @param NodeFront node
|
||||||
|
* The node to display.
|
||||||
|
* @param string templateID
|
||||||
|
* Which template to render for this container
|
||||||
|
*/
|
||||||
|
initialize: function(markupView, node, templateID) {
|
||||||
|
this.markup = markupView;
|
||||||
|
this.node = node;
|
||||||
|
this.undo = this.markup.undo;
|
||||||
|
|
||||||
|
// The template will fill the following properties
|
||||||
|
this.elt = null;
|
||||||
|
this.expander = null;
|
||||||
|
this.tagState = null;
|
||||||
|
this.tagLine = null;
|
||||||
|
this.children = null;
|
||||||
|
this.markup.template(templateID, this);
|
||||||
|
this.elt.container = this;
|
||||||
|
|
||||||
|
// Binding event listeners
|
||||||
|
this._onMouseDown = this._onMouseDown.bind(this);
|
||||||
|
this.elt.addEventListener("mousedown", this._onMouseDown, false);
|
||||||
|
|
||||||
|
this._onToggle = this._onToggle.bind(this);
|
||||||
|
|
||||||
|
// Expanding/collapsing the node on dblclick of the whole tag-line element
|
||||||
|
this.elt.addEventListener("dblclick", this._onToggle, false);
|
||||||
|
|
||||||
|
if (this.expander) {
|
||||||
|
this.expander.addEventListener("click", this._onToggle, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marking the node as shown or hidden
|
||||||
|
this.isDisplayed = this.node.isDisplayed;
|
||||||
|
},
|
||||||
|
|
||||||
toString: function() {
|
toString: function() {
|
||||||
return "[MarkupContainer for " + this.node + "]";
|
return "[MarkupContainer for " + this.node + "]";
|
||||||
},
|
},
|
||||||
|
|
||||||
isPreviewable: function() {
|
isPreviewable: function() {
|
||||||
if (this.node.tagName) {
|
if (this.node.tagName && !this.node.isPseudoElement) {
|
||||||
let tagName = this.node.tagName.toLowerCase();
|
let tagName = this.node.tagName.toLowerCase();
|
||||||
let srcAttr = this.editor.getAttributeElement("src");
|
let srcAttr = this.editor.getAttributeElement("src");
|
||||||
let isImage = tagName === "img" && srcAttr;
|
let isImage = tagName === "img" && srcAttr;
|
||||||
@ -1385,60 +1393,6 @@ MarkupContainer.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* If the node is an image or canvas (@see isPreviewable), then get the
|
|
||||||
* image data uri from the server so that it can then later be previewed in
|
|
||||||
* a tooltip if needed.
|
|
||||||
* Stores a promise in this.tooltipData.data that resolves when the data has
|
|
||||||
* been retrieved
|
|
||||||
*/
|
|
||||||
_prepareImagePreview: function() {
|
|
||||||
if (this.isPreviewable()) {
|
|
||||||
// Get the image data for later so that when the user actually hovers over
|
|
||||||
// the element, the tooltip does contain the image
|
|
||||||
let def = promise.defer();
|
|
||||||
|
|
||||||
this.tooltipData = {
|
|
||||||
target: this.editor.getAttributeElement("src") || this.editor.tag,
|
|
||||||
data: def.promise
|
|
||||||
};
|
|
||||||
|
|
||||||
let maxDim = Services.prefs.getIntPref("devtools.inspector.imagePreviewTooltipSize");
|
|
||||||
this.node.getImageData(maxDim).then(data => {
|
|
||||||
data.data.string().then(str => {
|
|
||||||
let res = {data: str, size: data.size};
|
|
||||||
// Resolving the data promise and, to always keep tooltipData.data
|
|
||||||
// as a promise, create a new one that resolves immediately
|
|
||||||
def.resolve(res);
|
|
||||||
this.tooltipData.data = promise.resolve(res);
|
|
||||||
});
|
|
||||||
}, () => {
|
|
||||||
this.tooltipData.data = promise.reject();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed by MarkupView._isImagePreviewTarget which is itself called when the
|
|
||||||
* mouse hovers over a target in the markup-view.
|
|
||||||
* Checks if the target is indeed something we want to have an image tooltip
|
|
||||||
* preview over and, if so, inserts content into the tooltip.
|
|
||||||
* @return a promise that resolves when the content has been inserted or
|
|
||||||
* rejects if no preview is required. This promise is then used by Tooltip.js
|
|
||||||
* to decide if/when to show the tooltip
|
|
||||||
*/
|
|
||||||
_isImagePreviewTarget: function(target, tooltip) {
|
|
||||||
if (!this.tooltipData || this.tooltipData.target !== target) {
|
|
||||||
return promise.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.tooltipData.data.then(({data, size}) => {
|
|
||||||
tooltip.setImageContent(data, size);
|
|
||||||
}, () => {
|
|
||||||
tooltip.setBrokenImageContent();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the element has displayed or not
|
* Show the element has displayed or not
|
||||||
*/
|
*/
|
||||||
@ -1449,37 +1403,6 @@ MarkupContainer.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
copyImageDataUri: function() {
|
|
||||||
// We need to send again a request to gettooltipData even if one was sent for
|
|
||||||
// the tooltip, because we want the full-size image
|
|
||||||
this.node.getImageData().then(data => {
|
|
||||||
data.data.string().then(str => {
|
|
||||||
clipboardHelper.copyString(str, this.markup.doc);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_buildEventTooltipContent: function(target, tooltip) {
|
|
||||||
if (target.hasAttribute("data-event")) {
|
|
||||||
tooltip.hide(target);
|
|
||||||
|
|
||||||
this.node.getEventListenerInfo().then(listenerInfo => {
|
|
||||||
tooltip.setEventContent({
|
|
||||||
eventListenerInfos: listenerInfo,
|
|
||||||
toolbox: this._inspector.toolbox
|
|
||||||
});
|
|
||||||
|
|
||||||
this.markup._makeTooltipPersistent(true);
|
|
||||||
tooltip.once("hidden", () => {
|
|
||||||
this.markup._makeTooltipPersistent(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
tooltip.show(target);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the current node has children. The MarkupView
|
* True if the current node has children. The MarkupView
|
||||||
* will set this attribute for the MarkupContainer.
|
* will set this attribute for the MarkupContainer.
|
||||||
@ -1492,6 +1415,10 @@ MarkupContainer.prototype = {
|
|||||||
|
|
||||||
set hasChildren(aValue) {
|
set hasChildren(aValue) {
|
||||||
this._hasChildren = aValue;
|
this._hasChildren = aValue;
|
||||||
|
if (!this.expander) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (aValue) {
|
if (aValue) {
|
||||||
this.expander.style.visibility = "visible";
|
this.expander.style.visibility = "visible";
|
||||||
} else {
|
} else {
|
||||||
@ -1499,10 +1426,6 @@ MarkupContainer.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
parentContainer: function() {
|
|
||||||
return this.elt.parentNode ? this.elt.parentNode.container : null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the node has been visually expanded in the tree.
|
* True if the node has been visually expanded in the tree.
|
||||||
*/
|
*/
|
||||||
@ -1511,32 +1434,35 @@ MarkupContainer.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
set expanded(aValue) {
|
set expanded(aValue) {
|
||||||
|
if (!this.expander) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (aValue && this.elt.classList.contains("collapsed")) {
|
if (aValue && this.elt.classList.contains("collapsed")) {
|
||||||
// Expanding a node means cloning its "inline" closing tag into a new
|
// Expanding a node means cloning its "inline" closing tag into a new
|
||||||
// tag-line that the user can interact with and showing the children.
|
// tag-line that the user can interact with and showing the children.
|
||||||
if (this.editor instanceof ElementEditor) {
|
let closingTag = this.elt.querySelector(".close");
|
||||||
let closingTag = this.elt.querySelector(".close");
|
if (closingTag) {
|
||||||
if (closingTag) {
|
if (!this.closeTagLine) {
|
||||||
if (!this.closeTagLine) {
|
let line = this.markup.doc.createElement("div");
|
||||||
let line = this.markup.doc.createElement("div");
|
line.classList.add("tag-line");
|
||||||
line.classList.add("tag-line");
|
|
||||||
|
|
||||||
let tagState = this.markup.doc.createElement("div");
|
let tagState = this.markup.doc.createElement("div");
|
||||||
tagState.classList.add("tag-state");
|
tagState.classList.add("tag-state");
|
||||||
line.appendChild(tagState);
|
line.appendChild(tagState);
|
||||||
|
|
||||||
line.appendChild(closingTag.cloneNode(true));
|
line.appendChild(closingTag.cloneNode(true));
|
||||||
|
|
||||||
this.closeTagLine = line;
|
this.closeTagLine = line;
|
||||||
}
|
|
||||||
this.elt.appendChild(this.closeTagLine);
|
|
||||||
}
|
}
|
||||||
|
this.elt.appendChild(this.closeTagLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.elt.classList.remove("collapsed");
|
this.elt.classList.remove("collapsed");
|
||||||
this.expander.setAttribute("open", "");
|
this.expander.setAttribute("open", "");
|
||||||
this.hovered = false;
|
this.hovered = false;
|
||||||
} else if (!aValue) {
|
} else if (!aValue) {
|
||||||
if (this.editor instanceof ElementEditor && this.closeTagLine) {
|
if (this.closeTagLine) {
|
||||||
this.elt.removeChild(this.closeTagLine);
|
this.elt.removeChild(this.closeTagLine);
|
||||||
}
|
}
|
||||||
this.elt.classList.add("collapsed");
|
this.elt.classList.add("collapsed");
|
||||||
@ -1544,12 +1470,8 @@ MarkupContainer.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_onToggle: function(event) {
|
parentContainer: function() {
|
||||||
this.markup.navigate(this);
|
return this.elt.parentNode ? this.elt.parentNode.container : null;
|
||||||
if(this.hasChildren) {
|
|
||||||
this.markup.setNodeExpanded(this.node, !this.expanded, event.altKey);
|
|
||||||
}
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMouseDown: function(event) {
|
_onMouseDown: function(event) {
|
||||||
@ -1695,11 +1617,27 @@ MarkupContainer.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onToggle: function(event) {
|
||||||
|
this.markup.navigate(this);
|
||||||
|
if (this.hasChildren) {
|
||||||
|
this.markup.setNodeExpanded(this.node, !this.expanded, event.altKey);
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get rid of event listeners and references, when the container is no longer
|
* Get rid of event listeners and references, when the container is no longer
|
||||||
* needed
|
* needed
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
|
// Remove event listeners
|
||||||
|
this.elt.removeEventListener("mousedown", this._onMouseDown, false);
|
||||||
|
this.elt.removeEventListener("dblclick", this._onToggle, false);
|
||||||
|
|
||||||
|
if (this.expander) {
|
||||||
|
this.expander.removeEventListener("click", this._onToggle, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Recursively destroy children containers
|
// Recursively destroy children containers
|
||||||
let firstChild;
|
let firstChild;
|
||||||
while (firstChild = this.children.firstChild) {
|
while (firstChild = this.children.firstChild) {
|
||||||
@ -1711,16 +1649,168 @@ MarkupContainer.prototype = {
|
|||||||
this.children.removeChild(firstChild);
|
this.children.removeChild(firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove event listeners
|
|
||||||
this.elt.removeEventListener("dblclick", this._onToggle, false);
|
|
||||||
this.elt.removeEventListener("mousedown", this._onMouseDown, false);
|
|
||||||
this.expander.removeEventListener("click", this._onToggle, false);
|
|
||||||
|
|
||||||
// Destroy my editor
|
|
||||||
this.editor.destroy();
|
this.editor.destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of MarkupContainer for Pseudo Elements,
|
||||||
|
* Doctype nodes, or any other type generic node that doesn't
|
||||||
|
* fit for other editors.
|
||||||
|
* Does not allow any editing, just viewing / selecting.
|
||||||
|
*
|
||||||
|
* @param MarkupView markupView
|
||||||
|
* The markup view that owns this container.
|
||||||
|
* @param NodeFront node
|
||||||
|
* The node to display.
|
||||||
|
*/
|
||||||
|
function MarkupReadOnlyContainer(markupView, node) {
|
||||||
|
MarkupContainer.prototype.initialize.call(this, markupView, node, "readonlycontainer");
|
||||||
|
|
||||||
|
this.editor = new GenericEditor(this, node);
|
||||||
|
this.tagLine.appendChild(this.editor.elt);
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkupReadOnlyContainer.prototype = Heritage.extend(MarkupContainer.prototype, {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of MarkupContainer for text node and comment nodes.
|
||||||
|
* Allows basic text editing in a textarea.
|
||||||
|
*
|
||||||
|
* @param MarkupView aMarkupView
|
||||||
|
* The markup view that owns this container.
|
||||||
|
* @param NodeFront aNode
|
||||||
|
* The node to display.
|
||||||
|
* @param Inspector aInspector
|
||||||
|
* The inspector tool container the markup-view
|
||||||
|
*/
|
||||||
|
function MarkupTextContainer(markupView, node) {
|
||||||
|
MarkupContainer.prototype.initialize.call(this, markupView, node, "textcontainer");
|
||||||
|
|
||||||
|
if (node.nodeType == Ci.nsIDOMNode.TEXT_NODE) {
|
||||||
|
this.editor = new TextEditor(this, node, "text");
|
||||||
|
} else if (node.nodeType == Ci.nsIDOMNode.COMMENT_NODE) {
|
||||||
|
this.editor = new TextEditor(this, node, "comment");
|
||||||
|
} else {
|
||||||
|
throw "Invalid node for MarkupTextContainer";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tagLine.appendChild(this.editor.elt);
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkupTextContainer.prototype = Heritage.extend(MarkupContainer.prototype, {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of MarkupContainer for Elements that can contain
|
||||||
|
* child nodes.
|
||||||
|
* Allows editing of tag name, attributes, expanding / collapsing.
|
||||||
|
*
|
||||||
|
* @param MarkupView markupView
|
||||||
|
* The markup view that owns this container.
|
||||||
|
* @param NodeFront node
|
||||||
|
* The node to display.
|
||||||
|
*/
|
||||||
|
function MarkupElementContainer(markupView, node) {
|
||||||
|
MarkupContainer.prototype.initialize.call(this, markupView, node, "elementcontainer");
|
||||||
|
|
||||||
|
if (node.nodeType === Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||||
|
this.editor = new ElementEditor(this, node);
|
||||||
|
} else {
|
||||||
|
throw "Invalid node for MarkupElementContainer";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tagLine.appendChild(this.editor.elt);
|
||||||
|
|
||||||
|
// Prepare the image preview tooltip data if any
|
||||||
|
this._prepareImagePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkupElementContainer.prototype = Heritage.extend(MarkupContainer.prototype, {
|
||||||
|
|
||||||
|
_buildEventTooltipContent: function(target, tooltip) {
|
||||||
|
if (target.hasAttribute("data-event")) {
|
||||||
|
tooltip.hide(target);
|
||||||
|
|
||||||
|
this.node.getEventListenerInfo().then(listenerInfo => {
|
||||||
|
tooltip.setEventContent({
|
||||||
|
eventListenerInfos: listenerInfo,
|
||||||
|
toolbox: this.markup._inspector.toolbox
|
||||||
|
});
|
||||||
|
|
||||||
|
this.markup._makeTooltipPersistent(true);
|
||||||
|
tooltip.once("hidden", () => {
|
||||||
|
this.markup._makeTooltipPersistent(false);
|
||||||
|
});
|
||||||
|
tooltip.show(target);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the node is an image or canvas (@see isPreviewable), then get the
|
||||||
|
* image data uri from the server so that it can then later be previewed in
|
||||||
|
* a tooltip if needed.
|
||||||
|
* Stores a promise in this.tooltipData.data that resolves when the data has
|
||||||
|
* been retrieved
|
||||||
|
*/
|
||||||
|
_prepareImagePreview: function() {
|
||||||
|
if (this.isPreviewable()) {
|
||||||
|
// Get the image data for later so that when the user actually hovers over
|
||||||
|
// the element, the tooltip does contain the image
|
||||||
|
let def = promise.defer();
|
||||||
|
|
||||||
|
this.tooltipData = {
|
||||||
|
target: this.editor.getAttributeElement("src") || this.editor.tag,
|
||||||
|
data: def.promise
|
||||||
|
};
|
||||||
|
|
||||||
|
let maxDim = Services.prefs.getIntPref("devtools.inspector.imagePreviewTooltipSize");
|
||||||
|
this.node.getImageData(maxDim).then(data => {
|
||||||
|
data.data.string().then(str => {
|
||||||
|
let res = {data: str, size: data.size};
|
||||||
|
// Resolving the data promise and, to always keep tooltipData.data
|
||||||
|
// as a promise, create a new one that resolves immediately
|
||||||
|
def.resolve(res);
|
||||||
|
this.tooltipData.data = promise.resolve(res);
|
||||||
|
});
|
||||||
|
}, () => {
|
||||||
|
this.tooltipData.data = promise.reject();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executed by MarkupView._isImagePreviewTarget which is itself called when the
|
||||||
|
* mouse hovers over a target in the markup-view.
|
||||||
|
* Checks if the target is indeed something we want to have an image tooltip
|
||||||
|
* preview over and, if so, inserts content into the tooltip.
|
||||||
|
* @return a promise that resolves when the content has been inserted or
|
||||||
|
* rejects if no preview is required. This promise is then used by Tooltip.js
|
||||||
|
* to decide if/when to show the tooltip
|
||||||
|
*/
|
||||||
|
isImagePreviewTarget: function(target, tooltip) {
|
||||||
|
if (!this.tooltipData || this.tooltipData.target !== target) {
|
||||||
|
return promise.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.tooltipData.data.then(({data, size}) => {
|
||||||
|
tooltip.setImageContent(data, size);
|
||||||
|
}, () => {
|
||||||
|
tooltip.setBrokenImageContent();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
copyImageDataUri: function() {
|
||||||
|
// We need to send again a request to gettooltipData even if one was sent for
|
||||||
|
// the tooltip, because we want the full-size image
|
||||||
|
this.node.getImageData().then(data => {
|
||||||
|
data.data.string().then(str => {
|
||||||
|
clipboardHelper.copyString(str, this.markup.doc);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dummy container node used for the root document element.
|
* Dummy container node used for the root document element.
|
||||||
@ -1742,35 +1832,33 @@ RootContainer.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an editor for simple nodes.
|
* Creates an editor for non-editable nodes.
|
||||||
*/
|
*/
|
||||||
function GenericEditor(aContainer, aNode) {
|
function GenericEditor(aContainer, aNode) {
|
||||||
this.elt = aContainer.doc.createElement("span");
|
this.container = aContainer;
|
||||||
this.elt.className = "editor";
|
this.markup = this.container.markup;
|
||||||
this.elt.textContent = aNode.nodeName;
|
this.template = this.markup.template.bind(this.markup);
|
||||||
|
this.elt = null;
|
||||||
|
this.template("generic", this);
|
||||||
|
|
||||||
|
if (aNode.isPseudoElement) {
|
||||||
|
this.tag.classList.add("theme-fg-color5");
|
||||||
|
this.tag.textContent = aNode.isBeforePseudoElement ? "::before" : "::after";
|
||||||
|
} else if (aNode.nodeType == Ci.nsIDOMNode.DOCUMENT_TYPE_NODE) {
|
||||||
|
this.elt.classList.add("comment");
|
||||||
|
this.tag.textContent = '<!DOCTYPE ' + aNode.name +
|
||||||
|
(aNode.publicId ? ' PUBLIC "' + aNode.publicId + '"': '') +
|
||||||
|
(aNode.systemId ? ' "' + aNode.systemId + '"' : '') +
|
||||||
|
'>';
|
||||||
|
} else {
|
||||||
|
this.tag.textContent = aNode.nodeName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericEditor.prototype = {
|
GenericEditor.prototype = {
|
||||||
destroy: function() {}
|
destroy: function() {
|
||||||
};
|
this.elt.remove();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Creates an editor for a DOCTYPE node.
|
|
||||||
*
|
|
||||||
* @param MarkupContainer aContainer The container owning this editor.
|
|
||||||
* @param DOMNode aNode The node being edited.
|
|
||||||
*/
|
|
||||||
function DoctypeEditor(aContainer, aNode) {
|
|
||||||
this.elt = aContainer.doc.createElement("span");
|
|
||||||
this.elt.className = "editor comment";
|
|
||||||
this.elt.textContent = '<!DOCTYPE ' + aNode.name +
|
|
||||||
(aNode.publicId ? ' PUBLIC "' + aNode.publicId + '"': '') +
|
|
||||||
(aNode.systemId ? ' "' + aNode.systemId + '"' : '') +
|
|
||||||
'>';
|
|
||||||
}
|
|
||||||
|
|
||||||
DoctypeEditor.prototype = {
|
|
||||||
destroy: function() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1782,10 +1870,13 @@ DoctypeEditor.prototype = {
|
|||||||
* @param string aTemplate The template id to use to build the editor.
|
* @param string aTemplate The template id to use to build the editor.
|
||||||
*/
|
*/
|
||||||
function TextEditor(aContainer, aNode, aTemplate) {
|
function TextEditor(aContainer, aNode, aTemplate) {
|
||||||
|
this.container = aContainer;
|
||||||
|
this.markup = this.container.markup;
|
||||||
this.node = aNode;
|
this.node = aNode;
|
||||||
|
this.template = this.markup.template.bind(aTemplate);
|
||||||
this._selected = false;
|
this._selected = false;
|
||||||
|
|
||||||
aContainer.markup.template(aTemplate, this);
|
this.markup.template(aTemplate, this);
|
||||||
|
|
||||||
editableField({
|
editableField({
|
||||||
element: this.value,
|
element: this.value,
|
||||||
@ -1800,13 +1891,13 @@ function TextEditor(aContainer, aNode, aTemplate) {
|
|||||||
longstr.string().then(oldValue => {
|
longstr.string().then(oldValue => {
|
||||||
longstr.release().then(null, console.error);
|
longstr.release().then(null, console.error);
|
||||||
|
|
||||||
aContainer.undo.do(() => {
|
this.container.undo.do(() => {
|
||||||
this.node.setNodeValue(aVal).then(() => {
|
this.node.setNodeValue(aVal).then(() => {
|
||||||
aContainer.markup.nodeChanged(this.node);
|
this.markup.nodeChanged(this.node);
|
||||||
});
|
});
|
||||||
}, () => {
|
}, () => {
|
||||||
this.node.setNodeValue(oldValue).then(() => {
|
this.node.setNodeValue(oldValue).then(() => {
|
||||||
aContainer.markup.nodeChanged(this.node);
|
this.markup.nodeChanged(this.node);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1859,12 +1950,11 @@ TextEditor.prototype = {
|
|||||||
* @param Element aNode The node being edited.
|
* @param Element aNode The node being edited.
|
||||||
*/
|
*/
|
||||||
function ElementEditor(aContainer, aNode) {
|
function ElementEditor(aContainer, aNode) {
|
||||||
this.doc = aContainer.doc;
|
|
||||||
this.undo = aContainer.undo;
|
|
||||||
this.template = aContainer.markup.template.bind(aContainer.markup);
|
|
||||||
this.container = aContainer;
|
this.container = aContainer;
|
||||||
this.markup = this.container.markup;
|
|
||||||
this.node = aNode;
|
this.node = aNode;
|
||||||
|
this.markup = this.container.markup;
|
||||||
|
this.template = this.markup.template.bind(this.markup);
|
||||||
|
this.doc = this.markup.doc;
|
||||||
|
|
||||||
this.attrs = {};
|
this.attrs = {};
|
||||||
|
|
||||||
@ -1911,7 +2001,7 @@ function ElementEditor(aContainer, aNode) {
|
|||||||
let doMods = this._startModifyingAttributes();
|
let doMods = this._startModifyingAttributes();
|
||||||
let undoMods = this._startModifyingAttributes();
|
let undoMods = this._startModifyingAttributes();
|
||||||
this._applyAttributes(aVal, null, doMods, undoMods);
|
this._applyAttributes(aVal, null, doMods, undoMods);
|
||||||
this.undo.do(() => {
|
this.container.undo.do(() => {
|
||||||
doMods.apply();
|
doMods.apply();
|
||||||
}, function() {
|
}, function() {
|
||||||
undoMods.apply();
|
undoMods.apply();
|
||||||
@ -2039,7 +2129,7 @@ ElementEditor.prototype = {
|
|||||||
this._saveAttribute(aAttr.name, undoMods);
|
this._saveAttribute(aAttr.name, undoMods);
|
||||||
doMods.removeAttribute(aAttr.name);
|
doMods.removeAttribute(aAttr.name);
|
||||||
this._applyAttributes(aVal, attr, doMods, undoMods);
|
this._applyAttributes(aVal, attr, doMods, undoMods);
|
||||||
this.undo.do(() => {
|
this.container.undo.do(() => {
|
||||||
doMods.apply();
|
doMods.apply();
|
||||||
}, () => {
|
}, () => {
|
||||||
undoMods.apply();
|
undoMods.apply();
|
||||||
@ -2154,7 +2244,7 @@ ElementEditor.prototype = {
|
|||||||
aOld.parentNode.removeChild(aOld);
|
aOld.parentNode.removeChild(aOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.undo.do(() => {
|
this.container.undo.do(() => {
|
||||||
swapNodes(this.rawNode, newElt);
|
swapNodes(this.rawNode, newElt);
|
||||||
this.markup.setNodeExpanded(newFront, this.container.expanded);
|
this.markup.setNodeExpanded(newFront, this.container.expanded);
|
||||||
if (this.container.selected) {
|
if (this.container.selected) {
|
||||||
|
@ -26,7 +26,20 @@
|
|||||||
<div id="templates" style="display:none">
|
<div id="templates" style="display:none">
|
||||||
|
|
||||||
<ul class="children">
|
<ul class="children">
|
||||||
<li id="template-container" save="${elt}" class="child collapsed">
|
<li id="template-elementcontainer" save="${elt}" class="child collapsed">
|
||||||
|
<div save="${tagLine}" class="tag-line"><!--
|
||||||
|
--><span save="${tagState}" class="tag-state"></span><!--
|
||||||
|
--><span save="${expander}" class="theme-twisty expander"></span><!--
|
||||||
|
--></div>
|
||||||
|
<ul save="${children}" class="children"></ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="template-textcontainer" save="${elt}" class="child collapsed">
|
||||||
|
<div save="${tagLine}" class="tag-line"><span save="${tagState}" class="tag-state"></span></div>
|
||||||
|
<ul save="${children}" class="children"></ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="template-readonlycontainer" save="${elt}" class="child collapsed">
|
||||||
<div save="${tagLine}" class="tag-line"><!--
|
<div save="${tagLine}" class="tag-line"><!--
|
||||||
--><span save="${tagState}" class="tag-state"></span><!--
|
--><span save="${tagState}" class="tag-state"></span><!--
|
||||||
--><span save="${expander}" class="theme-twisty expander"></span><!--
|
--><span save="${expander}" class="theme-twisty expander"></span><!--
|
||||||
@ -42,6 +55,8 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<span id="template-generic" save="${elt}" class="editor"><span save="${tag}" class="tag"></span></span>
|
||||||
|
|
||||||
<span id="template-element" save="${elt}" class="editor"><!--
|
<span id="template-element" save="${elt}" class="editor"><!--
|
||||||
--><span class="open"><<!--
|
--><span class="open"><<!--
|
||||||
--><span save="${tag}" class="tag theme-fg-color3" tabindex="0"></span><!--
|
--><span save="${tag}" class="tag theme-fg-color3" tabindex="0"></span><!--
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
subsuite = devtools
|
subsuite = devtools
|
||||||
support-files =
|
support-files =
|
||||||
|
doc_markup_anonymous.html
|
||||||
doc_markup_edit.html
|
doc_markup_edit.html
|
||||||
doc_markup_events.html
|
doc_markup_events.html
|
||||||
doc_markup_events_jquery.html
|
doc_markup_events_jquery.html
|
||||||
@ -29,6 +30,10 @@ support-files =
|
|||||||
lib_jquery_1.11.1_min.js
|
lib_jquery_1.11.1_min.js
|
||||||
lib_jquery_2.1.1_min.js
|
lib_jquery_2.1.1_min.js
|
||||||
|
|
||||||
|
[browser_markupview_anonymous_01.js]
|
||||||
|
[browser_markupview_anonymous_02.js]
|
||||||
|
skip-if = e10s # scratchpad.xul is not loading in e10s window
|
||||||
|
[browser_markupview_anonymous_03.js]
|
||||||
[browser_markupview_copy_image_data.js]
|
[browser_markupview_copy_image_data.js]
|
||||||
[browser_markupview_css_completion_style_attribute.js]
|
[browser_markupview_css_completion_style_attribute.js]
|
||||||
[browser_markupview_events.js]
|
[browser_markupview_events.js]
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test native anonymous content in the markupview.
|
||||||
|
const TEST_URL = TEST_URL_ROOT + "doc_markup_anonymous.html";
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||||
|
|
||||||
|
let pseudo = yield getNodeFront("#pseudo", inspector);
|
||||||
|
|
||||||
|
// Markup looks like: <div><::before /><span /><::after /></div>
|
||||||
|
let children = yield inspector.walker.children(pseudo);
|
||||||
|
is (children.nodes.length, 3, "Children returned from walker");
|
||||||
|
|
||||||
|
info ("Checking the ::before pseudo element");
|
||||||
|
let before = children.nodes[0];
|
||||||
|
yield isEditingMenuDisabled(before, inspector);
|
||||||
|
|
||||||
|
info ("Checking the normal child element");
|
||||||
|
let span = children.nodes[1];
|
||||||
|
yield isEditingMenuEnabled(span, inspector);
|
||||||
|
|
||||||
|
info ("Checking the ::after pseudo element");
|
||||||
|
let after = children.nodes[2];
|
||||||
|
yield isEditingMenuDisabled(after, inspector);
|
||||||
|
});
|
@ -0,0 +1,29 @@
|
|||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test XBL anonymous content in the markupview
|
||||||
|
const TEST_URL = "chrome://browser/content/devtools/scratchpad.xul";
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||||
|
|
||||||
|
let toolbarbutton = yield getNodeFront("toolbarbutton", inspector);
|
||||||
|
let children = yield inspector.walker.children(toolbarbutton);
|
||||||
|
|
||||||
|
is(toolbarbutton.numChildren, 3, "Correct number of children");
|
||||||
|
is (children.nodes.length, 3, "Children returned from walker");
|
||||||
|
|
||||||
|
is(toolbarbutton.isAnonymous, false, "Toolbarbutton is not anonymous");
|
||||||
|
yield isEditingMenuEnabled(toolbarbutton, inspector);
|
||||||
|
|
||||||
|
for (let node of children.nodes) {
|
||||||
|
ok (node.isAnonymous, "Child is anonymous");
|
||||||
|
ok (node._form.isXBLAnonymous, "Child is XBL anonymous");
|
||||||
|
ok (!node._form.isShadowAnonymous, "Child is not shadow anonymous");
|
||||||
|
ok (!node._form.isNativeAnonymous, "Child is not native anonymous");
|
||||||
|
yield isEditingMenuDisabled(node, inspector);
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,34 @@
|
|||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test shadow DOM content in the markupview.
|
||||||
|
// Note that many features are not yet enabled, but basic listing
|
||||||
|
// of elements should be working.
|
||||||
|
const TEST_URL = TEST_URL_ROOT + "doc_markup_anonymous.html";
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
Services.prefs.setBoolPref("dom.webcomponents.enabled", true);
|
||||||
|
|
||||||
|
let {inspector} = yield addTab(TEST_URL).then(openInspector);
|
||||||
|
|
||||||
|
let shadow = yield getNodeFront("#shadow", inspector.markup);
|
||||||
|
let children = yield inspector.walker.children(shadow);
|
||||||
|
|
||||||
|
is (shadow.numChildren, 3, "Children of the shadow root are counted");
|
||||||
|
is (children.nodes.length, 3, "Children returned from walker");
|
||||||
|
|
||||||
|
info ("Checking the ::before pseudo element");
|
||||||
|
let before = children.nodes[0];
|
||||||
|
yield isEditingMenuDisabled(before, inspector);
|
||||||
|
|
||||||
|
info ("Checking the <h3> shadow element");
|
||||||
|
let shadowChild1 = children.nodes[1];
|
||||||
|
yield isEditingMenuDisabled(shadowChild1, inspector);
|
||||||
|
|
||||||
|
info ("Checking the <select> shadow element");
|
||||||
|
let shadowChild2 = children.nodes[2];
|
||||||
|
yield isEditingMenuDisabled(shadowChild2, inspector);
|
||||||
|
});
|
31
browser/devtools/markupview/test/doc_markup_anonymous.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Anonymous content test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
#pseudo::before {
|
||||||
|
content: "before";
|
||||||
|
}
|
||||||
|
#pseudo::after {
|
||||||
|
content: "after";
|
||||||
|
}
|
||||||
|
#shadow::before {
|
||||||
|
content: "Testing ::before on a shadow host";
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="pseudo"><span>middle</span></div>
|
||||||
|
|
||||||
|
<div id="shadow">light dom</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var host = document.querySelector('#shadow');
|
||||||
|
if (host.createShadowRoot) {
|
||||||
|
var root = host.createShadowRoot();
|
||||||
|
root.innerHTML = '<h3>Shadow DOM</h3><select multiple></select>';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -8,6 +8,7 @@ let TargetFactory = devtools.TargetFactory;
|
|||||||
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
||||||
let promise = devtools.require("devtools/toolkit/deprecated-sync-thenables");
|
let promise = devtools.require("devtools/toolkit/deprecated-sync-thenables");
|
||||||
let {getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared/inplace-editor");
|
let {getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared/inplace-editor");
|
||||||
|
let clipboard = devtools.require("sdk/clipboard");
|
||||||
|
|
||||||
// All test are asynchronous
|
// All test are asynchronous
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
@ -30,6 +31,7 @@ registerCleanupFunction(() => {
|
|||||||
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
|
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
|
||||||
Services.prefs.clearUserPref("devtools.dump.emit");
|
Services.prefs.clearUserPref("devtools.dump.emit");
|
||||||
Services.prefs.clearUserPref("devtools.markup.pagesize");
|
Services.prefs.clearUserPref("devtools.markup.pagesize");
|
||||||
|
Services.prefs.clearUserPref("dom.webcomponents.enabled");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Auto close the toolbox and close the test tabs when the test ends
|
// Auto close the toolbox and close the test tabs when the test ends
|
||||||
@ -143,12 +145,15 @@ function getNode(nodeOrSelector) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the NodeFront for a given css selector, via the protocol
|
* Get the NodeFront for a given css selector, via the protocol
|
||||||
* @param {String} selector
|
* @param {String|NodeFront} selector
|
||||||
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
||||||
* loaded in the toolbox
|
* loaded in the toolbox
|
||||||
* @return {Promise} Resolves to the NodeFront instance
|
* @return {Promise} Resolves to the NodeFront instance
|
||||||
*/
|
*/
|
||||||
function getNodeFront(selector, {walker}) {
|
function getNodeFront(selector, {walker}) {
|
||||||
|
if (selector._form) {
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
return walker.querySelector(walker.rootNode, selector);
|
return walker.querySelector(walker.rootNode, selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +178,7 @@ function selectAndHighlightNode(nodeOrSelector, inspector) {
|
|||||||
/**
|
/**
|
||||||
* Set the inspector's current selection to the first match of the given css
|
* Set the inspector's current selection to the first match of the given css
|
||||||
* selector
|
* selector
|
||||||
* @param {String} selector
|
* @param {String|NodeFront} selector
|
||||||
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
||||||
* loaded in the toolbox
|
* loaded in the toolbox
|
||||||
* @param {String} reason Defaults to "test" which instructs the inspector not
|
* @param {String} reason Defaults to "test" which instructs the inspector not
|
||||||
@ -203,7 +208,7 @@ function getContainerForNodeFront(nodeFront, {markup}) {
|
|||||||
/**
|
/**
|
||||||
* Get the MarkupContainer object instance that corresponds to the given
|
* Get the MarkupContainer object instance that corresponds to the given
|
||||||
* selector
|
* selector
|
||||||
* @param {String} selector
|
* @param {String|NodeFront} selector
|
||||||
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
||||||
* loaded in the toolbox
|
* loaded in the toolbox
|
||||||
* @return {MarkupContainer}
|
* @return {MarkupContainer}
|
||||||
@ -236,7 +241,7 @@ function waitForChildrenUpdated({markup}) {
|
|||||||
/**
|
/**
|
||||||
* Simulate a mouse-over on the markup-container (a line in the markup-view)
|
* Simulate a mouse-over on the markup-container (a line in the markup-view)
|
||||||
* that corresponds to the selector passed.
|
* that corresponds to the selector passed.
|
||||||
* @param {String} selector
|
* @param {String|NodeFront} selector
|
||||||
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
||||||
* loaded in the toolbox
|
* loaded in the toolbox
|
||||||
* @return {Promise} Resolves when the container is hovered and the higlighter
|
* @return {Promise} Resolves when the container is hovered and the higlighter
|
||||||
@ -257,7 +262,7 @@ let hoverContainer = Task.async(function*(selector, inspector) {
|
|||||||
/**
|
/**
|
||||||
* Simulate a click on the markup-container (a line in the markup-view)
|
* Simulate a click on the markup-container (a line in the markup-view)
|
||||||
* that corresponds to the selector passed.
|
* that corresponds to the selector passed.
|
||||||
* @param {String} selector
|
* @param {String|NodeFront} selector
|
||||||
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
||||||
* loaded in the toolbox
|
* loaded in the toolbox
|
||||||
* @return {Promise} Resolves when the node has been selected.
|
* @return {Promise} Resolves when the node has been selected.
|
||||||
@ -440,6 +445,124 @@ function wait(ms) {
|
|||||||
return def.promise;
|
return def.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for eventName on target.
|
||||||
|
* @param {Object} target An observable object that either supports on/off or
|
||||||
|
* addEventListener/removeEventListener
|
||||||
|
* @param {String} eventName
|
||||||
|
* @param {Boolean} useCapture Optional, for addEventListener/removeEventListener
|
||||||
|
* @return A promise that resolves when the event has been handled
|
||||||
|
*/
|
||||||
|
function once(target, eventName, useCapture=false) {
|
||||||
|
info("Waiting for event: '" + eventName + "' on " + target + ".");
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
|
|
||||||
|
for (let [add, remove] of [
|
||||||
|
["addEventListener", "removeEventListener"],
|
||||||
|
["addListener", "removeListener"],
|
||||||
|
["on", "off"]
|
||||||
|
]) {
|
||||||
|
if ((add in target) && (remove in target)) {
|
||||||
|
target[add](eventName, function onEvent(...aArgs) {
|
||||||
|
info("Got event: '" + eventName + "' on " + target + ".");
|
||||||
|
target[remove](eventName, onEvent, useCapture);
|
||||||
|
deferred.resolve.apply(deferred, aArgs);
|
||||||
|
}, useCapture);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if the inspector menu items for editing are disabled.
|
||||||
|
* Things like Edit As HTML, Delete Node, etc.
|
||||||
|
* @param {NodeFront} nodeFront
|
||||||
|
* @param {InspectorPanel} inspector
|
||||||
|
* @param {Boolean} assert Should this function run assertions inline.
|
||||||
|
* @return A promise that resolves with a boolean indicating whether
|
||||||
|
* the menu items are disabled once the menu has been checked.
|
||||||
|
*/
|
||||||
|
let isEditingMenuDisabled = Task.async(function*(nodeFront, inspector, assert=true) {
|
||||||
|
let deleteMenuItem = inspector.panelDoc.getElementById("node-menu-delete");
|
||||||
|
let editHTMLMenuItem = inspector.panelDoc.getElementById("node-menu-edithtml");
|
||||||
|
let pasteHTMLMenuItem = inspector.panelDoc.getElementById("node-menu-pasteouterhtml");
|
||||||
|
|
||||||
|
// To ensure clipboard contains something to paste.
|
||||||
|
clipboard.set("<p>test</p>", "html");
|
||||||
|
|
||||||
|
let menu = inspector.nodemenu;
|
||||||
|
yield selectNode(nodeFront, inspector);
|
||||||
|
yield reopenMenu(menu);
|
||||||
|
|
||||||
|
let isDeleteMenuDisabled = deleteMenuItem.hasAttribute("disabled");
|
||||||
|
let isEditHTMLMenuDisabled = editHTMLMenuItem.hasAttribute("disabled");
|
||||||
|
let isPasteHTMLMenuDisabled = pasteHTMLMenuItem.hasAttribute("disabled");
|
||||||
|
|
||||||
|
if (assert) {
|
||||||
|
ok(isDeleteMenuDisabled, "Delete menu item is disabled");
|
||||||
|
ok(isEditHTMLMenuDisabled, "Edit HTML menu item is disabled");
|
||||||
|
ok(isPasteHTMLMenuDisabled, "Paste HTML menu item is disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
return isDeleteMenuDisabled && isEditHTMLMenuDisabled && isPasteHTMLMenuDisabled;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if the inspector menu items for editing are enabled.
|
||||||
|
* Things like Edit As HTML, Delete Node, etc.
|
||||||
|
* @param {NodeFront} nodeFront
|
||||||
|
* @param {InspectorPanel} inspector
|
||||||
|
* @param {Boolean} assert Should this function run assertions inline.
|
||||||
|
* @return A promise that resolves with a boolean indicating whether
|
||||||
|
* the menu items are enabled once the menu has been checked.
|
||||||
|
*/
|
||||||
|
let isEditingMenuEnabled = Task.async(function*(nodeFront, inspector, assert=true) {
|
||||||
|
let deleteMenuItem = inspector.panelDoc.getElementById("node-menu-delete");
|
||||||
|
let editHTMLMenuItem = inspector.panelDoc.getElementById("node-menu-edithtml");
|
||||||
|
let pasteHTMLMenuItem = inspector.panelDoc.getElementById("node-menu-pasteouterhtml");
|
||||||
|
|
||||||
|
// To ensure clipboard contains something to paste.
|
||||||
|
clipboard.set("<p>test</p>", "html");
|
||||||
|
|
||||||
|
let menu = inspector.nodemenu;
|
||||||
|
yield selectNode(nodeFront, inspector);
|
||||||
|
yield reopenMenu(menu);
|
||||||
|
|
||||||
|
let isDeleteMenuDisabled = deleteMenuItem.hasAttribute("disabled");
|
||||||
|
let isEditHTMLMenuDisabled = editHTMLMenuItem.hasAttribute("disabled");
|
||||||
|
let isPasteHTMLMenuDisabled = pasteHTMLMenuItem.hasAttribute("disabled");
|
||||||
|
|
||||||
|
if (assert) {
|
||||||
|
ok(!isDeleteMenuDisabled, "Delete menu item is enabled");
|
||||||
|
ok(!isEditHTMLMenuDisabled, "Edit HTML menu item is enabled");
|
||||||
|
ok(!isPasteHTMLMenuDisabled, "Paste HTML menu item is enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
return !isDeleteMenuDisabled && !isEditHTMLMenuDisabled && !isPasteHTMLMenuDisabled;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a menu (closing it first if necessary).
|
||||||
|
* @param {DOMNode} menu A menu that implements hidePopup/openPopup
|
||||||
|
* @return a promise that resolves once the menu is opened.
|
||||||
|
*/
|
||||||
|
let reopenMenu = Task.async(function*(menu) {
|
||||||
|
// First close it is if it is already opened.
|
||||||
|
if (menu.state == "closing" || menu.state == "open") {
|
||||||
|
let popuphidden = once(menu, "popuphidden", true);
|
||||||
|
menu.hidePopup();
|
||||||
|
yield popuphidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then open it and return once
|
||||||
|
let popupshown = once(menu, "popupshown", true);
|
||||||
|
menu.openPopup();
|
||||||
|
yield popupshown;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for all current promises to be resolved. See this as executeSoon that
|
* Wait for all current promises to be resolved. See this as executeSoon that
|
||||||
* can be used with yield.
|
* can be used with yield.
|
||||||
|
@ -153,7 +153,9 @@ ElementStyle.prototype = {
|
|||||||
// engine, we will set properties on a dummy element and observe
|
// engine, we will set properties on a dummy element and observe
|
||||||
// how their .style attribute reflects them as computed values.
|
// how their .style attribute reflects them as computed values.
|
||||||
return this.dummyElementPromise = createDummyDocument().then(document => {
|
return this.dummyElementPromise = createDummyDocument().then(document => {
|
||||||
this.dummyElement = document.createElementNS(this.element.namespaceURI,
|
// ::before and ::after do not have a namespaceURI
|
||||||
|
let namespaceURI = this.element.namespaceURI || document.documentElement.namespaceURI;
|
||||||
|
this.dummyElement = document.createElementNS(namespaceURI,
|
||||||
this.element.tagName);
|
this.element.tagName);
|
||||||
document.documentElement.appendChild(this.dummyElement);
|
document.documentElement.appendChild(this.dummyElement);
|
||||||
return this.dummyElement;
|
return this.dummyElement;
|
||||||
@ -163,9 +165,7 @@ ElementStyle.prototype = {
|
|||||||
destroy: function() {
|
destroy: function() {
|
||||||
this.dummyElement = null;
|
this.dummyElement = null;
|
||||||
this.dummyElementPromise.then(dummyElement => {
|
this.dummyElementPromise.then(dummyElement => {
|
||||||
if (dummyElement.parentNode) {
|
dummyElement.remove();
|
||||||
dummyElement.parentNode.removeChild(dummyElement);
|
|
||||||
}
|
|
||||||
this.dummyElementPromise = null;
|
this.dummyElementPromise = null;
|
||||||
}, console.error);
|
}, console.error);
|
||||||
},
|
},
|
||||||
@ -1236,6 +1236,8 @@ CssRuleView.prototype = {
|
|||||||
let accessKey = label + ".accessKey";
|
let accessKey = label + ".accessKey";
|
||||||
this.menuitemSources.setAttribute("accesskey",
|
this.menuitemSources.setAttribute("accesskey",
|
||||||
_strings.GetStringFromName(accessKey));
|
_strings.GetStringFromName(accessKey));
|
||||||
|
|
||||||
|
this.menuitemAddRule.disabled = this.inspector.selection.isAnonymousNode();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1831,10 +1833,14 @@ function RuleEditor(aRuleView, aRule) {
|
|||||||
RuleEditor.prototype = {
|
RuleEditor.prototype = {
|
||||||
get isSelectorEditable() {
|
get isSelectorEditable() {
|
||||||
let toolbox = this.ruleView.inspector.toolbox;
|
let toolbox = this.ruleView.inspector.toolbox;
|
||||||
return this.isEditable &&
|
let trait = this.isEditable &&
|
||||||
toolbox.target.client.traits.selectorEditable &&
|
toolbox.target.client.traits.selectorEditable &&
|
||||||
this.rule.domRule.type !== ELEMENT_STYLE &&
|
this.rule.domRule.type !== ELEMENT_STYLE &&
|
||||||
this.rule.domRule.type !== Ci.nsIDOMCSSRule.KEYFRAME_RULE
|
this.rule.domRule.type !== Ci.nsIDOMCSSRule.KEYFRAME_RULE;
|
||||||
|
|
||||||
|
// Do not allow editing anonymousselectors until we can
|
||||||
|
// detect mutations on pseudo elements in Bug 1034110.
|
||||||
|
return trait && !this.rule.elementStyle.element.isAnonymous;
|
||||||
},
|
},
|
||||||
|
|
||||||
_create: function() {
|
_create: function() {
|
||||||
|
@ -34,6 +34,7 @@ support-files =
|
|||||||
[browser_computedview_media-queries.js]
|
[browser_computedview_media-queries.js]
|
||||||
[browser_computedview_no-results-placeholder.js]
|
[browser_computedview_no-results-placeholder.js]
|
||||||
[browser_computedview_original-source-link.js]
|
[browser_computedview_original-source-link.js]
|
||||||
|
[browser_computedview_pseudo-element_01.js]
|
||||||
[browser_computedview_refresh-on-style-change_01.js]
|
[browser_computedview_refresh-on-style-change_01.js]
|
||||||
[browser_computedview_refresh-on-style-change_02.js]
|
[browser_computedview_refresh-on-style-change_02.js]
|
||||||
[browser_computedview_search-filter.js]
|
[browser_computedview_search-filter.js]
|
||||||
@ -92,7 +93,8 @@ skip-if = (os == "win" && debug) || e10s # bug 963492: win. bug 1040653: e10s.
|
|||||||
[browser_ruleview_multiple_properties_02.js]
|
[browser_ruleview_multiple_properties_02.js]
|
||||||
[browser_ruleview_original-source-link.js]
|
[browser_ruleview_original-source-link.js]
|
||||||
[browser_ruleview_override.js]
|
[browser_ruleview_override.js]
|
||||||
[browser_ruleview_pseudo-element.js]
|
[browser_ruleview_pseudo-element_01.js]
|
||||||
|
[browser_ruleview_pseudo-element_02.js]
|
||||||
[browser_ruleview_refresh-on-attribute-change_01.js]
|
[browser_ruleview_refresh-on-attribute-change_01.js]
|
||||||
[browser_ruleview_refresh-on-attribute-change_02.js]
|
[browser_ruleview_refresh-on-attribute-change_02.js]
|
||||||
[browser_ruleview_refresh-on-style-change.js]
|
[browser_ruleview_refresh-on-style-change.js]
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test that pseudoelements are displayed correctly in the rule view
|
||||||
|
|
||||||
|
const TEST_URI = TEST_URL_ROOT + "doc_pseudoelement.html";
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
yield addTab(TEST_URI);
|
||||||
|
let {toolbox, inspector, view} = yield openComputedView();
|
||||||
|
|
||||||
|
yield testTopLeft(inspector, view);
|
||||||
|
});
|
||||||
|
|
||||||
|
function* testTopLeft(inspector, view) {
|
||||||
|
let node = yield getNodeFront("#topleft", inspector.markup);
|
||||||
|
yield selectNode(node, inspector);
|
||||||
|
let float = getComputedViewPropertyValue(view, "float");
|
||||||
|
is(float, "left", "The computed view shows the correct float");
|
||||||
|
|
||||||
|
let children = yield inspector.markup.walker.children(node);
|
||||||
|
is (children.nodes.length, 3, "Element has correct number of children");
|
||||||
|
|
||||||
|
let beforeElement = children.nodes[0];
|
||||||
|
yield selectNode(beforeElement, inspector);
|
||||||
|
let top = getComputedViewPropertyValue(view, "top");
|
||||||
|
is(top, "0px", "The computed view shows the correct top");
|
||||||
|
let left = getComputedViewPropertyValue(view, "left");
|
||||||
|
is(left, "0px", "The computed view shows the correct left");
|
||||||
|
|
||||||
|
let afterElement = children.nodes[children.nodes.length-1];
|
||||||
|
yield selectNode(afterElement, inspector);
|
||||||
|
top = getComputedViewPropertyValue(view, "top");
|
||||||
|
is(top, "50%", "The computed view shows the correct top");
|
||||||
|
left = getComputedViewPropertyValue(view, "left");
|
||||||
|
is(left, "50%", "The computed view shows the correct left");
|
||||||
|
}
|
||||||
|
|
@ -5,15 +5,15 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Testing selector inplace-editor behaviors in the rule-view with pseudo
|
// Testing selector inplace-editor behaviors in the rule-view with pseudo
|
||||||
// classes and elements
|
// classes.
|
||||||
|
|
||||||
let PAGE_CONTENT = [
|
let PAGE_CONTENT = [
|
||||||
'<style type="text/css">',
|
'<style type="text/css">',
|
||||||
' .testclass {',
|
' .testclass {',
|
||||||
' text-align: center;',
|
' text-align: center;',
|
||||||
' }',
|
' }',
|
||||||
' #testid3:after {',
|
' #testid3:first-letter {',
|
||||||
' content: "+"',
|
' text-decoration: "italic"',
|
||||||
' }',
|
' }',
|
||||||
'</style>',
|
'</style>',
|
||||||
'<div id="testid">Styled Node</div>',
|
'<div id="testid">Styled Node</div>',
|
||||||
@ -41,11 +41,11 @@ let test = asyncTest(function*() {
|
|||||||
|
|
||||||
info("Selecting the test element");
|
info("Selecting the test element");
|
||||||
yield selectNode("#testid3", inspector);
|
yield selectNode("#testid3", inspector);
|
||||||
yield testEditSelector(view, ".testclass2:after");
|
yield testEditSelector(view, ".testclass2:first-letter");
|
||||||
|
|
||||||
info("Selecting the modified element");
|
info("Selecting the modified element");
|
||||||
yield selectNode(".testclass2", inspector);
|
yield selectNode(".testclass2", inspector);
|
||||||
yield checkModifiedElement(view, ".testclass2:after");
|
yield checkModifiedElement(view, ".testclass2:first-letter");
|
||||||
});
|
});
|
||||||
|
|
||||||
function* testEditSelector(view, name) {
|
function* testEditSelector(view, name) {
|
||||||
|
@ -28,10 +28,8 @@ function* testTopLeft(inspector, view) {
|
|||||||
elementStyle
|
elementStyle
|
||||||
} = yield assertPseudoElementRulesNumbers(selector, inspector, view, {
|
} = yield assertPseudoElementRulesNumbers(selector, inspector, view, {
|
||||||
elementRulesNb: 4,
|
elementRulesNb: 4,
|
||||||
afterRulesNb: 1,
|
firstLineRulesNb: 2,
|
||||||
beforeRulesNb: 2,
|
firstLetterRulesNb: 1,
|
||||||
firstLineRulesNb: 0,
|
|
||||||
firstLetterRulesNb: 0,
|
|
||||||
selectionRulesNb: 0
|
selectionRulesNb: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -50,74 +48,62 @@ function* testTopLeft(inspector, view) {
|
|||||||
ok (!view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements are collapsed by dblclicking");
|
ok (!view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements are collapsed by dblclicking");
|
||||||
|
|
||||||
let defaultView = element.ownerDocument.defaultView;
|
let defaultView = element.ownerDocument.defaultView;
|
||||||
|
|
||||||
let elementRule = rules.elementRules[0];
|
let elementRule = rules.elementRules[0];
|
||||||
let elementRuleView = getRuleViewRuleEditor(view, 3);
|
let elementRuleView = getRuleViewRuleEditor(view, 3);
|
||||||
|
|
||||||
let elementAfterRule = rules.afterRules[0];
|
let elementFirstLineRule = rules.firstLineRules[0];
|
||||||
let elementAfterRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
let elementFirstLineRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementAfterRule;
|
return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
|
||||||
})[0]._ruleEditor;
|
})[0]._ruleEditor;
|
||||||
|
|
||||||
is
|
is
|
||||||
(
|
(
|
||||||
convertTextPropsToString(elementAfterRule.textProps),
|
convertTextPropsToString(elementFirstLineRule.textProps),
|
||||||
"background: none repeat scroll 0% 0% red; content: \" \"; position: absolute; " +
|
"color: orange",
|
||||||
"border-radius: 50%; height: 32px; width: 32px; top: 50%; left: 50%; margin-top: -16px; margin-left: -16px",
|
"TopLeft firstLine properties are correct"
|
||||||
"TopLeft after properties are correct"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let elementBeforeRule = rules.beforeRules[0];
|
let firstProp = elementFirstLineRuleView.addProperty("background-color", "rgb(0, 255, 0)", "");
|
||||||
let elementBeforeRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
let secondProp = elementFirstLineRuleView.addProperty("font-style", "italic", "");
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule;
|
|
||||||
})[0]._ruleEditor;
|
|
||||||
|
|
||||||
is
|
is (firstProp, elementFirstLineRule.textProps[elementFirstLineRule.textProps.length - 2],
|
||||||
(
|
|
||||||
convertTextPropsToString(elementBeforeRule.textProps),
|
|
||||||
"top: 0px; left: 0px",
|
|
||||||
"TopLeft before properties are correct"
|
|
||||||
);
|
|
||||||
|
|
||||||
let firstProp = elementAfterRuleView.addProperty("background-color", "rgb(0, 255, 0)", "");
|
|
||||||
let secondProp = elementAfterRuleView.addProperty("padding", "100px", "");
|
|
||||||
|
|
||||||
is (firstProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 2],
|
|
||||||
"First added property is on back of array");
|
"First added property is on back of array");
|
||||||
is (secondProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 1],
|
is (secondProp, elementFirstLineRule.textProps[elementFirstLineRule.textProps.length - 1],
|
||||||
"Second added property is on back of array");
|
"Second added property is on back of array");
|
||||||
|
|
||||||
yield elementAfterRule._applyingModifications;
|
yield elementFirstLineRule._applyingModifications;
|
||||||
|
|
||||||
is((yield getComputedStyleProperty(selector, ":after", "background-color")),
|
is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
|
||||||
"rgb(0, 255, 0)", "Added property should have been used.");
|
"rgb(0, 255, 0)", "Added property should have been used.");
|
||||||
is((yield getComputedStyleProperty(selector, ":after", "padding-top")),
|
is((yield getComputedStyleProperty(selector, ":first-line", "font-style")),
|
||||||
"100px", "Added property should have been used.");
|
"italic", "Added property should have been used.");
|
||||||
is((yield getComputedStyleProperty(selector, null, "padding-top")),
|
is((yield getComputedStyleProperty(selector, null, "text-decoration")),
|
||||||
"32px", "Added property should not apply to element");
|
"none", "Added property should not apply to element");
|
||||||
|
|
||||||
secondProp.setEnabled(false);
|
firstProp.setEnabled(false);
|
||||||
yield elementAfterRule._applyingModifications;
|
yield elementFirstLineRule._applyingModifications;
|
||||||
|
|
||||||
is((yield getComputedStyleProperty(selector, ":after", "padding-top")), "0px",
|
is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
|
||||||
"Disabled property should have been used.");
|
"rgb(255, 0, 0)", "Disabled property should now have been used.");
|
||||||
is((yield getComputedStyleProperty(selector, null, "padding-top")), "32px",
|
is((yield getComputedStyleProperty(selector, null, "background-color")),
|
||||||
"Added property should not apply to element");
|
"rgb(221, 221, 221)", "Added property should not apply to element");
|
||||||
|
|
||||||
secondProp.setEnabled(true);
|
firstProp.setEnabled(true);
|
||||||
yield elementAfterRule._applyingModifications;
|
yield elementFirstLineRule._applyingModifications;
|
||||||
|
|
||||||
is((yield getComputedStyleProperty(selector, ":after", "padding-top")), "100px",
|
is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
|
||||||
"Enabled property should have been used.");
|
"rgb(0, 255, 0)", "Added property should have been used.");
|
||||||
is((yield getComputedStyleProperty(selector, null, "padding-top")), "32px",
|
is((yield getComputedStyleProperty(selector, null, "text-decoration")),
|
||||||
"Added property should not apply to element");
|
"none", "Added property should not apply to element");
|
||||||
|
|
||||||
firstProp = elementRuleView.addProperty("background-color", "rgb(0, 0, 255)", "");
|
firstProp = elementRuleView.addProperty("background-color", "rgb(0, 0, 255)", "");
|
||||||
yield elementRule._applyingModifications;
|
yield elementRule._applyingModifications;
|
||||||
|
|
||||||
is((yield getComputedStyleProperty(selector, null, "background-color")), "rgb(0, 0, 255)",
|
is((yield getComputedStyleProperty(selector, null, "background-color")),
|
||||||
"Added property should have been used.");
|
"rgb(0, 0, 255)", "Added property should have been used.");
|
||||||
is((yield getComputedStyleProperty(selector, ":after", "background-color")), "rgb(0, 255, 0)",
|
is((yield getComputedStyleProperty(selector, ":first-line", "background-color")),
|
||||||
"Added prop does not apply to pseudo");
|
"rgb(0, 255, 0)", "Added prop does not apply to pseudo");
|
||||||
}
|
}
|
||||||
|
|
||||||
function* testTopRight(inspector, view) {
|
function* testTopRight(inspector, view) {
|
||||||
@ -127,10 +113,8 @@ function* testTopRight(inspector, view) {
|
|||||||
elementStyle
|
elementStyle
|
||||||
} = yield assertPseudoElementRulesNumbers("#topright", inspector, view, {
|
} = yield assertPseudoElementRulesNumbers("#topright", inspector, view, {
|
||||||
elementRulesNb: 4,
|
elementRulesNb: 4,
|
||||||
afterRulesNb: 1,
|
firstLineRulesNb: 1,
|
||||||
beforeRulesNb: 2,
|
firstLetterRulesNb: 1,
|
||||||
firstLineRulesNb: 0,
|
|
||||||
firstLetterRulesNb: 0,
|
|
||||||
selectionRulesNb: 0
|
selectionRulesNb: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -146,10 +130,8 @@ function* testTopRight(inspector, view) {
|
|||||||
function* testBottomRight(inspector, view) {
|
function* testBottomRight(inspector, view) {
|
||||||
yield assertPseudoElementRulesNumbers("#bottomright", inspector, view, {
|
yield assertPseudoElementRulesNumbers("#bottomright", inspector, view, {
|
||||||
elementRulesNb: 4,
|
elementRulesNb: 4,
|
||||||
afterRulesNb: 1,
|
firstLineRulesNb: 1,
|
||||||
beforeRulesNb: 3,
|
firstLetterRulesNb: 1,
|
||||||
firstLineRulesNb: 0,
|
|
||||||
firstLetterRulesNb: 0,
|
|
||||||
selectionRulesNb: 0
|
selectionRulesNb: 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -157,10 +139,8 @@ function* testBottomRight(inspector, view) {
|
|||||||
function* testBottomLeft(inspector, view) {
|
function* testBottomLeft(inspector, view) {
|
||||||
yield assertPseudoElementRulesNumbers("#bottomleft", inspector, view, {
|
yield assertPseudoElementRulesNumbers("#bottomleft", inspector, view, {
|
||||||
elementRulesNb: 4,
|
elementRulesNb: 4,
|
||||||
afterRulesNb: 1,
|
firstLineRulesNb: 1,
|
||||||
beforeRulesNb: 2,
|
firstLetterRulesNb: 1,
|
||||||
firstLineRulesNb: 0,
|
|
||||||
firstLetterRulesNb: 0,
|
|
||||||
selectionRulesNb: 0
|
selectionRulesNb: 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -172,8 +152,6 @@ function* testParagraph(inspector, view) {
|
|||||||
elementStyle
|
elementStyle
|
||||||
} = yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, {
|
} = yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, {
|
||||||
elementRulesNb: 3,
|
elementRulesNb: 3,
|
||||||
afterRulesNb: 0,
|
|
||||||
beforeRulesNb: 0,
|
|
||||||
firstLineRulesNb: 1,
|
firstLineRulesNb: 1,
|
||||||
firstLetterRulesNb: 1,
|
firstLetterRulesNb: 1,
|
||||||
selectionRulesNb: 1
|
selectionRulesNb: 1
|
||||||
@ -241,8 +219,6 @@ function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
|
|||||||
|
|
||||||
let rules = {
|
let rules = {
|
||||||
elementRules: elementStyle.rules.filter(rule => !rule.pseudoElement),
|
elementRules: elementStyle.rules.filter(rule => !rule.pseudoElement),
|
||||||
afterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":after"),
|
|
||||||
beforeRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":before"),
|
|
||||||
firstLineRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-line"),
|
firstLineRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-line"),
|
||||||
firstLetterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-letter"),
|
firstLetterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-letter"),
|
||||||
selectionRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":-moz-selection")
|
selectionRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":-moz-selection")
|
||||||
@ -250,10 +226,6 @@ function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
|
|||||||
|
|
||||||
is(rules.elementRules.length, ruleNbs.elementRulesNb, selector +
|
is(rules.elementRules.length, ruleNbs.elementRulesNb, selector +
|
||||||
" has the correct number of non pseudo element rules");
|
" has the correct number of non pseudo element rules");
|
||||||
is(rules.afterRules.length, ruleNbs.afterRulesNb, selector +
|
|
||||||
" has the correct number of :after rules");
|
|
||||||
is(rules.beforeRules.length, ruleNbs.beforeRulesNb, selector +
|
|
||||||
" has the correct number of :before rules");
|
|
||||||
is(rules.firstLineRules.length, ruleNbs.firstLineRulesNb, selector +
|
is(rules.firstLineRules.length, ruleNbs.firstLineRulesNb, selector +
|
||||||
" has the correct number of :first-line rules");
|
" has the correct number of :first-line rules");
|
||||||
is(rules.firstLetterRules.length, ruleNbs.firstLetterRulesNb, selector +
|
is(rules.firstLetterRules.length, ruleNbs.firstLetterRulesNb, selector +
|
||||||
@ -270,5 +242,6 @@ function assertGutters(view) {
|
|||||||
is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct");
|
is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct");
|
||||||
is (gutters[1].textContent, "This Element", "Gutter heading is correct");
|
is (gutters[1].textContent, "This Element", "Gutter heading is correct");
|
||||||
is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct");
|
is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct");
|
||||||
|
|
||||||
return gutters;
|
return gutters;
|
||||||
}
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test that pseudoelements are displayed correctly in the rule view
|
||||||
|
|
||||||
|
const TEST_URI = TEST_URL_ROOT + "doc_pseudoelement.html";
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
yield addTab(TEST_URI);
|
||||||
|
let {toolbox, inspector, view} = yield openRuleView();
|
||||||
|
|
||||||
|
yield testTopLeft(inspector, view);
|
||||||
|
});
|
||||||
|
|
||||||
|
function* testTopLeft(inspector, view) {
|
||||||
|
let node = inspector.markup.walker.frontForRawNode(getNode("#topleft"));
|
||||||
|
let children = yield inspector.markup.walker.children(node);
|
||||||
|
|
||||||
|
is (children.nodes.length, 3, "Element has correct number of children");
|
||||||
|
|
||||||
|
let beforeElement = children.nodes[0];
|
||||||
|
is (beforeElement.tagName, "_moz_generated_content_before", "tag name is correct");
|
||||||
|
yield selectNode(beforeElement, inspector);
|
||||||
|
|
||||||
|
let afterElement = children.nodes[children.nodes.length-1];
|
||||||
|
is (afterElement.tagName, "_moz_generated_content_after", "tag name is correct");
|
||||||
|
yield selectNode(afterElement, inspector);
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,15 @@ body {
|
|||||||
position:relative;
|
position:relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box:first-line {
|
||||||
|
color: orange;
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box:first-letter {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
@ -69,6 +78,13 @@ p:first-letter {
|
|||||||
left:0;
|
left:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topleft:first-line {
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
.topleft::selection {
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
.topright:before {
|
.topright:before {
|
||||||
top:0;
|
top:0;
|
||||||
right:0;
|
right:0;
|
||||||
|
@ -163,19 +163,25 @@ let selectAndHighlightNode = Task.async(function*(selector, inspector) {
|
|||||||
yield updated;
|
yield updated;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Set the inspector's current selection to a node that matches the given css
|
* Set the inspector's current selection to a node or to the first match of the
|
||||||
* selector.
|
* given css selector.
|
||||||
* @param {String} selector
|
* @param {String|NodeFront}
|
||||||
* @param {InspectorPanel} inspector The instance of InspectorPanel currently
|
* data The node to select
|
||||||
|
* @param {InspectorPanel} inspector
|
||||||
|
* The instance of InspectorPanel currently
|
||||||
* loaded in the toolbox
|
* loaded in the toolbox
|
||||||
* @param {String} reason Defaults to "test" which instructs the inspector not
|
* @param {String} reason
|
||||||
* to highlight the node upon selection
|
* Defaults to "test" which instructs the inspector not
|
||||||
|
* to highlight the node upon selection
|
||||||
* @return {Promise} Resolves when the inspector is updated with the new node
|
* @return {Promise} Resolves when the inspector is updated with the new node
|
||||||
*/
|
*/
|
||||||
let selectNode = Task.async(function*(selector, inspector, reason="test") {
|
let selectNode = Task.async(function*(data, inspector, reason="test") {
|
||||||
info("Selecting the node for '" + selector + "'");
|
info("Selecting the node for '" + data + "'");
|
||||||
let nodeFront = yield getNodeFront(selector, inspector);
|
let nodeFront = data;
|
||||||
|
if (!data._form) {
|
||||||
|
nodeFront = yield getNodeFront(data, inspector);
|
||||||
|
}
|
||||||
let updated = inspector.once("inspector-updated");
|
let updated = inspector.once("inspector-updated");
|
||||||
inspector.selection.setNodeFront(nodeFront, reason);
|
inspector.selection.setNodeFront(nodeFront, reason);
|
||||||
yield updated;
|
yield updated;
|
||||||
|
@ -23,10 +23,9 @@
|
|||||||
; Mac bundle stuff
|
; Mac bundle stuff
|
||||||
@APPNAME@/Contents/Info.plist
|
@APPNAME@/Contents/Info.plist
|
||||||
@APPNAME@/Contents/PkgInfo
|
@APPNAME@/Contents/PkgInfo
|
||||||
@APPNAME@/Contents/Resources/
|
@APPNAME@/Contents/Resources/firefox.icns
|
||||||
#ifdef MOZ_SIGNING
|
@APPNAME@/Contents/Resources/document.icns
|
||||||
@APPNAME@/Contents/_CodeSignature/CodeResources
|
@APPNAME@/Contents/Resources/en.lproj/*
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[@AB_CD@]
|
[@AB_CD@]
|
||||||
@ -55,16 +54,32 @@
|
|||||||
#ifdef GKMEDIAS_SHARED_LIBRARY
|
#ifdef GKMEDIAS_SHARED_LIBRARY
|
||||||
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
|
||||||
|
#endif
|
||||||
#ifdef MOZ_SHARED_MOZGLUE
|
#ifdef MOZ_SHARED_MOZGLUE
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef MOZ_STATIC_JS
|
#ifndef MOZ_STATIC_JS
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifdef MOZ_DMD
|
#ifdef MOZ_DMD
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@dmd@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef MOZ_NATIVE_NSPR
|
#ifndef MOZ_NATIVE_NSPR
|
||||||
#ifndef MOZ_FOLD_LIBS
|
#ifndef MOZ_FOLD_LIBS
|
||||||
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
||||||
@ -73,13 +88,13 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
@BINPATH@/XUL
|
@APPNAME@/Contents/MacOS/XUL
|
||||||
#else
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
@BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/
|
@APPNAME@/Contents/MacOS/@MOZ_CHILD_PROCESS_NAME@.app/
|
||||||
@BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
|
||||||
#else
|
#else
|
||||||
@BINPATH@/@MOZ_CHILD_PROCESS_NAME@
|
@BINPATH@/@MOZ_CHILD_PROCESS_NAME@
|
||||||
#endif
|
#endif
|
||||||
@ -109,9 +124,13 @@
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_REPLACE_MALLOC
|
#ifdef MOZ_REPLACE_MALLOC
|
||||||
#ifndef MOZ_JEMALLOC3
|
#ifndef MOZ_JEMALLOC3
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@replace_jemalloc@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@replace_jemalloc@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@replace_jemalloc@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifdef MOZ_GTK3
|
#ifdef MOZ_GTK3
|
||||||
@BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@mozgtk2@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@mozgtk2@DLL_SUFFIX@
|
||||||
@ -121,6 +140,9 @@
|
|||||||
; [Base Browser Files]
|
; [Base Browser Files]
|
||||||
#ifndef XP_UNIX
|
#ifndef XP_UNIX
|
||||||
@BINPATH@/@MOZ_APP_NAME@.exe
|
@BINPATH@/@MOZ_APP_NAME@.exe
|
||||||
|
#elif XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@MOZ_APP_NAME@-bin
|
||||||
|
@APPNAME@/Contents/MacOS/@MOZ_APP_NAME@
|
||||||
#else
|
#else
|
||||||
@BINPATH@/@MOZ_APP_NAME@-bin
|
@BINPATH@/@MOZ_APP_NAME@-bin
|
||||||
@BINPATH@/@MOZ_APP_NAME@
|
@BINPATH@/@MOZ_APP_NAME@
|
||||||
@ -741,19 +763,33 @@
|
|||||||
; meaning their .chk files are created there directly.
|
; meaning their .chk files are created there directly.
|
||||||
;
|
;
|
||||||
#ifndef MOZ_NATIVE_NSS
|
#ifndef MOZ_NATIVE_NSS
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@freebl3@DLL_SUFFIX@
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@nss3@DLL_SUFFIX@
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@nssckbi@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@freebl3@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@freebl3@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@nss3@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@nss3@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@nssckbi@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@nssckbi@DLL_SUFFIX@
|
||||||
|
#endif
|
||||||
#ifndef NSS_DISABLE_DBM
|
#ifndef NSS_DISABLE_DBM
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@nssdbm3@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@nssdbm3@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@nssdbm3@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifndef MOZ_FOLD_LIBS
|
#ifndef MOZ_FOLD_LIBS
|
||||||
@BINPATH@/@DLL_PREFIX@nssutil3@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@nssutil3@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@smime3@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@smime3@DLL_SUFFIX@
|
||||||
@BINPATH@/@DLL_PREFIX@ssl3@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@ssl3@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/@DLL_PREFIX@softokn3@DLL_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@
|
@BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
@BINPATH@/chrome/pippki@JAREXT@
|
@BINPATH@/chrome/pippki@JAREXT@
|
||||||
@BINPATH@/chrome/pippki.manifest
|
@BINPATH@/chrome/pippki.manifest
|
||||||
@BINPATH@/components/pipboot.xpt
|
@BINPATH@/components/pipboot.xpt
|
||||||
@ -780,7 +816,7 @@ bin/libfreebl_32int64_3.so
|
|||||||
;
|
;
|
||||||
#ifdef MOZ_UPDATER
|
#ifdef MOZ_UPDATER
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
@BINPATH@/updater.app/
|
@APPNAME@/Contents/MacOS/updater.app/
|
||||||
#else
|
#else
|
||||||
@BINPATH@/updater@BIN_SUFFIX@
|
@BINPATH@/updater@BIN_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
@ -800,7 +836,7 @@ bin/libfreebl_32int64_3.so
|
|||||||
@BINPATH@/components/CrashService.js
|
@BINPATH@/components/CrashService.js
|
||||||
@BINPATH@/components/toolkit_crashservice.xpt
|
@BINPATH@/components/toolkit_crashservice.xpt
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
@BINPATH@/crashreporter.app/
|
@APPNAME@/Contents/MacOS/crashreporter.app/
|
||||||
#else
|
#else
|
||||||
@BINPATH@/crashreporter@BIN_SUFFIX@
|
@BINPATH@/crashreporter@BIN_SUFFIX@
|
||||||
@BINPATH@/crashreporter.ini
|
@BINPATH@/crashreporter.ini
|
||||||
@ -819,7 +855,11 @@ bin/libfreebl_32int64_3.so
|
|||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
@BINPATH@/webapp-uninstaller@BIN_SUFFIX@
|
@BINPATH@/webapp-uninstaller@BIN_SUFFIX@
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@APPNAME@/Contents/MacOS/webapprt-stub@BIN_SUFFIX@
|
||||||
|
#else
|
||||||
@BINPATH@/webapprt-stub@BIN_SUFFIX@
|
@BINPATH@/webapprt-stub@BIN_SUFFIX@
|
||||||
|
#endif
|
||||||
@BINPATH@/webapprt/webapprt.ini
|
@BINPATH@/webapprt/webapprt.ini
|
||||||
@BINPATH@/webapprt/chrome.manifest
|
@BINPATH@/webapprt/chrome.manifest
|
||||||
@BINPATH@/webapprt/chrome/webapprt@JAREXT@
|
@BINPATH@/webapprt/chrome/webapprt@JAREXT@
|
||||||
|
@ -52,51 +52,75 @@
|
|||||||
#
|
#
|
||||||
# Example: path/to/dir/*
|
# Example: path/to/dir/*
|
||||||
|
|
||||||
# File Removals
|
# Due to Apple Mac OS X packaging requirements files that are in the same
|
||||||
|
# directory on other platforms must be located in different directories on
|
||||||
|
# Mac OS X. The following defines allow specifying the Mac OS X bundle
|
||||||
|
# location which also work on other platforms.
|
||||||
|
#
|
||||||
|
# @DIR_MACOS@
|
||||||
|
# Equals Contents/MacOS/ on Mac OX X and is an empty string on other platforms.
|
||||||
|
#
|
||||||
|
# @DIR_RESOURCES@
|
||||||
|
# Equals Contents/Resources/ on Mac OX X and is an empty string on other
|
||||||
|
# platforms.
|
||||||
|
|
||||||
|
# Common File Removals
|
||||||
# This is located under the "distribution/" directory and it was added before
|
# This is located under the "distribution/" directory and it was added before
|
||||||
# Firefox 27
|
# Firefox 27
|
||||||
distribution/extensions/testpilot@labs.mozilla.com.xpi
|
@DIR_MACOS@distribution/extensions/testpilot@labs.mozilla.com.xpi
|
||||||
|
|
||||||
# Some users are ending up with unpacked chrome instead of omni.ja. This
|
# Some users are ending up with unpacked chrome instead of omni.ja. This
|
||||||
# causes updates to break badly, see bug 1063052. Removing the toplevel
|
# causes updates to break badly, see bug 1063052. Removing the toplevel
|
||||||
# chrome.manifest causes us to use the updated omni.ja.
|
# chrome.manifest causes us to use the updated omni.ja.
|
||||||
#ifndef MOZ_GTK
|
#ifndef MOZ_GTK
|
||||||
chrome.manifest
|
@DIR_MACOS@chrome.manifest
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
@DIR_RESOURCES@chrome.manifest
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# Directory removals
|
# Mac OS X v2 signing removals
|
||||||
chrome/
|
#ifdef XP_MACOSX
|
||||||
|
@DIR_MACOS@active-update.xml
|
||||||
|
@DIR_MACOS@update-settings.ini
|
||||||
|
@DIR_MACOS@updates.xml
|
||||||
|
@DIR_MACOS@defaults/*
|
||||||
|
@DIR_MACOS@updates/*
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# Common Directory removals
|
||||||
|
@DIR_MACOS@chrome/
|
||||||
#ifdef XP_UNIX
|
#ifdef XP_UNIX
|
||||||
#ifndef XP_MACOSX
|
#ifndef XP_MACOSX
|
||||||
chrome/icons/
|
chrome/icons/
|
||||||
chrome/icons/default/
|
chrome/icons/default/
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
chrome/overlayinfo/
|
@DIR_MACOS@chrome/overlayinfo/
|
||||||
components/
|
@DIR_MACOS@components/
|
||||||
defaults/autoconfig/
|
@DIR_MACOS@defaults/autoconfig/
|
||||||
defaults/profile/
|
@DIR_MACOS@defaults/profile/
|
||||||
defaults/profile/chrome/
|
@DIR_MACOS@defaults/profile/chrome/
|
||||||
defaults/profile/US/*
|
@DIR_MACOS@defaults/profile/US/*
|
||||||
defaults/profile/extensions/
|
@DIR_MACOS@defaults/profile/extensions/
|
||||||
defaults/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/*
|
@DIR_MACOS@defaults/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/*
|
||||||
distribution/
|
@DIR_MACOS@distribution/
|
||||||
distribution/extensions/
|
@DIR_MACOS@distribution/extensions/
|
||||||
extensions/
|
@DIR_MACOS@extensions/
|
||||||
extensions/inspector@mozilla.org/*
|
@DIR_MACOS@extensions/inspector@mozilla.org/*
|
||||||
extensions/reporter@mozilla.org/*
|
@DIR_MACOS@extensions/reporter@mozilla.org/*
|
||||||
extensions/talkback@mozilla.org/*
|
@DIR_MACOS@extensions/talkback@mozilla.org/*
|
||||||
extensions/testpilot@labs.mozilla.com/*
|
@DIR_MACOS@extensions/testpilot@labs.mozilla.com/*
|
||||||
extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/*
|
@DIR_MACOS@extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/*
|
||||||
extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/*
|
@DIR_MACOS@extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/*
|
||||||
greprefs/
|
@DIR_MACOS@greprefs/
|
||||||
jssubloader/
|
@DIR_MACOS@jssubloader/
|
||||||
modules/
|
@DIR_MACOS@modules/
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
plugins/Default Plugin.plugin/*
|
@DIR_MACOS@plugins/Default Plugin.plugin/*
|
||||||
plugins/JavaEmbeddingPlugin.bundle/*
|
@DIR_MACOS@plugins/JavaEmbeddingPlugin.bundle/*
|
||||||
plugins/MRJPlugin.plugin/*
|
@DIR_MACOS@plugins/MRJPlugin.plugin/*
|
||||||
../Plug-Ins/PrintPDE.plugin/*
|
Contents/Plug-Ins/PrintPDE.plugin/*
|
||||||
#endif
|
#endif
|
||||||
searchplugins/*
|
@DIR_MACOS@searchplugins/*
|
||||||
webapprt/components/
|
@DIR_MACOS@webapprt/components/
|
||||||
|
@ -212,6 +212,8 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||||||
<!ENTITY addons.label "Add-ons">
|
<!ENTITY addons.label "Add-ons">
|
||||||
<!ENTITY addons.accesskey "A">
|
<!ENTITY addons.accesskey "A">
|
||||||
<!ENTITY addons.commandkey "A">
|
<!ENTITY addons.commandkey "A">
|
||||||
|
<!ENTITY webapps.label "Apps">
|
||||||
|
<!ENTITY webapps.accesskey "p">
|
||||||
|
|
||||||
<!ENTITY webDeveloperMenu.label "Web Developer">
|
<!ENTITY webDeveloperMenu.label "Web Developer">
|
||||||
<!ENTITY webDeveloperMenu.accesskey "W">
|
<!ENTITY webDeveloperMenu.accesskey "W">
|
||||||
|
@ -102,3 +102,6 @@ loop-call-button.tooltiptext = Invite someone to talk
|
|||||||
|
|
||||||
panic-button.label = Forget
|
panic-button.label = Forget
|
||||||
panic-button.tooltiptext = Forget about some browsing history
|
panic-button.tooltiptext = Forget about some browsing history
|
||||||
|
|
||||||
|
web-apps-button.label = Apps
|
||||||
|
web-apps-button.tooltiptext = Discover Apps
|
||||||
|
@ -23,9 +23,6 @@ const PREF_BRANCH = "browser.newtab.";
|
|||||||
// The interval between swapping in a preload docShell and kicking off the
|
// The interval between swapping in a preload docShell and kicking off the
|
||||||
// next preload in the background.
|
// next preload in the background.
|
||||||
const PRELOADER_INTERVAL_MS = 600;
|
const PRELOADER_INTERVAL_MS = 600;
|
||||||
// The initial delay before we start preloading our first new tab page. The
|
|
||||||
// timer is started after the first 'browser-delayed-startup' has been sent.
|
|
||||||
const PRELOADER_INIT_DELAY_MS = 5000;
|
|
||||||
// The number of miliseconds we'll wait after we received a notification that
|
// The number of miliseconds we'll wait after we received a notification that
|
||||||
// causes us to update our list of browsers and tabbrowser sizes. This acts as
|
// causes us to update our list of browsers and tabbrowser sizes. This acts as
|
||||||
// kind of a damper when too many events are occuring in quick succession.
|
// kind of a damper when too many events are occuring in quick succession.
|
||||||
@ -52,17 +49,20 @@ function clearTimer(timer) {
|
|||||||
|
|
||||||
this.BrowserNewTabPreloader = {
|
this.BrowserNewTabPreloader = {
|
||||||
init: function Preloader_init() {
|
init: function Preloader_init() {
|
||||||
Initializer.start();
|
Preferences.init();
|
||||||
},
|
},
|
||||||
|
|
||||||
uninit: function Preloader_uninit() {
|
uninit: function Preloader_uninit() {
|
||||||
Initializer.stop();
|
|
||||||
HostFrame.destroy();
|
HostFrame.destroy();
|
||||||
Preferences.uninit();
|
Preferences.uninit();
|
||||||
HiddenBrowsers.uninit();
|
HiddenBrowsers.uninit();
|
||||||
},
|
},
|
||||||
|
|
||||||
newTab: function Preloader_newTab(aTab) {
|
newTab: function Preloader_newTab(aTab) {
|
||||||
|
if (!Preferences.enabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let win = aTab.ownerDocument.defaultView;
|
let win = aTab.ownerDocument.defaultView;
|
||||||
if (win.gBrowser) {
|
if (win.gBrowser) {
|
||||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
@ -81,47 +81,6 @@ this.BrowserNewTabPreloader = {
|
|||||||
|
|
||||||
Object.freeze(BrowserNewTabPreloader);
|
Object.freeze(BrowserNewTabPreloader);
|
||||||
|
|
||||||
let Initializer = {
|
|
||||||
_timer: null,
|
|
||||||
_observing: false,
|
|
||||||
|
|
||||||
start: function Initializer_start() {
|
|
||||||
Services.obs.addObserver(this, TOPIC_DELAYED_STARTUP, false);
|
|
||||||
this._observing = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
stop: function Initializer_stop() {
|
|
||||||
this._timer = clearTimer(this._timer);
|
|
||||||
|
|
||||||
if (this._observing) {
|
|
||||||
Services.obs.removeObserver(this, TOPIC_DELAYED_STARTUP);
|
|
||||||
this._observing = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
observe: function Initializer_observe(aSubject, aTopic, aData) {
|
|
||||||
if (aTopic == TOPIC_DELAYED_STARTUP) {
|
|
||||||
Services.obs.removeObserver(this, TOPIC_DELAYED_STARTUP);
|
|
||||||
this._observing = false;
|
|
||||||
this._startTimer();
|
|
||||||
} else if (aTopic == TOPIC_TIMER_CALLBACK) {
|
|
||||||
this._timer = null;
|
|
||||||
this._startPreloader();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_startTimer: function Initializer_startTimer() {
|
|
||||||
this._timer = createTimer(this, PRELOADER_INIT_DELAY_MS);
|
|
||||||
},
|
|
||||||
|
|
||||||
_startPreloader: function Initializer_startPreloader() {
|
|
||||||
Preferences.init();
|
|
||||||
if (Preferences.enabled) {
|
|
||||||
HiddenBrowsers.init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let Preferences = {
|
let Preferences = {
|
||||||
_enabled: null,
|
_enabled: null,
|
||||||
_branch: null,
|
_branch: null,
|
||||||
@ -153,8 +112,6 @@ let Preferences = {
|
|||||||
|
|
||||||
if (prevEnabled && !this.enabled) {
|
if (prevEnabled && !this.enabled) {
|
||||||
HiddenBrowsers.uninit();
|
HiddenBrowsers.uninit();
|
||||||
} else if (!prevEnabled && this.enabled) {
|
|
||||||
HiddenBrowsers.init();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -168,7 +125,7 @@ let HiddenBrowsers = {
|
|||||||
TOPIC_XUL_WINDOW_CLOSED
|
TOPIC_XUL_WINDOW_CLOSED
|
||||||
],
|
],
|
||||||
|
|
||||||
init: function () {
|
_init: function () {
|
||||||
this._browsers = new Map();
|
this._browsers = new Map();
|
||||||
this._updateBrowserSizes();
|
this._updateBrowserSizes();
|
||||||
this._topics.forEach(t => Services.obs.addObserver(this, t, false));
|
this._topics.forEach(t => Services.obs.addObserver(this, t, false));
|
||||||
@ -187,9 +144,9 @@ let HiddenBrowsers = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
get: function (width, height) {
|
get: function (width, height) {
|
||||||
// We haven't been initialized, yet.
|
// Initialize if this is the first call.
|
||||||
if (!this._browsers) {
|
if (!this._browsers) {
|
||||||
return null;
|
this._init();
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = width + "x" + height;
|
let key = width + "x" + height;
|
||||||
|
@ -96,6 +96,7 @@ XPCOMUtils.defineLazyGetter(this, "PALETTE_ITEMS", function() {
|
|||||||
"email-link-button",
|
"email-link-button",
|
||||||
"sync-button",
|
"sync-button",
|
||||||
"tabview-button",
|
"tabview-button",
|
||||||
|
"web-apps-button",
|
||||||
];
|
];
|
||||||
|
|
||||||
let panelPlacements = DEFAULT_AREA_PLACEMENTS["PanelUI-contents"];
|
let panelPlacements = DEFAULT_AREA_PLACEMENTS["PanelUI-contents"];
|
||||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 70 KiB |
@ -1131,6 +1131,13 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
|
|||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#web-apps-button[cui-areatype="toolbar"] {
|
||||||
|
-moz-image-region: rect(0, 1440px, 36px, 1404px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#web-apps-button[cui-areatype="toolbar"]:hover:active:not([disabled="true"]) {
|
||||||
|
-moz-image-region: rect(36px, 1440px, 72px, 1404px);
|
||||||
|
}
|
||||||
|
|
||||||
:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
||||||
:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
|
:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
|
||||||
@ -1290,6 +1297,11 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
|
|||||||
-moz-image-region: rect(64px, 1792px, 128px, 1728px);
|
-moz-image-region: rect(64px, 1792px, 128px, 1728px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#web-apps-button[cui-areatype="menu-panel"],
|
||||||
|
toolbarpaletteitem[place="palette"] > #web-apps-button {
|
||||||
|
-moz-image-region: rect(0, 1856px, 64px, 1792px);
|
||||||
|
}
|
||||||
|
|
||||||
toolbaritem[sdkstylewidget="true"] > toolbarbutton {
|
toolbaritem[sdkstylewidget="true"] > toolbarbutton {
|
||||||
-moz-image-region: rect(0, 1664px, 64px, 1600px);
|
-moz-image-region: rect(0, 1664px, 64px, 1600px);
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 64 KiB |
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
% Note that zoom-reset-button is a bit different since it doesn't use an image and thus has the image with display: none.
|
% Note that zoom-reset-button is a bit different since it doesn't use an image and thus has the image with display: none.
|
||||||
%define nestedButtons #zoom-out-button, #zoom-reset-button, #zoom-in-button, #cut-button, #copy-button, #paste-button
|
%define nestedButtons #zoom-out-button, #zoom-reset-button, #zoom-in-button, #cut-button, #copy-button, #paste-button
|
||||||
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #feed-button, #tabview-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@, #e10s-button, #panic-button
|
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #feed-button, #tabview-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@, #e10s-button, #panic-button, #web-apps-button
|
||||||
|
|
||||||
%ifdef XP_MACOSX
|
%ifdef XP_MACOSX
|
||||||
% Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button to exit fullscreen
|
% Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button to exit fullscreen
|
||||||
|
@ -156,6 +156,11 @@ toolbarpaletteitem[place="palette"] > #panic-button {
|
|||||||
-moz-image-region: rect(32px, 896px, 64px, 864px);
|
-moz-image-region: rect(32px, 896px, 64px, 864px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#web-apps-button[cui-areatype="menu-panel"],
|
||||||
|
toolbarpaletteitem[place="palette"] > #web-apps-button {
|
||||||
|
-moz-image-region: rect(0, 928px, 32px, 896px);
|
||||||
|
}
|
||||||
|
|
||||||
toolbaritem[sdkstylewidget="true"] > toolbarbutton {
|
toolbaritem[sdkstylewidget="true"] > toolbarbutton {
|
||||||
-moz-image-region: rect(0, 832px, 32px, 800px);
|
-moz-image-region: rect(0, 832px, 32px, 800px);
|
||||||
}
|
}
|
||||||
|
@ -190,6 +190,15 @@ toolbar[brighttext] #sync-button[status="active"]:hover:active:not([disabled="tr
|
|||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#web-apps-button[cui-areatype="toolbar"] {
|
||||||
|
-moz-image-region: rect(0, 720px, 18px, 702px);
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef XP_MACOSX
|
||||||
|
#web-apps-button[cui-areatype="toolbar"]:hover:active:not([disabled="true"]) {
|
||||||
|
-moz-image-region: rect(18px, 720px, 36px, 702px);
|
||||||
|
}
|
||||||
|
%endif
|
||||||
|
|
||||||
#loop-call-button > .toolbarbutton-badge-container {
|
#loop-call-button > .toolbarbutton-badge-container {
|
||||||
list-style-image: url(chrome://browser/skin/loop/toolbar.png);
|
list-style-image: url(chrome://browser/skin/loop/toolbar.png);
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -390,7 +390,10 @@ def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=N
|
|||||||
|
|
||||||
assert os.path.isabs(xrePath)
|
assert os.path.isabs(xrePath)
|
||||||
|
|
||||||
ldLibraryPath = xrePath
|
if mozinfo.isMac:
|
||||||
|
ldLibraryPath = os.path.join(os.path.dirname(xrePath), "MacOS")
|
||||||
|
else:
|
||||||
|
ldLibraryPath = xrePath
|
||||||
|
|
||||||
envVar = None
|
envVar = None
|
||||||
dmdLibrary = None
|
dmdLibrary = None
|
||||||
|
@ -44,14 +44,17 @@ def generate_precomplete(root_path):
|
|||||||
application update instructions. The given directory is used
|
application update instructions. The given directory is used
|
||||||
for the location to enumerate and to create the precomplete file.
|
for the location to enumerate and to create the precomplete file.
|
||||||
"""
|
"""
|
||||||
|
rel_path_precomplete = "precomplete"
|
||||||
# If inside a Mac bundle use the root of the bundle for the path.
|
# If inside a Mac bundle use the root of the bundle for the path.
|
||||||
if os.path.basename(root_path) == "MacOS":
|
if os.path.basename(root_path) == "Resources":
|
||||||
root_path = os.path.abspath(os.path.join(root_path, '../../'))
|
root_path = os.path.abspath(os.path.join(root_path, '../../'))
|
||||||
|
rel_path_precomplete = "Contents/Resources/precomplete"
|
||||||
|
|
||||||
rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
|
precomplete_file_path = os.path.join(root_path,rel_path_precomplete)
|
||||||
precomplete_file_path = os.path.join(root_path,"precomplete")
|
# Open the file so it exists before building the list of files and open it
|
||||||
# open in binary mode to prevent OS specific line endings.
|
# in binary mode to prevent OS specific line endings.
|
||||||
precomplete_file = open(precomplete_file_path, "wb")
|
precomplete_file = open(precomplete_file_path, "wb")
|
||||||
|
rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
|
||||||
for rel_file_path in rel_file_path_list:
|
for rel_file_path in rel_file_path_list:
|
||||||
precomplete_file.writelines("remove \""+rel_file_path+"\"\n")
|
precomplete_file.writelines("remove \""+rel_file_path+"\"\n")
|
||||||
|
|
||||||
|
@ -135,15 +135,26 @@ GeckoChildProcessHost::GetPathToBinary(FilePath& exePath)
|
|||||||
MOZ_ASSERT(gGREPath);
|
MOZ_ASSERT(gGREPath);
|
||||||
#ifdef OS_WIN
|
#ifdef OS_WIN
|
||||||
exePath = FilePath(char16ptr_t(gGREPath));
|
exePath = FilePath(char16ptr_t(gGREPath));
|
||||||
|
#elif MOZ_WIDGET_COCOA
|
||||||
|
nsCOMPtr<nsIFile> childProcPath;
|
||||||
|
NS_NewLocalFile(nsDependentString(gGREPath), false,
|
||||||
|
getter_AddRefs(childProcPath));
|
||||||
|
// We need to use an App Bundle on OS X so that we can hide
|
||||||
|
// the dock icon. See Bug 557225.
|
||||||
|
nsCOMPtr<nsIFile> tempPath;
|
||||||
|
childProcPath->GetParent(getter_AddRefs(tempPath));
|
||||||
|
childProcPath = tempPath.forget();
|
||||||
|
childProcPath->AppendNative(NS_LITERAL_CSTRING("MacOS"));
|
||||||
|
childProcPath->AppendNative(NS_LITERAL_CSTRING("plugin-container.app"));
|
||||||
|
childProcPath->AppendNative(NS_LITERAL_CSTRING("Contents"));
|
||||||
|
childProcPath->AppendNative(NS_LITERAL_CSTRING("MacOS"));
|
||||||
|
nsCString tempCPath;
|
||||||
|
childProcPath->GetNativePath(tempCPath);
|
||||||
|
exePath = FilePath(tempCPath.get());
|
||||||
#else
|
#else
|
||||||
nsCString path;
|
nsCString path;
|
||||||
NS_CopyUnicodeToNative(nsDependentString(gGREPath), path);
|
NS_CopyUnicodeToNative(nsDependentString(gGREPath), path);
|
||||||
exePath = FilePath(path.get());
|
exePath = FilePath(path.get());
|
||||||
#endif
|
|
||||||
#ifdef MOZ_WIDGET_COCOA
|
|
||||||
// We need to use an App Bundle on OS X so that we can hide
|
|
||||||
// the dock icon. See Bug 557225.
|
|
||||||
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_BUNDLE);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,7 +550,17 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||||||
if (ShouldHaveDirectoryService()) {
|
if (ShouldHaveDirectoryService()) {
|
||||||
MOZ_ASSERT(gGREPath);
|
MOZ_ASSERT(gGREPath);
|
||||||
nsCString path;
|
nsCString path;
|
||||||
|
#ifdef MOZ_WIDGET_COCOA
|
||||||
|
nsCOMPtr<nsIFile> grePath;
|
||||||
|
nsCOMPtr<nsIFile> tempPath;
|
||||||
|
NS_NewLocalFile(nsDependentString(gGREPath), false,
|
||||||
|
getter_AddRefs(grePath));
|
||||||
|
grePath->GetParent(getter_AddRefs(tempPath));
|
||||||
|
tempPath->AppendNative(NS_LITERAL_CSTRING("MacOS"));
|
||||||
|
tempPath->GetNativePath(path);
|
||||||
|
#else
|
||||||
NS_CopyUnicodeToNative(nsDependentString(gGREPath), path);
|
NS_CopyUnicodeToNative(nsDependentString(gGREPath), path);
|
||||||
|
#endif
|
||||||
# if defined(OS_LINUX) || defined(OS_BSD)
|
# if defined(OS_LINUX) || defined(OS_BSD)
|
||||||
# if defined(MOZ_WIDGET_ANDROID)
|
# if defined(MOZ_WIDGET_ANDROID)
|
||||||
path += "/lib";
|
path += "/lib";
|
||||||
|
@ -1351,6 +1351,23 @@ XRE_XPCShellMain(int argc, char **argv, char **envp)
|
|||||||
argc -= 2;
|
argc -= 2;
|
||||||
argv += 2;
|
argv += 2;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
// On OSX, the GreD needs to point to Contents/Resources in the .app
|
||||||
|
// bundle. Libraries will be loaded at a relative path to GreD, i.e.
|
||||||
|
// ../MacOS.
|
||||||
|
XRE_GetFileFromPath(argv[0], getter_AddRefs(greDir));
|
||||||
|
nsCOMPtr<nsIFile> parentDir;
|
||||||
|
greDir->GetParent(getter_AddRefs(parentDir));
|
||||||
|
parentDir->GetParent(getter_AddRefs(greDir));
|
||||||
|
greDir->AppendNative(NS_LITERAL_CSTRING("Resources"));
|
||||||
|
bool dirExists = false;
|
||||||
|
greDir->Exists(&dirExists);
|
||||||
|
if (!dirExists) {
|
||||||
|
printf("Setting GreD failed.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
dirprovider.SetGREDir(greDir);
|
||||||
|
#else
|
||||||
nsAutoString workingDir;
|
nsAutoString workingDir;
|
||||||
if (!GetCurrentWorkingDirectory(workingDir)) {
|
if (!GetCurrentWorkingDirectory(workingDir)) {
|
||||||
printf("GetCurrentWorkingDirectory failed.\n");
|
printf("GetCurrentWorkingDirectory failed.\n");
|
||||||
@ -1361,6 +1378,7 @@ XRE_XPCShellMain(int argc, char **argv, char **envp)
|
|||||||
printf("NS_NewLocalFile failed.\n");
|
printf("NS_NewLocalFile failed.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 1 && !strcmp(argv[1], "-a")) {
|
if (argc > 1 && !strcmp(argv[1], "-a")) {
|
||||||
|
@ -7,9 +7,6 @@
|
|||||||
#include "prlog.h"
|
#include "prlog.h"
|
||||||
#include "prenv.h"
|
#include "prenv.h"
|
||||||
#include "webrtc/system_wrappers/interface/trace.h"
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
#ifdef WEBRTC_GONK
|
|
||||||
#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nscore.h"
|
#include "nscore.h"
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
@ -56,10 +53,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static WebRtcTraceCallback gWebRtcCallback;
|
static WebRtcTraceCallback gWebRtcCallback;
|
||||||
#ifdef WEBRTC_GONK
|
|
||||||
static webrtc::LogcatTraceContext gWebRtcLogcatCallback;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
void GetWebRtcLogPrefs(uint32_t *aTraceMask, nsACString* aLogFile, nsACString *aAECLogDir, bool *aMultiLog)
|
void GetWebRtcLogPrefs(uint32_t *aTraceMask, nsACString* aLogFile, nsACString *aAECLogDir, bool *aMultiLog)
|
||||||
@ -122,13 +115,8 @@ void ConfigWebRtcLog(uint32_t trace_mask, nsCString &aLogFile, nsCString &aAECLo
|
|||||||
logFile.Append(default_log);
|
logFile.Append(default_log);
|
||||||
}
|
}
|
||||||
#elif defined(ANDROID)
|
#elif defined(ANDROID)
|
||||||
#ifdef WEBRTC_GONK
|
|
||||||
// Special case: use callback to log through logcat.
|
|
||||||
logFile.Assign("logcat");
|
|
||||||
#else
|
|
||||||
// Special case: use callback to pipe to NSPR logging.
|
// Special case: use callback to pipe to NSPR logging.
|
||||||
logFile.Assign("nspr");
|
logFile.Assign("nspr");
|
||||||
#endif
|
|
||||||
// for AEC, force the user to specify a directory
|
// for AEC, force the user to specify a directory
|
||||||
aecLogDir.Assign("/dev/null");
|
aecLogDir.Assign("/dev/null");
|
||||||
#else
|
#else
|
||||||
@ -149,10 +137,6 @@ void ConfigWebRtcLog(uint32_t trace_mask, nsCString &aLogFile, nsCString &aAECLo
|
|||||||
if (trace_mask != 0) {
|
if (trace_mask != 0) {
|
||||||
if (aLogFile.EqualsLiteral("nspr")) {
|
if (aLogFile.EqualsLiteral("nspr")) {
|
||||||
webrtc::Trace::SetTraceCallback(&gWebRtcCallback);
|
webrtc::Trace::SetTraceCallback(&gWebRtcCallback);
|
||||||
#ifdef WEBRTC_GONK
|
|
||||||
} else if (aLogFile.EqualsLiteral("logcat")) {
|
|
||||||
webrtc::Trace::SetTraceCallback(&gWebRtcLogcatCallback);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
webrtc::Trace::SetTraceFile(aLogFile.get(), multi_log);
|
webrtc::Trace::SetTraceFile(aLogFile.get(), multi_log);
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,6 @@
|
|||||||
['moz_widget_toolkit_gonk==1', {
|
['moz_widget_toolkit_gonk==1', {
|
||||||
'defines' : [
|
'defines' : [
|
||||||
'WEBRTC_GONK',
|
'WEBRTC_GONK',
|
||||||
'WEBRTC_DIRECT_TRACE',
|
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
['restrict_webrtc_logging==1', {
|
['restrict_webrtc_logging==1', {
|
||||||
|
@ -78,8 +78,8 @@ import org.mozilla.gecko.widget.GeckoActionProvider;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@ -521,14 +521,8 @@ public class BrowserApp extends GeckoApp
|
|||||||
final String args = intent.getStringExtra("args");
|
final String args = intent.getStringExtra("args");
|
||||||
|
|
||||||
if (GuestSession.shouldUse(this, args)) {
|
if (GuestSession.shouldUse(this, args)) {
|
||||||
GuestSession.configureWindow(getWindow());
|
|
||||||
mProfile = GeckoProfile.createGuestProfile(this);
|
mProfile = GeckoProfile.createGuestProfile(this);
|
||||||
} else {
|
} else {
|
||||||
// We also allow non-guest sessions if the keyguard isn't a secure one.
|
|
||||||
final KeyguardManager manager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
|
|
||||||
if (Versions.feature16Plus && !manager.isKeyguardSecure()) {
|
|
||||||
GuestSession.configureWindow(getWindow());
|
|
||||||
}
|
|
||||||
GeckoProfile.maybeCleanupGuestProfile(this);
|
GeckoProfile.maybeCleanupGuestProfile(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,6 +751,7 @@ public class BrowserApp extends GeckoApp
|
|||||||
final String args = getIntent().getStringExtra("args");
|
final String args = getIntent().getStringExtra("args");
|
||||||
// If an external intent tries to start Fennec in guest mode, and it's not already
|
// If an external intent tries to start Fennec in guest mode, and it's not already
|
||||||
// in guest mode, this will change modes before opening the url.
|
// in guest mode, this will change modes before opening the url.
|
||||||
|
// NOTE: OnResume is called twice sometimes when showing on the lock screen.
|
||||||
final boolean enableGuestSession = GuestSession.shouldUse(this, args);
|
final boolean enableGuestSession = GuestSession.shouldUse(this, args);
|
||||||
final boolean inGuestSession = GeckoProfile.get(this).inGuestMode();
|
final boolean inGuestSession = GeckoProfile.get(this).inGuestMode();
|
||||||
if (enableGuestSession != inGuestSession) {
|
if (enableGuestSession != inGuestSession) {
|
||||||
@ -765,6 +760,19 @@ public class BrowserApp extends GeckoApp
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final KeyguardManager manager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
|
||||||
|
// The test machines return null for the KeyguardService, despite running Android 4.2.
|
||||||
|
if (Versions.feature11Plus && manager != null) {
|
||||||
|
// If the keyguard is showing AND we're either in guest mode or the keyguard is insecure,
|
||||||
|
// allow showing this window. We do this in onResume so that we can avoid setting these flags if the keyguard
|
||||||
|
// is not showing since it affects Android's layout of the window.
|
||||||
|
if (manager.isKeyguardLocked() && (GeckoProfile.get(this).inGuestMode() || !manager.isKeyguardSecure())) {
|
||||||
|
GuestSession.configureWindow(getWindow());
|
||||||
|
} else {
|
||||||
|
GuestSession.unconfigureWindow(getWindow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener)this,
|
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener)this,
|
||||||
"Prompt:ShowTop");
|
"Prompt:ShowTop");
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.RelativeLayout.LayoutParams;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -60,12 +61,14 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
|||||||
}
|
}
|
||||||
private PopupType mPopupType;
|
private PopupType mPopupType;
|
||||||
|
|
||||||
|
private static final int MAX_VISIBLE_ROWS = 5;
|
||||||
|
|
||||||
private static int sAutoCompleteMinWidth;
|
private static int sAutoCompleteMinWidth;
|
||||||
private static int sAutoCompleteRowHeight;
|
private static int sAutoCompleteRowHeight;
|
||||||
private static int sValidationMessageHeight;
|
private static int sValidationMessageHeight;
|
||||||
private static int sValidationTextMarginTop;
|
private static int sValidationTextMarginTop;
|
||||||
private static RelativeLayout.LayoutParams sValidationTextLayoutNormal;
|
private static LayoutParams sValidationTextLayoutNormal;
|
||||||
private static RelativeLayout.LayoutParams sValidationTextLayoutInverted;
|
private static LayoutParams sValidationTextLayoutInverted;
|
||||||
|
|
||||||
private static final String LOGTAG = "GeckoFormAssistPopup";
|
private static final String LOGTAG = "GeckoFormAssistPopup";
|
||||||
|
|
||||||
@ -214,10 +217,10 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
|||||||
|
|
||||||
sValidationTextMarginTop = (int) (mContext.getResources().getDimension(R.dimen.validation_message_margin_top));
|
sValidationTextMarginTop = (int) (mContext.getResources().getDimension(R.dimen.validation_message_margin_top));
|
||||||
|
|
||||||
sValidationTextLayoutNormal = new RelativeLayout.LayoutParams(mValidationMessageText.getLayoutParams());
|
sValidationTextLayoutNormal = new LayoutParams(mValidationMessageText.getLayoutParams());
|
||||||
sValidationTextLayoutNormal.setMargins(0, sValidationTextMarginTop, 0, 0);
|
sValidationTextLayoutNormal.setMargins(0, sValidationTextMarginTop, 0, 0);
|
||||||
|
|
||||||
sValidationTextLayoutInverted = new RelativeLayout.LayoutParams((ViewGroup.MarginLayoutParams) sValidationTextLayoutNormal);
|
sValidationTextLayoutInverted = new LayoutParams((ViewGroup.MarginLayoutParams) sValidationTextLayoutNormal);
|
||||||
sValidationTextLayoutInverted.setMargins(0, 0, 0, 0);
|
sValidationTextLayoutInverted.setMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
mValidationMessageArrow = (ImageView) mValidationMessage.findViewById(R.id.validation_message_arrow);
|
mValidationMessageArrow = (ImageView) mValidationMessage.findViewById(R.id.validation_message_arrow);
|
||||||
@ -260,15 +263,18 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
|||||||
|
|
||||||
// Don't show the form assist popup when using fullscreen VKB
|
// Don't show the form assist popup when using fullscreen VKB
|
||||||
InputMethodManager imm =
|
InputMethodManager imm =
|
||||||
(InputMethodManager) GeckoAppShell.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
(InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
if (imm.isFullscreenMode())
|
if (imm.isFullscreenMode()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Hide/show the appropriate popup contents
|
// Hide/show the appropriate popup contents
|
||||||
if (mAutoCompleteList != null)
|
if (mAutoCompleteList != null) {
|
||||||
mAutoCompleteList.setVisibility((mPopupType == PopupType.AUTOCOMPLETE) ? VISIBLE : GONE);
|
mAutoCompleteList.setVisibility((mPopupType == PopupType.AUTOCOMPLETE) ? VISIBLE : GONE);
|
||||||
if (mValidationMessage != null)
|
}
|
||||||
|
if (mValidationMessage != null) {
|
||||||
mValidationMessage.setVisibility((mPopupType == PopupType.AUTOCOMPLETE) ? GONE : VISIBLE);
|
mValidationMessage.setVisibility((mPopupType == PopupType.AUTOCOMPLETE) ? GONE : VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
if (sAutoCompleteMinWidth == 0) {
|
if (sAutoCompleteMinWidth == 0) {
|
||||||
Resources res = mContext.getResources();
|
Resources res = mContext.getResources();
|
||||||
@ -287,7 +293,7 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
|||||||
int width = (int) (mW * zoom);
|
int width = (int) (mW * zoom);
|
||||||
int height = (int) (mH * zoom);
|
int height = (int) (mH * zoom);
|
||||||
|
|
||||||
int popupWidth = RelativeLayout.LayoutParams.MATCH_PARENT;
|
int popupWidth = LayoutParams.MATCH_PARENT;
|
||||||
int popupLeft = left < 0 ? 0 : left;
|
int popupLeft = left < 0 ? 0 : left;
|
||||||
|
|
||||||
FloatSize viewport = aMetrics.getSize();
|
FloatSize viewport = aMetrics.getSize();
|
||||||
@ -302,16 +308,24 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
|||||||
popupWidth = sAutoCompleteMinWidth;
|
popupWidth = sAutoCompleteMinWidth;
|
||||||
|
|
||||||
// Move the popup to the left if there isn't enough room for it.
|
// Move the popup to the left if there isn't enough room for it.
|
||||||
if ((popupLeft + popupWidth) > viewport.width)
|
if ((popupLeft + popupWidth) > viewport.width) {
|
||||||
popupLeft = (int) (viewport.width - popupWidth);
|
popupLeft = (int) (viewport.width - popupWidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int popupHeight;
|
int popupHeight;
|
||||||
if (mPopupType == PopupType.AUTOCOMPLETE)
|
if (mPopupType == PopupType.AUTOCOMPLETE) {
|
||||||
popupHeight = sAutoCompleteRowHeight * mAutoCompleteList.getAdapter().getCount();
|
// Limit the amount of visible rows.
|
||||||
else
|
int rows = mAutoCompleteList.getAdapter().getCount();
|
||||||
|
if (rows > MAX_VISIBLE_ROWS) {
|
||||||
|
rows = MAX_VISIBLE_ROWS;
|
||||||
|
}
|
||||||
|
|
||||||
|
popupHeight = sAutoCompleteRowHeight * rows;
|
||||||
|
} else {
|
||||||
popupHeight = sValidationMessageHeight;
|
popupHeight = sValidationMessageHeight;
|
||||||
|
}
|
||||||
|
|
||||||
int popupTop = top + height;
|
int popupTop = top + height;
|
||||||
|
|
||||||
@ -346,8 +360,7 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RelativeLayout.LayoutParams layoutParams =
|
LayoutParams layoutParams = new LayoutParams(popupWidth, popupHeight);
|
||||||
new RelativeLayout.LayoutParams(popupWidth, popupHeight);
|
|
||||||
layoutParams.setMargins(popupLeft, popupTop, 0, 0);
|
layoutParams.setMargins(popupLeft, popupTop, 0, 0);
|
||||||
setLayoutParams(layoutParams);
|
setLayoutParams(layoutParams);
|
||||||
requestLayout();
|
requestLayout();
|
||||||
|
@ -73,9 +73,14 @@ public class GuestSession {
|
|||||||
|
|
||||||
public static void configureWindow(Window window) {
|
public static void configureWindow(Window window) {
|
||||||
// In guest sessions we allow showing over the keyguard.
|
// In guest sessions we allow showing over the keyguard.
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
|
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void unconfigureWindow(Window window) {
|
||||||
|
// In guest sessions we allow showing over the keyguard.
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
private static PendingIntent getNotificationIntent(Context context) {
|
private static PendingIntent getNotificationIntent(Context context) {
|
||||||
Intent intent = new Intent(NOTIFICATION_INTENT);
|
Intent intent = new Intent(NOTIFICATION_INTENT);
|
||||||
intent.setClass(context, BrowserApp.class);
|
intent.setClass(context, BrowserApp.class);
|
||||||
|
@ -102,7 +102,7 @@ public class RemoteClientsDialogFragment extends DialogFragment {
|
|||||||
final AlertDialog dialog = (AlertDialog) dialogInterface;
|
final AlertDialog dialog = (AlertDialog) dialogInterface;
|
||||||
final SparseBooleanArray checkedItemPositions = dialog.getListView().getCheckedItemPositions();
|
final SparseBooleanArray checkedItemPositions = dialog.getListView().getCheckedItemPositions();
|
||||||
final ArrayList<RemoteClient> checked = new ArrayList<RemoteClient>();
|
final ArrayList<RemoteClient> checked = new ArrayList<RemoteClient>();
|
||||||
for (int i = 0; i < checkedItemPositions.size(); i++) {
|
for (int i = 0; i < clients.size(); i++) {
|
||||||
if (checkedItemPositions.get(i)) {
|
if (checkedItemPositions.get(i)) {
|
||||||
checked.add(clients.get(i));
|
checked.add(clients.get(i));
|
||||||
}
|
}
|
||||||
|
@ -275,6 +275,11 @@ class JavaPanZoomController
|
|||||||
} else if (MESSAGE_TOUCH_LISTENER.equals(event)) {
|
} else if (MESSAGE_TOUCH_LISTENER.equals(event)) {
|
||||||
int tabId = message.getInt("tabID");
|
int tabId = message.getInt("tabID");
|
||||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||||
|
// Make sure we still have a Tab
|
||||||
|
if (tab == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tab.setHasTouchListeners(true);
|
tab.setHasTouchListeners(true);
|
||||||
mTarget.post(new Runnable() {
|
mTarget.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
android:color="@color/text_color_primary_inverse"/>
|
android:color="@color/text_color_primary_inverse"/>
|
||||||
|
|
||||||
<item android:state_checked="true"
|
<item android:state_checked="true"
|
||||||
android:color="@color/text_color_primary"/>
|
android:color="@color/text_color_secondary"/>
|
||||||
|
|
||||||
<item android:color="@color/text_color_tertiary_inverse"/>
|
<item android:color="@color/text_color_secondary"/>
|
||||||
|
|
||||||
</selector>
|
</selector>
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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/. -->
|
|
||||||
|
|
||||||
<level-list xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:gecko="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<item android:maxLevel="1">
|
|
||||||
|
|
||||||
<selector>
|
|
||||||
|
|
||||||
<item gecko:state_private="true" android:drawable="@drawable/menu_pb"/>
|
|
||||||
<item android:drawable="@drawable/new_tablet_menu"/>
|
|
||||||
|
|
||||||
</selector>
|
|
||||||
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item android:maxLevel="2" android:drawable="@android:color/transparent"/>
|
|
||||||
|
|
||||||
</level-list>
|
|
@ -91,7 +91,7 @@
|
|||||||
style="@style/UrlBar.ImageButton"
|
style="@style/UrlBar.ImageButton"
|
||||||
android:layout_alignLeft="@id/menu"
|
android:layout_alignLeft="@id/menu"
|
||||||
android:layout_alignRight="@id/menu"
|
android:layout_alignRight="@id/menu"
|
||||||
android:src="@drawable/new_tablet_menu_level"
|
android:src="@drawable/new_tablet_menu"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<!-- We draw after the menu items so when they are hidden, the cancel button,
|
<!-- We draw after the menu items so when they are hidden, the cancel button,
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
android:paddingLeft="4dip"
|
android:paddingLeft="4dip"
|
||||||
android:background="@drawable/new_tablet_tabs_count_foreground"
|
android:background="@drawable/new_tablet_tabs_count_foreground"
|
||||||
android:textAppearance="@style/TextAppearance.Micro"
|
android:textAppearance="@style/TextAppearance.Micro"
|
||||||
android:textColor="#eeeeee"
|
android:textColor="@color/text_color_primary_inverse"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:duplicateParentState="true"
|
android:duplicateParentState="true"
|
||||||
android:gravity="center"/>
|
android:gravity="center"/>
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
<color name="text_color_tertiary">#9198A1</color>
|
<color name="text_color_tertiary">#9198A1</color>
|
||||||
|
|
||||||
<!-- Default inverse colors -->
|
<!-- Default inverse colors -->
|
||||||
<color name="text_color_primary_inverse">#FFFFFF</color>
|
<color name="text_color_primary_inverse">#F5F5F5</color>
|
||||||
<color name="text_color_secondary_inverse">#DDDDDD</color>
|
<color name="text_color_secondary_inverse">#DDDDDD</color>
|
||||||
<color name="text_color_tertiary_inverse">#A4A7A9</color>
|
<color name="text_color_tertiary_inverse">#A4A7A9</color>
|
||||||
|
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
<dimen name="browser_toolbar_button_padding">12dp</dimen>
|
<dimen name="browser_toolbar_button_padding">12dp</dimen>
|
||||||
<dimen name="browser_toolbar_icon_width">48dp</dimen>
|
<dimen name="browser_toolbar_icon_width">48dp</dimen>
|
||||||
<dimen name="browser_toolbar_lock_width">20dp</dimen>
|
<dimen name="browser_toolbar_lock_width">20dp</dimen>
|
||||||
<dimen name="browser_toolbar_favicon_size">25.33dip</dimen>
|
<!-- favicon_size includes 4dp of right padding. We can't use margin (which would allow us to
|
||||||
|
specify the actual size) because that would decrease the size of our hit target. -->
|
||||||
|
<dimen name="browser_toolbar_favicon_size">21.33dip</dimen>
|
||||||
<dimen name="browser_toolbar_shadow_size">2dp</dimen>
|
<dimen name="browser_toolbar_shadow_size">2dp</dimen>
|
||||||
|
|
||||||
<dimen name="new_tablet_tab_strip_height">48dp</dimen>
|
<dimen name="new_tablet_tab_strip_height">48dp</dimen>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<org.mozilla.gecko.preferences.SyncPreference android:key="android.not_a_preference.sync"
|
<org.mozilla.gecko.preferences.SyncPreference android:key="android.not_a_preference.sync"
|
||||||
android:title="@string/pref_sync"
|
android:title="@string/pref_sync"
|
||||||
android:summary="@string/pref_category_customize_summary"
|
android:summary="@string/pref_sync_summary"
|
||||||
android:persistent="false" />
|
android:persistent="false" />
|
||||||
|
|
||||||
<PreferenceScreen android:title="@string/pref_category_customize"
|
<PreferenceScreen android:title="@string/pref_category_customize"
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package org.mozilla.gecko.tests;
|
package org.mozilla.gecko.tests;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.mozilla.gecko.Actions;
|
import org.mozilla.gecko.Actions;
|
||||||
|
import org.mozilla.gecko.GeckoProfile;
|
||||||
import org.mozilla.gecko.home.HomePager;
|
import org.mozilla.gecko.home.HomePager;
|
||||||
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
@ -101,6 +103,11 @@ public class testAddSearchEngine extends AboutHomeTest {
|
|||||||
// Verify that the number of displayed searchengines is the same as the one received through the SearchEngines:Data event.
|
// Verify that the number of displayed searchengines is the same as the one received through the SearchEngines:Data event.
|
||||||
verifyDisplayedSearchEnginesCount(initialNumSearchEngines + 1);
|
verifyDisplayedSearchEnginesCount(initialNumSearchEngines + 1);
|
||||||
searchEngineDataEventExpector.unregisterListener();
|
searchEngineDataEventExpector.unregisterListener();
|
||||||
|
|
||||||
|
// Verify that the search plugin XML file for the new engine ended up where we expected it to.
|
||||||
|
// This file name is created in nsSearchService.js based on the name of the new engine.
|
||||||
|
final File f = GeckoProfile.get(getActivity()).getFile("searchplugins/robocop-search-engine.xml");
|
||||||
|
mAsserter.ok(f.exists(), "Checking that new search plugin file exists", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,5 +156,5 @@ public class testAddSearchEngine extends AboutHomeTest {
|
|||||||
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
|
mActions.sendSpecialKey(Actions.SpecialKey.BACK);
|
||||||
waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE);
|
waitForText(StringHelper.ROBOCOP_BLANK_PAGE_01_TITLE);
|
||||||
mAsserter.ok(correctNumSearchEnginesDisplayed, expectedCount + " Search Engines should be displayed" , "The correct number of Search Engines has been displayed");
|
mAsserter.ok(correctNumSearchEnginesDisplayed, expectedCount + " Search Engines should be displayed" , "The correct number of Search Engines has been displayed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,11 @@ public class UpdateService extends IntentService {
|
|||||||
} else if (UpdateServiceHelper.ACTION_CANCEL_DOWNLOAD.equals(intent.getAction())) {
|
} else if (UpdateServiceHelper.ACTION_CANCEL_DOWNLOAD.equals(intent.getAction())) {
|
||||||
mCancelDownload = true;
|
mCancelDownload = true;
|
||||||
} else {
|
} else {
|
||||||
|
if (!UpdateServiceHelper.ACTION_APPLY_UPDATE.equals(intent.getAction())) {
|
||||||
|
// Delete the update package used to install the current version.
|
||||||
|
deleteUpdatePackage(getLastFileName());
|
||||||
|
}
|
||||||
|
|
||||||
super.onStartCommand(intent, flags, startId);
|
super.onStartCommand(intent, flags, startId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,8 +417,26 @@ public class UpdateService extends IntentService {
|
|||||||
mNotificationManager.notify(NOTIFICATION_ID, notification);
|
mNotificationManager.notify(NOTIFICATION_ID, notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean deleteUpdatePackage(String path) {
|
||||||
|
if (path == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File pkg = new File(path);
|
||||||
|
if (!pkg.exists()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg.delete();
|
||||||
|
Log.i(LOGTAG, "deleted update package: " + path);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private File downloadUpdatePackage(UpdateInfo info, boolean overwriteExisting) {
|
private File downloadUpdatePackage(UpdateInfo info, boolean overwriteExisting) {
|
||||||
File downloadFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), new File(info.url.getFile()).getName());
|
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||||
|
String fileName = new File(info.url.getFile()).getName();
|
||||||
|
File downloadFile = new File(path, fileName);
|
||||||
|
|
||||||
if (!overwriteExisting && info.buildID.equals(getLastBuildID()) && downloadFile.exists()) {
|
if (!overwriteExisting && info.buildID.equals(getLastBuildID()) && downloadFile.exists()) {
|
||||||
// The last saved buildID is the same as the one for the current update. We also have a file
|
// The last saved buildID is the same as the one for the current update. We also have a file
|
||||||
@ -533,7 +556,7 @@ public class UpdateService extends IntentService {
|
|||||||
|
|
||||||
private void applyUpdate(String updatePath) {
|
private void applyUpdate(String updatePath) {
|
||||||
if (updatePath == null) {
|
if (updatePath == null) {
|
||||||
updatePath = mPrefs.getString(KEY_LAST_FILE_NAME, null);
|
updatePath = getLastFileName();
|
||||||
}
|
}
|
||||||
applyUpdate(new File(updatePath));
|
applyUpdate(new File(updatePath));
|
||||||
}
|
}
|
||||||
@ -569,6 +592,10 @@ public class UpdateService extends IntentService {
|
|||||||
return mPrefs.getString(KEY_LAST_HASH_VALUE, null);
|
return mPrefs.getString(KEY_LAST_HASH_VALUE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getLastFileName() {
|
||||||
|
return mPrefs.getString(KEY_LAST_FILE_NAME, null);
|
||||||
|
}
|
||||||
|
|
||||||
private Calendar getLastAttemptDate() {
|
private Calendar getLastAttemptDate() {
|
||||||
long lastAttempt = mPrefs.getLong(KEY_LAST_ATTEMPT_DATE, -1);
|
long lastAttempt = mPrefs.getLong(KEY_LAST_ATTEMPT_DATE, -1);
|
||||||
if (lastAttempt < 0)
|
if (lastAttempt < 0)
|
||||||
|
@ -98,6 +98,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetErrorHelper",
|
|||||||
XPCOMUtils.defineLazyModuleGetter(this, "PermissionsUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "PermissionsUtils",
|
||||||
"resource://gre/modules/PermissionsUtils.jsm");
|
"resource://gre/modules/PermissionsUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "SharedPreferences",
|
||||||
|
"resource://gre/modules/SharedPreferences.jsm");
|
||||||
|
|
||||||
// Lazily-loaded browser scripts:
|
// Lazily-loaded browser scripts:
|
||||||
[
|
[
|
||||||
["SelectHelper", "chrome://browser/content/SelectHelper.js"],
|
["SelectHelper", "chrome://browser/content/SelectHelper.js"],
|
||||||
@ -820,12 +823,32 @@ var BrowserApp = {
|
|||||||
Services.obs.notifyObservers(null, "FormHistory:Init", "");
|
Services.obs.notifyObservers(null, "FormHistory:Init", "");
|
||||||
Services.obs.notifyObservers(null, "Passwords:Init", "");
|
Services.obs.notifyObservers(null, "Passwords:Init", "");
|
||||||
|
|
||||||
// Migrate user-set "plugins.click_to_play" pref. See bug 884694.
|
// Migrate the UI if necessary.
|
||||||
// Because the default value is true, a user-set pref means that the pref was set to false.
|
const UI_VERSION = 1;
|
||||||
if (Services.prefs.prefHasUserValue("plugins.click_to_play")) {
|
|
||||||
Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_ENABLED);
|
let currentUIVersion = 0;
|
||||||
Services.prefs.clearUserPref("plugins.click_to_play");
|
try {
|
||||||
|
currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
|
||||||
|
} catch(ex) {}
|
||||||
|
|
||||||
|
if (currentUIVersion >= UI_VERSION) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentUIVersion < 1) {
|
||||||
|
// Migrate user-set "plugins.click_to_play" pref. See bug 884694.
|
||||||
|
// Because the default value is true, a user-set pref means that the pref was set to false.
|
||||||
|
if (Services.prefs.prefHasUserValue("plugins.click_to_play")) {
|
||||||
|
Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_ENABLED);
|
||||||
|
Services.prefs.clearUserPref("plugins.click_to_play");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the default search engine for the search activity.
|
||||||
|
SearchEngines.migrateSearchActivityDefaultPref();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the migration version.
|
||||||
|
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||||
},
|
},
|
||||||
|
|
||||||
shutdown: function shutdown() {
|
shutdown: function shutdown() {
|
||||||
@ -6764,12 +6787,16 @@ var SearchEngines = {
|
|||||||
PREF_SUGGEST_ENABLED: "browser.search.suggest.enabled",
|
PREF_SUGGEST_ENABLED: "browser.search.suggest.enabled",
|
||||||
PREF_SUGGEST_PROMPTED: "browser.search.suggest.prompted",
|
PREF_SUGGEST_PROMPTED: "browser.search.suggest.prompted",
|
||||||
|
|
||||||
|
// Shared preference key used for search activity default engine.
|
||||||
|
PREF_SEARCH_ACTIVITY_ENGINE_KEY: "search.engines.default",
|
||||||
|
|
||||||
init: function init() {
|
init: function init() {
|
||||||
Services.obs.addObserver(this, "SearchEngines:Add", false);
|
Services.obs.addObserver(this, "SearchEngines:Add", false);
|
||||||
Services.obs.addObserver(this, "SearchEngines:GetVisible", false);
|
Services.obs.addObserver(this, "SearchEngines:GetVisible", false);
|
||||||
Services.obs.addObserver(this, "SearchEngines:Remove", false);
|
Services.obs.addObserver(this, "SearchEngines:Remove", false);
|
||||||
Services.obs.addObserver(this, "SearchEngines:RestoreDefaults", false);
|
Services.obs.addObserver(this, "SearchEngines:RestoreDefaults", false);
|
||||||
Services.obs.addObserver(this, "SearchEngines:SetDefault", false);
|
Services.obs.addObserver(this, "SearchEngines:SetDefault", false);
|
||||||
|
Services.obs.addObserver(this, "browser-search-engine-modified", false);
|
||||||
|
|
||||||
let filter = {
|
let filter = {
|
||||||
matches: function (aElement) {
|
matches: function (aElement) {
|
||||||
@ -6814,6 +6841,7 @@ var SearchEngines = {
|
|||||||
Services.obs.removeObserver(this, "SearchEngines:Remove");
|
Services.obs.removeObserver(this, "SearchEngines:Remove");
|
||||||
Services.obs.removeObserver(this, "SearchEngines:RestoreDefaults");
|
Services.obs.removeObserver(this, "SearchEngines:RestoreDefaults");
|
||||||
Services.obs.removeObserver(this, "SearchEngines:SetDefault");
|
Services.obs.removeObserver(this, "SearchEngines:SetDefault");
|
||||||
|
Services.obs.removeObserver(this, "browser-search-engine-modified");
|
||||||
if (this._contextMenuId != null)
|
if (this._contextMenuId != null)
|
||||||
NativeWindow.contextmenus.remove(this._contextMenuId);
|
NativeWindow.contextmenus.remove(this._contextMenuId);
|
||||||
},
|
},
|
||||||
@ -6894,13 +6922,53 @@ var SearchEngines = {
|
|||||||
Services.search.moveEngine(engine, 0);
|
Services.search.moveEngine(engine, 0);
|
||||||
Services.search.defaultEngine = engine;
|
Services.search.defaultEngine = engine;
|
||||||
break;
|
break;
|
||||||
|
case "browser-search-engine-modified":
|
||||||
|
if (aData == "engine-default") {
|
||||||
|
this._setSearchActivityDefaultPref(aSubject.QueryInterface(Ci.nsISearchEngine));
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dump("Unexpected message type observed: " + aTopic);
|
dump("Unexpected message type observed: " + aTopic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
migrateSearchActivityDefaultPref: function migrateSearchActivityDefaultPref() {
|
||||||
|
Services.search.init(() => this._setSearchActivityDefaultPref(Services.search.defaultEngine));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Updates the search activity pref when the default engine changes.
|
||||||
|
_setSearchActivityDefaultPref: function _setSearchActivityDefaultPref(engine) {
|
||||||
|
// Helper function copied from nsSearchService.js. This is the logic that is used
|
||||||
|
// to create file names for search plugin XML serialized to disk.
|
||||||
|
function sanitizeName(aName) {
|
||||||
|
const maxLength = 60;
|
||||||
|
const minLength = 1;
|
||||||
|
let name = aName.toLowerCase();
|
||||||
|
name = name.replace(/\s+/g, "-");
|
||||||
|
name = name.replace(/[^-a-z0-9]/g, "");
|
||||||
|
|
||||||
|
if (name.length < minLength) {
|
||||||
|
// Well, in this case, we're kinda screwed. In this case, the search service
|
||||||
|
// generates a random file name, so to do this the right way, we'd need
|
||||||
|
// to open up search.json and see what file name is stored.
|
||||||
|
Cu.reportError("Couldn't create search plugin file name from engine name: " + aName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force max length.
|
||||||
|
return name.substring(0, maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
let identifier = engine.identifier;
|
||||||
|
if (identifier === null) {
|
||||||
|
// The identifier will be null for non-built-in engines. In this case, we need to
|
||||||
|
// figure out an identifier to store from the engine name.
|
||||||
|
identifier = sanitizeName(engine.name);
|
||||||
|
}
|
||||||
|
SharedPreferences.forApp().setCharPref(this.PREF_SEARCH_ACTIVITY_ENGINE_KEY, identifier);
|
||||||
|
},
|
||||||
|
|
||||||
// Display context menu listing names of the search engines available to be added.
|
// Display context menu listing names of the search engines available to be added.
|
||||||
displaySearchEnginesList: function displaySearchEnginesList(aData) {
|
displaySearchEnginesList: function displaySearchEnginesList(aData) {
|
||||||
let data = JSON.parse(aData);
|
let data = JSON.parse(aData);
|
||||||
|
@ -20,4 +20,6 @@ public class Constants {
|
|||||||
|
|
||||||
// TODO: Localize this with region.properties (or a similar solution). See bug 1065306.
|
// TODO: Localize this with region.properties (or a similar solution). See bug 1065306.
|
||||||
public static final String DEFAULT_ENGINE_IDENTIFIER = "yahoo";
|
public static final String DEFAULT_ENGINE_IDENTIFIER = "yahoo";
|
||||||
|
|
||||||
|
public static final String PREF_SEARCH_ENGINE_KEY = "search.engines.default";
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,11 @@ package org.mozilla.search;
|
|||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.ListPreference;
|
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@ -22,10 +19,6 @@ import org.mozilla.gecko.LocaleAware;
|
|||||||
import org.mozilla.gecko.Telemetry;
|
import org.mozilla.gecko.Telemetry;
|
||||||
import org.mozilla.gecko.TelemetryContract;
|
import org.mozilla.gecko.TelemetryContract;
|
||||||
import org.mozilla.gecko.db.BrowserContract;
|
import org.mozilla.gecko.db.BrowserContract;
|
||||||
import org.mozilla.search.providers.SearchEngine;
|
|
||||||
import org.mozilla.search.providers.SearchEngineManager;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This activity allows users to modify the settings for the search activity.
|
* This activity allows users to modify the settings for the search activity.
|
||||||
@ -37,15 +30,11 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* TODO: Change this to PreferenceFragment when we stop supporting devices older than SDK 11.
|
* TODO: Change this to PreferenceFragment when we stop supporting devices older than SDK 11.
|
||||||
*/
|
*/
|
||||||
public class SearchPreferenceActivity extends PreferenceActivity
|
public class SearchPreferenceActivity extends PreferenceActivity {
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
|
||||||
|
|
||||||
private static final String LOG_TAG = "SearchPreferenceActivity";
|
private static final String LOG_TAG = "SearchPreferenceActivity";
|
||||||
|
|
||||||
public static final String PREF_CLEAR_HISTORY_KEY = "search.not_a_preference.clear_history";
|
public static final String PREF_CLEAR_HISTORY_KEY = "search.not_a_preference.clear_history";
|
||||||
public static final String PREF_SEARCH_ENGINE_KEY = "search.engines.default";
|
|
||||||
|
|
||||||
private SearchEngineManager searchEngineManager;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@ -55,8 +44,6 @@ public class SearchPreferenceActivity extends PreferenceActivity
|
|||||||
|
|
||||||
getPreferenceManager().setSharedPreferencesName(GeckoSharedPrefs.APP_PREFS_NAME);
|
getPreferenceManager().setSharedPreferencesName(GeckoSharedPrefs.APP_PREFS_NAME);
|
||||||
|
|
||||||
searchEngineManager = new SearchEngineManager(this);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
if (getActionBar() != null) {
|
if (getActionBar() != null) {
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
@ -64,24 +51,6 @@ public class SearchPreferenceActivity extends PreferenceActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
searchEngineManager.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
GeckoSharedPrefs.forApp(this).registerOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
GeckoSharedPrefs.forApp(this).unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
protected void onPostCreate(Bundle savedInstanceState) {
|
||||||
super.onPostCreate(savedInstanceState);
|
super.onPostCreate(savedInstanceState);
|
||||||
@ -111,40 +80,6 @@ public class SearchPreferenceActivity extends PreferenceActivity
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setUpSearchEnginePref();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private void setUpSearchEnginePref() {
|
|
||||||
final AsyncTask<Void, Void, List<SearchEngine>> task = new AsyncTask<Void, Void, List<SearchEngine>>() {
|
|
||||||
@Override
|
|
||||||
protected List<SearchEngine> doInBackground(Void... params) {
|
|
||||||
return searchEngineManager.getAllEngines();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(List<SearchEngine> engines) {
|
|
||||||
final CharSequence[] entries = new CharSequence[engines.size()];
|
|
||||||
final CharSequence[] entryValues = new CharSequence[engines.size()];
|
|
||||||
|
|
||||||
for (int i = 0; i < engines.size(); i++) {
|
|
||||||
final SearchEngine engine = engines.get(i);
|
|
||||||
entries[i] = engine.getName();
|
|
||||||
entryValues[i] = engine.getIdentifier();
|
|
||||||
}
|
|
||||||
|
|
||||||
final ListPreference searchEnginePref = (ListPreference) findPreference(PREF_SEARCH_ENGINE_KEY);
|
|
||||||
searchEnginePref.setEntries(entries);
|
|
||||||
searchEnginePref.setEntryValues(entryValues);
|
|
||||||
|
|
||||||
if (searchEnginePref.getValue() == null) {
|
|
||||||
searchEnginePref.setValue(Constants.DEFAULT_ENGINE_IDENTIFIER);
|
|
||||||
}
|
|
||||||
searchEnginePref.setSummary(searchEnginePref.getEntry());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
task.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearHistory() {
|
private void clearHistory() {
|
||||||
@ -169,19 +104,4 @@ public class SearchPreferenceActivity extends PreferenceActivity
|
|||||||
};
|
};
|
||||||
clearHistoryTask.execute();
|
clearHistoryTask.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update summaries when the value of a shared preference changes.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
|
||||||
if (TextUtils.equals(PREF_SEARCH_ENGINE_KEY, key)) {
|
|
||||||
final ListPreference searchEnginePref = (ListPreference) findPreference(PREF_SEARCH_ENGINE_KEY);
|
|
||||||
searchEnginePref.setSummary(searchEnginePref.getEntry());
|
|
||||||
Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH_SET_DEFAULT,
|
|
||||||
TelemetryContract.Method.DIALOG,
|
|
||||||
searchEnginePref.getValue().toLowerCase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,16 @@ import android.util.Log;
|
|||||||
|
|
||||||
import org.mozilla.gecko.AppConstants;
|
import org.mozilla.gecko.AppConstants;
|
||||||
import org.mozilla.gecko.BrowserLocaleManager;
|
import org.mozilla.gecko.BrowserLocaleManager;
|
||||||
|
import org.mozilla.gecko.GeckoProfile;
|
||||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||||
import org.mozilla.gecko.util.GeckoJarReader;
|
import org.mozilla.gecko.util.GeckoJarReader;
|
||||||
import org.mozilla.search.Constants;
|
import org.mozilla.search.Constants;
|
||||||
import org.mozilla.search.R;
|
|
||||||
import org.mozilla.search.SearchPreferenceActivity;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@ -71,7 +73,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
|
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
|
||||||
if (!TextUtils.equals(SearchPreferenceActivity.PREF_SEARCH_ENGINE_KEY, key)) {
|
if (!TextUtils.equals(Constants.PREF_SEARCH_ENGINE_KEY, key)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getEngineFromPrefs(changeCallback);
|
getEngineFromPrefs(changeCallback);
|
||||||
@ -88,7 +90,7 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference
|
|||||||
final AsyncTask<Void, Void, SearchEngine> task = new AsyncTask<Void, Void, SearchEngine>() {
|
final AsyncTask<Void, Void, SearchEngine> task = new AsyncTask<Void, Void, SearchEngine>() {
|
||||||
@Override
|
@Override
|
||||||
protected SearchEngine doInBackground(Void... params) {
|
protected SearchEngine doInBackground(Void... params) {
|
||||||
String identifier = GeckoSharedPrefs.forApp(context).getString(SearchPreferenceActivity.PREF_SEARCH_ENGINE_KEY, null);
|
String identifier = GeckoSharedPrefs.forApp(context).getString(Constants.PREF_SEARCH_ENGINE_KEY, null);
|
||||||
if (!TextUtils.isEmpty(identifier)) {
|
if (!TextUtils.isEmpty(identifier)) {
|
||||||
try {
|
try {
|
||||||
return createEngine(identifier);
|
return createEngine(identifier);
|
||||||
@ -179,6 +181,10 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference
|
|||||||
private SearchEngine createEngine(String identifier) {
|
private SearchEngine createEngine(String identifier) {
|
||||||
InputStream in = getInputStreamFromJar(identifier + ".xml");
|
InputStream in = getInputStreamFromJar(identifier + ".xml");
|
||||||
|
|
||||||
|
if (in == null) {
|
||||||
|
in = getEngineFromProfile(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
// Fallback for standalone search activity.
|
// Fallback for standalone search activity.
|
||||||
if (in == null) {
|
if (in == null) {
|
||||||
in = getEngineFromAssets(identifier);
|
in = getEngineFromAssets(identifier);
|
||||||
@ -264,4 +270,22 @@ public class SearchEngineManager implements SharedPreferences.OnSharedPreference
|
|||||||
final String path = "!/chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName;
|
final String path = "!/chrome/" + locale + "/locale/" + locale + "/browser/searchplugins/" + fileName;
|
||||||
return "jar:jar:file://" + context.getPackageResourcePath() + "!/" + AppConstants.OMNIJAR_NAME + path;
|
return "jar:jar:file://" + context.getPackageResourcePath() + "!/" + AppConstants.OMNIJAR_NAME + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the search plugin XML file from the searchplugins directory in the Gecko profile.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* @return InputStream for search plugin file
|
||||||
|
*/
|
||||||
|
private InputStream getEngineFromProfile(String identifier) {
|
||||||
|
final File f = GeckoProfile.get(context).getFile("searchplugins/" + identifier + ".xml");
|
||||||
|
if (f.exists()) {
|
||||||
|
try {
|
||||||
|
return new FileInputStream(f);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.e(LOG_TAG, "Exception getting search engine from profile", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
<!-- Make sure the border only appears at the bottom of the background -->
|
<!-- Make sure the border only appears at the bottom of the background -->
|
||||||
<item
|
<item
|
||||||
android:top="-2dp"
|
android:top="-3dp"
|
||||||
android:right="-2dp"
|
android:right="-3dp"
|
||||||
android:left="-2dp">
|
android:left="-3dp">
|
||||||
<shape>
|
<shape>
|
||||||
<!-- Padding creates vertical space between the text and the underline -->
|
<!-- Padding creates vertical space between the text and the underline -->
|
||||||
<padding
|
<padding
|
||||||
|
@ -6,9 +6,4 @@
|
|||||||
<Preference
|
<Preference
|
||||||
android:key="search.not_a_preference.clear_history"
|
android:key="search.not_a_preference.clear_history"
|
||||||
android:title="@string/pref_clearHistory_title"/>
|
android:title="@string/pref_clearHistory_title"/>
|
||||||
|
|
||||||
<ListPreference
|
|
||||||
android:key="search.engines.default"
|
|
||||||
android:title="@string/pref_searchProvider_title"
|
|
||||||
android:dialogTitle="@string/pref_searchProvider_title" />
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<Param name="action" value="opensearch"/>
|
<Param name="action" value="opensearch"/>
|
||||||
<Param name="search" value="{searchTerms}"/>
|
<Param name="search" value="{searchTerms}"/>
|
||||||
</Url>
|
</Url>
|
||||||
<Url type="text/html" method="GET" template="https://en.wikipedia.org/wiki/Special:Search">
|
<Url type="text/html" method="GET" template="https://en.m.wikipedia.org/wiki/Special:Search">
|
||||||
<Param name="search" value="{searchTerms}"/>
|
<Param name="search" value="{searchTerms}"/>
|
||||||
<Param name="sourceid" value="Mozilla-search"/>
|
<Param name="sourceid" value="Mozilla-search"/>
|
||||||
</Url>
|
</Url>
|
||||||
|
@ -30,16 +30,10 @@ function getAvailableBytes(input)
|
|||||||
|
|
||||||
function runScriptSubprocess(script, args)
|
function runScriptSubprocess(script, args)
|
||||||
{
|
{
|
||||||
// logic copied from ted's crashreporter unit test
|
|
||||||
var ds = new DirectoryService();
|
var ds = new DirectoryService();
|
||||||
var bin = ds.get("CurProcD", Ci.nsILocalFile);
|
var bin = ds.get("XREExeF", Ci.nsILocalFile);
|
||||||
|
|
||||||
bin.append("xpcshell");
|
|
||||||
if (!bin.exists()) {
|
if (!bin.exists()) {
|
||||||
bin.leafName = "xpcshell.exe";
|
do_throw("Can't find xpcshell binary");
|
||||||
do_check_true(bin.exists());
|
|
||||||
if (!bin.exists())
|
|
||||||
do_throw("Can't find xpcshell binary");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var script = do_get_file(script);
|
var script = do_get_file(script);
|
||||||
|