зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b2g-inbound
--HG-- rename : mobile/android/base/resources/layout/home_history_split_pane_panel.xml => mobile/android/base/resources/layout-sw600dp-land/home_history_panel.xml extra : rebase_source : d757b3473eb5f87c9ddf60be1cb545aea556ebd0
This commit is contained in:
Коммит
857b10eeb2
|
@ -39,13 +39,11 @@ ifndef MOZ_PROFILE_USE
|
|||
# otherwise the rule in rules.mk doesn't run early enough.
|
||||
$(TIERS) binaries:: CLOBBER $(configure_dir)/configure config.status backend.RecursiveMakeBackend
|
||||
ifndef JS_STANDALONE
|
||||
ifndef LIBXUL_SDK
|
||||
ifdef COMPILE_ENVIRONMENT
|
||||
$(TIERS) binaries:: $(topsrcdir)/js/src/configure js/src/config.status
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef JS_STANDALONE
|
||||
.PHONY: CLOBBER
|
||||
|
@ -106,7 +104,6 @@ install_manifest_depends = \
|
|||
$(NULL)
|
||||
|
||||
ifndef JS_STANDALONE
|
||||
ifndef LIBXUL_SDK
|
||||
ifdef COMPILE_ENVIRONMENT
|
||||
install_manifest_depends += \
|
||||
$(topsrcdir)/js/src/configure \
|
||||
|
@ -114,7 +111,6 @@ install_manifest_depends += \
|
|||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: install-manifests
|
||||
install-manifests: $(addprefix install-,$(install_manifests))
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
# 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/.
|
||||
|
||||
if not CONFIG['LIBXUL_SDK']:
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
elif CONFIG['ENABLE_TESTS']:
|
||||
DIRS += ['/testing/mochitest']
|
||||
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
|
||||
if CONFIG['MOZ_EXTENSIONS']:
|
||||
DIRS += ['/extensions']
|
||||
|
|
|
@ -52,24 +52,14 @@ tools repackage:: $(libs-preqs)
|
|||
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/$(LPROJ)/InfoPlist.strings
|
||||
rsync -a --exclude 'mangle' --exclude 'shlibsign' --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/Resources
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/MacOS
|
||||
ifdef LIBXUL_SDK
|
||||
cp $(LIBXUL_DIST)/bin/xulrunner$(BIN_SUFFIX) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(APP_BINARY)
|
||||
rsync -a --exclude nsinstall --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework $(DIST)/$(APP_NAME).app/Contents/Frameworks
|
||||
else
|
||||
$(RM) $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
|
||||
rsync -aL $(PROGRAM) $(DIST)/$(APP_NAME).app/Contents/MacOS
|
||||
endif
|
||||
cp -RL $(DIST)/branding/app.icns $(DIST)/$(APP_NAME).app/Contents/Resources/$(MOZ_APP_NAME).icns
|
||||
printf APPLMOZB > $(DIST)/$(APP_NAME).app/Contents/PkgInfo
|
||||
|
||||
else # MOZ_WIDGET_TOOLKIT != cocoa
|
||||
|
||||
libs::
|
||||
ifdef LIBXUL_SDK
|
||||
cp $(LIBXUL_DIST)/bin/xulrunner-stub$(BIN_SUFFIX) $(DIST)/bin/$(APP_BINARY)
|
||||
$(NSINSTALL) -D $(DIST)/bin/xulrunner
|
||||
(cd $(LIBXUL_SDK)/bin && tar $(TAR_CREATE_FLAGS) - .) | (cd $(DIST)/bin/xulrunner && tar -xf -)
|
||||
endif
|
||||
$(NSINSTALL) -D $(DIST)/bin/chrome/icons/default
|
||||
|
||||
# Copy the app icon for b2g-desktop
|
||||
|
|
|
@ -4,27 +4,26 @@
|
|||
# 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/.
|
||||
|
||||
if not CONFIG['LIBXUL_SDK']:
|
||||
if CONFIG['GAIADIR']:
|
||||
GeckoProgram(CONFIG['MOZ_APP_NAME'] + "-bin")
|
||||
else:
|
||||
GeckoProgram(CONFIG['MOZ_APP_NAME'])
|
||||
if CONFIG['MOZ_B2G_LOADER']:
|
||||
SOURCES += [
|
||||
'B2GLoader.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['GAIADIR']:
|
||||
GeckoProgram(CONFIG['MOZ_APP_NAME'] + "-bin")
|
||||
else:
|
||||
GeckoProgram(CONFIG['MOZ_APP_NAME'])
|
||||
if CONFIG['MOZ_B2G_LOADER']:
|
||||
SOURCES += [
|
||||
'nsBrowserApp.cpp',
|
||||
'B2GLoader.cpp',
|
||||
]
|
||||
if CONFIG['_MSC_VER']:
|
||||
# Always enter a Windows program through wmain, whether or not we're
|
||||
# a console application.
|
||||
WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
|
||||
|
||||
USE_LIBS += [
|
||||
'zlib',
|
||||
]
|
||||
SOURCES += [
|
||||
'nsBrowserApp.cpp',
|
||||
]
|
||||
if CONFIG['_MSC_VER']:
|
||||
# Always enter a Windows program through wmain, whether or not we're
|
||||
# a console application.
|
||||
WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
|
||||
|
||||
USE_LIBS += [
|
||||
'zlib',
|
||||
]
|
||||
|
||||
for var in ('MOZ_APP_NAME', 'MOZ_APP_VERSION', 'MOZ_UPDATER'):
|
||||
DEFINES[var] = CONFIG[var]
|
||||
|
|
|
@ -44,11 +44,7 @@ fi
|
|||
# use custom widget for html:select
|
||||
MOZ_USE_NATIVE_POPUP_WINDOWS=1
|
||||
|
||||
if test "$LIBXUL_SDK"; then
|
||||
MOZ_XULRUNNER=1
|
||||
else
|
||||
MOZ_XULRUNNER=
|
||||
fi
|
||||
|
||||
MOZ_MEDIA_NAVIGATOR=1
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
if not CONFIG['LIBXUL_SDK']:
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
|
||||
if CONFIG['MOZ_EXTENSIONS']:
|
||||
DIRS += ['/extensions']
|
||||
|
|
|
@ -3,10 +3,7 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
if not CONFIG['LIBXUL_SDK']:
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
elif CONFIG['ENABLE_TESTS']:
|
||||
DIRS += ['/testing/mochitest']
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
|
||||
if CONFIG['MOZ_EXTENSIONS']:
|
||||
DIRS += ['/extensions']
|
||||
|
|
|
@ -117,18 +117,10 @@ installers-%: clobber-% langpack-% repackage-win32-installer-% repackage-zip-%
|
|||
# When we unpack b2g on MacOS X the platform.ini and application.ini are in slightly
|
||||
# different locations that on all other platforms
|
||||
ifeq (Darwin, $(OS_ARCH))
|
||||
ifdef LIBXUL_SDK
|
||||
GECKO_PLATFORM_INI_PATH='$(STAGEDIST)/../Frameworks/XUL.framework/Versions/$(MOZILLA_VERSION)/platform.ini'
|
||||
else
|
||||
GECKO_PLATFORM_INI_PATH='$(STAGEDIST)/platform.ini'
|
||||
endif
|
||||
B2G_APPLICATION_INI_PATH='$(STAGEDIST)/application.ini'
|
||||
else
|
||||
ifdef LIBXUL_SDK
|
||||
GECKO_PLATFORM_INI_PATH='$(STAGEDIST)/xulrunner/platform.ini'
|
||||
else
|
||||
GECKO_PLATFORM_INI_PATH='$(STAGEDIST)/platform.ini'
|
||||
endif
|
||||
B2G_APPLICATION_INI_PATH='$(STAGEDIST)/application.ini'
|
||||
endif
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
if not CONFIG['LIBXUL_SDK']:
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
|
||||
if CONFIG['MOZ_EXTENSIONS']:
|
||||
DIRS += ['/extensions']
|
||||
|
|
|
@ -62,12 +62,10 @@ libs::
|
|||
$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png $(FINAL_TARGET)/chrome/icons/default
|
||||
endif
|
||||
|
||||
ifndef LIBXUL_SDK
|
||||
# channel-prefs.js is handled separate from other prefs due to bug 756325
|
||||
libs:: $(srcdir)/profile/channel-prefs.js
|
||||
$(NSINSTALL) -D $(DIST)/bin/defaults/pref
|
||||
$(call py_action,preprocessor,-Fsubstitution $(PREF_PPFLAGS) $(ACDEFINES) $^ -o $(DIST)/bin/defaults/pref/channel-prefs.js)
|
||||
endif
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
||||
|
@ -107,13 +105,3 @@ tools repackage:: $(PROGRAM)
|
|||
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
|
||||
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
|
||||
endif
|
||||
|
||||
ifdef LIBXUL_SDK #{
|
||||
libs::
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{
|
||||
rsync -a --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework $(dist_dest)/Contents/Frameworks
|
||||
else
|
||||
$(NSINSTALL) -D $(DIST)/bin/xulrunner
|
||||
(cd $(LIBXUL_SDK)/bin && tar $(TAR_CREATE_FLAGS) - .) | (cd $(DIST)/bin/xulrunner && tar -xf -)
|
||||
endif #} cocoa
|
||||
endif #} LIBXUL_SDK
|
||||
|
|
|
@ -15,11 +15,6 @@ JS_PREFERENCE_FILES += [
|
|||
'profile/firefox.js',
|
||||
]
|
||||
|
||||
if CONFIG['LIBXUL_SDK']:
|
||||
PREF_JS_EXPORTS += [
|
||||
'profile/channel-prefs.js',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'nsBrowserApp.cpp',
|
||||
]
|
||||
|
@ -29,9 +24,6 @@ FINAL_TARGET_FILES.defaults.profile += ['profile/prefs.js']
|
|||
|
||||
DEFINES['APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
|
||||
|
||||
if CONFIG['LIBXUL_SDK']:
|
||||
DEFINES['LIBXUL_SDK'] = True
|
||||
|
||||
GENERATED_INCLUDES += [
|
||||
'/build',
|
||||
]
|
||||
|
|
|
@ -225,11 +225,6 @@ FileExists(const char *path)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef LIBXUL_SDK
|
||||
# define XPCOM_PATH "xulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL
|
||||
#else
|
||||
# define XPCOM_PATH XPCOM_DLL
|
||||
#endif
|
||||
static nsresult
|
||||
InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
|
||||
{
|
||||
|
@ -242,55 +237,13 @@ InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
|
|||
}
|
||||
|
||||
char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
|
||||
if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_PATH) - 1))
|
||||
if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN -
|
||||
sizeof(XPCOM_DLL) - 1))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
strcpy(lastSlash + 1, XPCOM_PATH);
|
||||
lastSlash += sizeof(XPCOM_PATH) - sizeof(XPCOM_DLL);
|
||||
strcpy(lastSlash + 1, XPCOM_DLL);
|
||||
|
||||
if (!FileExists(exePath)) {
|
||||
#if defined(LIBXUL_SDK) && defined(XP_MACOSX)
|
||||
// Check for <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib
|
||||
bool greFound = false;
|
||||
CFBundleRef appBundle = CFBundleGetMainBundle();
|
||||
if (!appBundle)
|
||||
return NS_ERROR_FAILURE;
|
||||
CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle);
|
||||
CFURLRef absfwurl = nullptr;
|
||||
if (fwurl) {
|
||||
absfwurl = CFURLCopyAbsoluteURL(fwurl);
|
||||
CFRelease(fwurl);
|
||||
}
|
||||
if (absfwurl) {
|
||||
CFURLRef xulurl =
|
||||
CFURLCreateCopyAppendingPathComponent(nullptr, absfwurl,
|
||||
CFSTR("XUL.framework"),
|
||||
true);
|
||||
|
||||
if (xulurl) {
|
||||
CFURLRef xpcomurl =
|
||||
CFURLCreateCopyAppendingPathComponent(nullptr, xulurl,
|
||||
CFSTR("libxpcom.dylib"),
|
||||
false);
|
||||
|
||||
if (xpcomurl) {
|
||||
if (CFURLGetFileSystemRepresentation(xpcomurl, true,
|
||||
(UInt8*) exePath,
|
||||
sizeof(exePath)) &&
|
||||
access(tbuffer, R_OK | X_OK) == 0) {
|
||||
if (realpath(tbuffer, exePath)) {
|
||||
greFound = true;
|
||||
}
|
||||
}
|
||||
CFRelease(xpcomurl);
|
||||
}
|
||||
CFRelease(xulurl);
|
||||
}
|
||||
CFRelease(absfwurl);
|
||||
}
|
||||
}
|
||||
if (!greFound) {
|
||||
#endif
|
||||
Output("Could not find the Mozilla runtime.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -1624,6 +1624,13 @@ pref("devtools.fontinspector.enabled", true);
|
|||
// version for each user.
|
||||
pref("devtools.telemetry.tools.opened.version", "{}");
|
||||
|
||||
// Enable the JSON View tool (an inspector for application/json documents)
|
||||
#ifdef MOZ_DEV_EDITION
|
||||
pref("devtools.jsonview.enabled", true);
|
||||
#else
|
||||
pref("devtools.jsonview.enabled", false);
|
||||
#endif
|
||||
|
||||
// Whether the character encoding menu is under the main Firefox button. This
|
||||
// preference is a string so that localizers can alter it.
|
||||
pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
|
||||
|
@ -1728,7 +1735,6 @@ pref("loop.support_url", "https://support.mozilla.org/kb/group-conversations-fir
|
|||
pref("loop.contacts.gravatars.show", false);
|
||||
pref("loop.contacts.gravatars.promo", true);
|
||||
pref("loop.browserSharing.showInfoBar", true);
|
||||
pref("loop.contextInConversations.enabled", true);
|
||||
|
||||
pref("social.sidebar.unload_timeout_ms", 10000);
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ browser.jar:
|
|||
content/browser/newtab/newTab.css (content/newtab/newTab.css)
|
||||
content/browser/newtab/newTab.inadjacent.json (content/newtab/newTab.inadjacent.json)
|
||||
content/browser/remote-newtab/newTab.xhtml (content/remote-newtab/newTab.xhtml)
|
||||
* content/browser/remote-newtab/newTab.js (content/remote-newtab/newTab.js)
|
||||
content/browser/remote-newtab/newTab.js (content/remote-newtab/newTab.js)
|
||||
content/browser/remote-newtab/newTab.css (content/remote-newtab/newTab.css)
|
||||
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
|
||||
content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js)
|
||||
|
|
|
@ -181,6 +181,12 @@ const DownloadsButton = {
|
|||
}
|
||||
};
|
||||
|
||||
Object.defineProperty(this, "DownloadsButton", {
|
||||
value: DownloadsButton,
|
||||
enumerable: true,
|
||||
writable: false
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadsIndicatorView
|
||||
|
||||
|
|
|
@ -208,46 +208,6 @@ body {
|
|||
border-top: 1px solid #d8d8d8;
|
||||
}
|
||||
|
||||
.new-room-view > .context-checkbox-checked {
|
||||
background-color: #dbf7ff;
|
||||
}
|
||||
|
||||
.new-room-view > .context {
|
||||
border-top: 1px solid #ebebeb;
|
||||
flex: 1;
|
||||
border-radius: 3px 3px 0 0;
|
||||
padding: 6px 15px 8px;
|
||||
}
|
||||
|
||||
.new-room-view > .context > .context-enabled {
|
||||
margin-bottom: .5rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.new-room-view > .context > .context-enabled > input {
|
||||
-moz-margin-start: 0;
|
||||
}
|
||||
|
||||
.new-room-view > .context > .checkbox-wrapper {
|
||||
height: 2rem;
|
||||
margin-bottom: .5em;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.new-room-view > .context > .checkbox-wrapper > .checkbox {
|
||||
border-color: #d8d8d8;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.new-room-view > .context > .checkbox-wrapper > .checkbox.checked {
|
||||
background-image: url("../shared/img/check.svg#check-blue");
|
||||
}
|
||||
|
||||
.new-room-view > .context > .checkbox-wrapper > label {
|
||||
color: #333;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.new-room-view > .btn {
|
||||
flex: 1;
|
||||
height: 3rem;
|
||||
|
@ -635,55 +595,6 @@ html[dir="rtl"] .generate-url-spinner {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* DnD menu */
|
||||
|
||||
.dnd-status {
|
||||
border: 1px solid transparent;
|
||||
padding: 2px 4px;
|
||||
margin: 0;
|
||||
/* Undo the start border + padding so that unhovered dnd-status is aligned
|
||||
as if there was no additional spacing. */
|
||||
-moz-margin-start: calc(-1px + -4px);
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.dnd-status:hover {
|
||||
border-color: #ddd;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.status-available:before,
|
||||
.status-unavailable:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: bottom;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
-moz-margin-end: .2rem;
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
|
||||
.dropdown-menu-item.status-available:before,
|
||||
.dropdown-menu-item.status-unavailable:before {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .dropdown-menu-item.status-available:before,
|
||||
html[dir="rtl"] .dropdown-menu-item.status-unavailable:before {
|
||||
margin-right: -3px;
|
||||
}
|
||||
|
||||
.status-available:before {
|
||||
background-image: url("../shared/img/icons-16x16.svg#status-available");
|
||||
}
|
||||
|
||||
.status-unavailable:before {
|
||||
background-image: url("../shared/img/icons-16x16.svg#status-unavailable");
|
||||
}
|
||||
|
||||
/* Status badges -- Available/Unavailable */
|
||||
.status {
|
||||
display: inline-block;
|
||||
|
@ -743,6 +654,12 @@ html[dir="rtl"] .user-details .dropdown-menu {
|
|||
right: 14px;
|
||||
}
|
||||
|
||||
.entries-divider {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: solid 1px #d8d8d8;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .settings-menu .dropdown-menu {
|
||||
/* This is specified separately rather than using -moz-margin-start etc, as
|
||||
we need to override .dropdown-menu's values which can't use the gecko
|
||||
|
|
|
@ -13,76 +13,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
var Button = sharedViews.Button;
|
||||
var Checkbox = sharedViews.Checkbox;
|
||||
|
||||
/**
|
||||
* Availability drop down menu subview.
|
||||
*/
|
||||
var AvailabilityDropdown = React.createClass({displayName: "AvailabilityDropdown",
|
||||
mixins: [sharedMixins.DropdownMenuMixin()],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
doNotDisturb: navigator.mozLoop.doNotDisturb
|
||||
};
|
||||
},
|
||||
|
||||
// XXX target event can either be the li, the span or the i tag
|
||||
// this makes it easier to figure out the target by making a
|
||||
// closure with the desired status already passed in.
|
||||
changeAvailability: function(newAvailabilty) {
|
||||
return function(event) {
|
||||
// Note: side effect!
|
||||
switch (newAvailabilty) {
|
||||
case "available":
|
||||
this.setState({doNotDisturb: false});
|
||||
navigator.mozLoop.doNotDisturb = false;
|
||||
break;
|
||||
case "do-not-disturb":
|
||||
this.setState({doNotDisturb: true});
|
||||
navigator.mozLoop.doNotDisturb = true;
|
||||
break;
|
||||
}
|
||||
this.hideDropdownMenu();
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var cx = React.addons.classSet;
|
||||
var availabilityDropdown = cx({
|
||||
"dropdown-menu": true,
|
||||
"hide": !this.state.showMenu
|
||||
});
|
||||
var statusIcon = cx({
|
||||
"status-unavailable": this.state.doNotDisturb,
|
||||
"status-available": !this.state.doNotDisturb
|
||||
});
|
||||
var availabilityText = this.state.doNotDisturb ?
|
||||
mozL10n.get("display_name_dnd_status") :
|
||||
mozL10n.get("display_name_available_status");
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "dropdown"},
|
||||
React.createElement("p", {className: "dnd-status"},
|
||||
React.createElement("span", {className: statusIcon,
|
||||
onClick: this.toggleDropdownMenu,
|
||||
ref: "menu-button"},
|
||||
availabilityText
|
||||
)
|
||||
),
|
||||
React.createElement("ul", {className: availabilityDropdown},
|
||||
React.createElement("li", {className: "dropdown-menu-item status-available",
|
||||
onClick: this.changeAvailability("available")},
|
||||
React.createElement("span", null, mozL10n.get("display_name_available_status"))
|
||||
),
|
||||
React.createElement("li", {className: "dropdown-menu-item status-unavailable",
|
||||
onClick: this.changeAvailability("do-not-disturb")},
|
||||
React.createElement("span", null, mozL10n.get("display_name_dnd_status"))
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var GettingStartedView = React.createClass({displayName: "GettingStartedView",
|
||||
mixins: [sharedMixins.WindowCloseMixin],
|
||||
|
||||
|
@ -290,6 +220,11 @@ loop.panel = (function(_, mozL10n) {
|
|||
this.closeWindow();
|
||||
},
|
||||
|
||||
handleToggleNotifications: function() {
|
||||
this.props.mozLoop.doNotDisturb = !this.props.mozLoop.doNotDisturb;
|
||||
this.hideDropdownMenu();
|
||||
},
|
||||
|
||||
_isSignedIn: function() {
|
||||
return !!this.props.mozLoop.userProfile;
|
||||
},
|
||||
|
@ -303,6 +238,8 @@ loop.panel = (function(_, mozL10n) {
|
|||
var cx = React.addons.classSet;
|
||||
var accountEntryCSSClass = this._isSignedIn() ? "entry-settings-signout" :
|
||||
"entry-settings-signin";
|
||||
var notificationsLabel = this.props.mozLoop.doNotDisturb ? "settings_menu_item_turnnotificationson" :
|
||||
"settings_menu_item_turnnotificationsoff";
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "settings-menu dropdown"},
|
||||
|
@ -311,6 +248,10 @@ loop.panel = (function(_, mozL10n) {
|
|||
ref: "menu-button",
|
||||
title: mozL10n.get("settings_menu_button_tooltip")}),
|
||||
React.createElement("ul", {className: cx({"dropdown-menu": true, hide: !this.state.showMenu})},
|
||||
React.createElement(SettingsDropdownEntry, {
|
||||
extraCSSClass: "entry-settings-notifications entries-divider",
|
||||
label: mozL10n.get(notificationsLabel),
|
||||
onClick: this.handleToggleNotifications}),
|
||||
React.createElement(SettingsDropdownEntry, {
|
||||
displayed: this._isSignedIn() && this.props.mozLoop.fxAEnabled,
|
||||
extraCSSClass: "entry-settings-account",
|
||||
|
@ -794,7 +735,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
checked: false,
|
||||
previewImage: "",
|
||||
description: "",
|
||||
url: ""
|
||||
|
@ -818,7 +758,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
var description = metadata.title || metadata.description;
|
||||
var url = metadata.url;
|
||||
this.setState({
|
||||
checked: false,
|
||||
previewImage: previewImage,
|
||||
description: description,
|
||||
url: url
|
||||
|
@ -826,55 +765,22 @@ loop.panel = (function(_, mozL10n) {
|
|||
}.bind(this));
|
||||
},
|
||||
|
||||
onCheckboxChange: function(newState) {
|
||||
this.setState({checked: newState.checked});
|
||||
},
|
||||
|
||||
handleCreateButtonClick: function() {
|
||||
var createRoomAction = new sharedActions.CreateRoom({
|
||||
nameTemplate: mozL10n.get("rooms_default_room_name_template")
|
||||
});
|
||||
|
||||
if (this.state.checked) {
|
||||
createRoomAction.urls = [{
|
||||
location: this.state.url,
|
||||
description: this.state.description,
|
||||
thumbnail: this.state.previewImage
|
||||
}];
|
||||
}
|
||||
createRoomAction.urls = [{
|
||||
location: this.state.url,
|
||||
description: this.state.description,
|
||||
thumbnail: this.state.previewImage
|
||||
}];
|
||||
this.props.dispatcher.dispatch(createRoomAction);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var hostname;
|
||||
|
||||
try {
|
||||
hostname = new URL(this.state.url).hostname;
|
||||
} catch (ex) {
|
||||
// Empty catch - if there's an error, then we won't show the context.
|
||||
}
|
||||
|
||||
var contextClasses = React.addons.classSet({
|
||||
context: true,
|
||||
"context-checkbox-checked": this.state.checked,
|
||||
hide: !hostname ||
|
||||
!this.props.mozLoop.getLoopPref("contextInConversations.enabled")
|
||||
});
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "new-room-view"},
|
||||
React.createElement("div", {className: contextClasses},
|
||||
React.createElement(Checkbox, {checked: this.state.checked,
|
||||
label: mozL10n.get("context_inroom_label2"),
|
||||
onChange: this.onCheckboxChange}),
|
||||
React.createElement(sharedViews.ContextUrlView, {
|
||||
allowClick: false,
|
||||
description: this.state.description,
|
||||
showContextTitle: false,
|
||||
thumbnail: this.state.previewImage,
|
||||
url: this.state.url,
|
||||
useDesktopPaths: true})
|
||||
),
|
||||
React.createElement("button", {className: "btn btn-info new-room-button",
|
||||
disabled: this.props.pendingOperation,
|
||||
onClick: this.handleCreateButtonClick},
|
||||
|
@ -996,11 +902,10 @@ loop.panel = (function(_, mozL10n) {
|
|||
store: this.props.roomStore}),
|
||||
React.createElement("div", {className: "footer"},
|
||||
React.createElement("div", {className: "user-details"},
|
||||
React.createElement(AvailabilityDropdown, null)
|
||||
React.createElement(AccountLink, {fxAEnabled: this.props.mozLoop.fxAEnabled,
|
||||
userProfile: this.state.userProfile})
|
||||
),
|
||||
React.createElement("div", {className: "signin-details"},
|
||||
React.createElement(AccountLink, {fxAEnabled: this.props.mozLoop.fxAEnabled,
|
||||
userProfile: this.state.userProfile}),
|
||||
React.createElement(SettingsDropdown, {mozLoop: this.props.mozLoop})
|
||||
)
|
||||
)
|
||||
|
@ -1042,7 +947,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
return {
|
||||
AccountLink: AccountLink,
|
||||
AvailabilityDropdown: AvailabilityDropdown,
|
||||
ConversationDropdown: ConversationDropdown,
|
||||
GettingStartedView: GettingStartedView,
|
||||
init: init,
|
||||
|
|
|
@ -13,76 +13,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
var Button = sharedViews.Button;
|
||||
var Checkbox = sharedViews.Checkbox;
|
||||
|
||||
/**
|
||||
* Availability drop down menu subview.
|
||||
*/
|
||||
var AvailabilityDropdown = React.createClass({
|
||||
mixins: [sharedMixins.DropdownMenuMixin()],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
doNotDisturb: navigator.mozLoop.doNotDisturb
|
||||
};
|
||||
},
|
||||
|
||||
// XXX target event can either be the li, the span or the i tag
|
||||
// this makes it easier to figure out the target by making a
|
||||
// closure with the desired status already passed in.
|
||||
changeAvailability: function(newAvailabilty) {
|
||||
return function(event) {
|
||||
// Note: side effect!
|
||||
switch (newAvailabilty) {
|
||||
case "available":
|
||||
this.setState({doNotDisturb: false});
|
||||
navigator.mozLoop.doNotDisturb = false;
|
||||
break;
|
||||
case "do-not-disturb":
|
||||
this.setState({doNotDisturb: true});
|
||||
navigator.mozLoop.doNotDisturb = true;
|
||||
break;
|
||||
}
|
||||
this.hideDropdownMenu();
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var cx = React.addons.classSet;
|
||||
var availabilityDropdown = cx({
|
||||
"dropdown-menu": true,
|
||||
"hide": !this.state.showMenu
|
||||
});
|
||||
var statusIcon = cx({
|
||||
"status-unavailable": this.state.doNotDisturb,
|
||||
"status-available": !this.state.doNotDisturb
|
||||
});
|
||||
var availabilityText = this.state.doNotDisturb ?
|
||||
mozL10n.get("display_name_dnd_status") :
|
||||
mozL10n.get("display_name_available_status");
|
||||
|
||||
return (
|
||||
<div className="dropdown">
|
||||
<p className="dnd-status">
|
||||
<span className={statusIcon}
|
||||
onClick={this.toggleDropdownMenu}
|
||||
ref="menu-button">
|
||||
{availabilityText}
|
||||
</span>
|
||||
</p>
|
||||
<ul className={availabilityDropdown}>
|
||||
<li className="dropdown-menu-item status-available"
|
||||
onClick={this.changeAvailability("available")}>
|
||||
<span>{mozL10n.get("display_name_available_status")}</span>
|
||||
</li>
|
||||
<li className="dropdown-menu-item status-unavailable"
|
||||
onClick={this.changeAvailability("do-not-disturb")}>
|
||||
<span>{mozL10n.get("display_name_dnd_status")}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var GettingStartedView = React.createClass({
|
||||
mixins: [sharedMixins.WindowCloseMixin],
|
||||
|
||||
|
@ -290,6 +220,11 @@ loop.panel = (function(_, mozL10n) {
|
|||
this.closeWindow();
|
||||
},
|
||||
|
||||
handleToggleNotifications: function() {
|
||||
this.props.mozLoop.doNotDisturb = !this.props.mozLoop.doNotDisturb;
|
||||
this.hideDropdownMenu();
|
||||
},
|
||||
|
||||
_isSignedIn: function() {
|
||||
return !!this.props.mozLoop.userProfile;
|
||||
},
|
||||
|
@ -303,6 +238,8 @@ loop.panel = (function(_, mozL10n) {
|
|||
var cx = React.addons.classSet;
|
||||
var accountEntryCSSClass = this._isSignedIn() ? "entry-settings-signout" :
|
||||
"entry-settings-signin";
|
||||
var notificationsLabel = this.props.mozLoop.doNotDisturb ? "settings_menu_item_turnnotificationson" :
|
||||
"settings_menu_item_turnnotificationsoff";
|
||||
|
||||
return (
|
||||
<div className="settings-menu dropdown">
|
||||
|
@ -311,6 +248,10 @@ loop.panel = (function(_, mozL10n) {
|
|||
ref="menu-button"
|
||||
title={mozL10n.get("settings_menu_button_tooltip")} />
|
||||
<ul className={cx({"dropdown-menu": true, hide: !this.state.showMenu})}>
|
||||
<SettingsDropdownEntry
|
||||
extraCSSClass="entry-settings-notifications entries-divider"
|
||||
label={mozL10n.get(notificationsLabel)}
|
||||
onClick={this.handleToggleNotifications} />
|
||||
<SettingsDropdownEntry
|
||||
displayed={this._isSignedIn() && this.props.mozLoop.fxAEnabled}
|
||||
extraCSSClass="entry-settings-account"
|
||||
|
@ -794,7 +735,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
checked: false,
|
||||
previewImage: "",
|
||||
description: "",
|
||||
url: ""
|
||||
|
@ -818,7 +758,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
var description = metadata.title || metadata.description;
|
||||
var url = metadata.url;
|
||||
this.setState({
|
||||
checked: false,
|
||||
previewImage: previewImage,
|
||||
description: description,
|
||||
url: url
|
||||
|
@ -826,55 +765,22 @@ loop.panel = (function(_, mozL10n) {
|
|||
}.bind(this));
|
||||
},
|
||||
|
||||
onCheckboxChange: function(newState) {
|
||||
this.setState({checked: newState.checked});
|
||||
},
|
||||
|
||||
handleCreateButtonClick: function() {
|
||||
var createRoomAction = new sharedActions.CreateRoom({
|
||||
nameTemplate: mozL10n.get("rooms_default_room_name_template")
|
||||
});
|
||||
|
||||
if (this.state.checked) {
|
||||
createRoomAction.urls = [{
|
||||
location: this.state.url,
|
||||
description: this.state.description,
|
||||
thumbnail: this.state.previewImage
|
||||
}];
|
||||
}
|
||||
createRoomAction.urls = [{
|
||||
location: this.state.url,
|
||||
description: this.state.description,
|
||||
thumbnail: this.state.previewImage
|
||||
}];
|
||||
this.props.dispatcher.dispatch(createRoomAction);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var hostname;
|
||||
|
||||
try {
|
||||
hostname = new URL(this.state.url).hostname;
|
||||
} catch (ex) {
|
||||
// Empty catch - if there's an error, then we won't show the context.
|
||||
}
|
||||
|
||||
var contextClasses = React.addons.classSet({
|
||||
context: true,
|
||||
"context-checkbox-checked": this.state.checked,
|
||||
hide: !hostname ||
|
||||
!this.props.mozLoop.getLoopPref("contextInConversations.enabled")
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="new-room-view">
|
||||
<div className={contextClasses}>
|
||||
<Checkbox checked={this.state.checked}
|
||||
label={mozL10n.get("context_inroom_label2")}
|
||||
onChange={this.onCheckboxChange} />
|
||||
<sharedViews.ContextUrlView
|
||||
allowClick={false}
|
||||
description={this.state.description}
|
||||
showContextTitle={false}
|
||||
thumbnail={this.state.previewImage}
|
||||
url={this.state.url}
|
||||
useDesktopPaths={true} />
|
||||
</div>
|
||||
<button className="btn btn-info new-room-button"
|
||||
disabled={this.props.pendingOperation}
|
||||
onClick={this.handleCreateButtonClick}>
|
||||
|
@ -996,11 +902,10 @@ loop.panel = (function(_, mozL10n) {
|
|||
store={this.props.roomStore} />
|
||||
<div className="footer">
|
||||
<div className="user-details">
|
||||
<AvailabilityDropdown />
|
||||
</div>
|
||||
<div className="signin-details">
|
||||
<AccountLink fxAEnabled={this.props.mozLoop.fxAEnabled}
|
||||
userProfile={this.state.userProfile}/>
|
||||
</div>
|
||||
<div className="signin-details">
|
||||
<SettingsDropdown mozLoop={this.props.mozLoop}/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1042,7 +947,6 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
return {
|
||||
AccountLink: AccountLink,
|
||||
AvailabilityDropdown: AvailabilityDropdown,
|
||||
ConversationDropdown: ConversationDropdown,
|
||||
GettingStartedView: GettingStartedView,
|
||||
init: init,
|
||||
|
|
|
@ -606,7 +606,6 @@ loop.roomViews = (function(mozL10n) {
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
contextEnabled: this.props.mozLoop.getLoopPref("contextInConversations.enabled"),
|
||||
showEditContext: false
|
||||
};
|
||||
},
|
||||
|
@ -767,7 +766,7 @@ loop.roomViews = (function(mozL10n) {
|
|||
};
|
||||
|
||||
var shouldRenderInvitationOverlay = this._shouldRenderInvitationOverlay();
|
||||
var shouldRenderEditContextView = this.state.contextEnabled && this.state.showEditContext;
|
||||
var shouldRenderEditContextView = this.state.showEditContext;
|
||||
var roomData = this.props.roomStore.getStoreState("activeRoom");
|
||||
|
||||
switch(this.state.roomState) {
|
||||
|
@ -792,7 +791,7 @@ loop.roomViews = (function(mozL10n) {
|
|||
{
|
||||
id: "edit",
|
||||
enabled: !this.state.showEditContext,
|
||||
visible: this.state.contextEnabled,
|
||||
visible: true,
|
||||
onClick: this.handleEditContextClick
|
||||
},
|
||||
{ id: "feedback" },
|
||||
|
|
|
@ -606,7 +606,6 @@ loop.roomViews = (function(mozL10n) {
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
contextEnabled: this.props.mozLoop.getLoopPref("contextInConversations.enabled"),
|
||||
showEditContext: false
|
||||
};
|
||||
},
|
||||
|
@ -767,7 +766,7 @@ loop.roomViews = (function(mozL10n) {
|
|||
};
|
||||
|
||||
var shouldRenderInvitationOverlay = this._shouldRenderInvitationOverlay();
|
||||
var shouldRenderEditContextView = this.state.contextEnabled && this.state.showEditContext;
|
||||
var shouldRenderEditContextView = this.state.showEditContext;
|
||||
var roomData = this.props.roomStore.getStoreState("activeRoom");
|
||||
|
||||
switch(this.state.roomState) {
|
||||
|
@ -792,7 +791,7 @@ loop.roomViews = (function(mozL10n) {
|
|||
{
|
||||
id: "edit",
|
||||
enabled: !this.state.showEditContext,
|
||||
visible: this.state.contextEnabled,
|
||||
visible: true,
|
||||
onClick: this.handleEditContextClick
|
||||
},
|
||||
{ id: "feedback" },
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
До Ширина: | Высота: | Размер: 72 KiB После Ширина: | Высота: | Размер: 71 KiB |
|
@ -28,8 +28,6 @@ describe("loop.conversation", function() {
|
|||
setLoopPref: setLoopPrefStub,
|
||||
getLoopPref: function(prefName) {
|
||||
switch (prefName) {
|
||||
case "contextInConversations.enabled":
|
||||
return false;
|
||||
case "debug.sdk":
|
||||
return false;
|
||||
default:
|
||||
|
|
|
@ -51,12 +51,7 @@ describe("loop.panel", function() {
|
|||
},
|
||||
setLoopPref: sandbox.stub(),
|
||||
getLoopPref: function (prefName) {
|
||||
switch (prefName) {
|
||||
case "contextInConversations.enabled":
|
||||
return true;
|
||||
default:
|
||||
return "unseen";
|
||||
}
|
||||
return "unseen";
|
||||
},
|
||||
getPluralForm: function() {
|
||||
return "fakeText";
|
||||
|
@ -131,39 +126,6 @@ describe("loop.panel", function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.AvailabilityDropdown", function() {
|
||||
var view;
|
||||
|
||||
beforeEach(function() {
|
||||
view = TestUtils.renderIntoDocument(
|
||||
React.createElement(loop.panel.AvailabilityDropdown));
|
||||
});
|
||||
|
||||
describe("doNotDisturb preference change", function() {
|
||||
beforeEach(function() {
|
||||
navigator.mozLoop.doNotDisturb = true;
|
||||
});
|
||||
|
||||
it("should toggle mozLoop.doNotDisturb to false", function() {
|
||||
var availableMenuOption = view.getDOMNode()
|
||||
.querySelector(".status-available");
|
||||
|
||||
TestUtils.Simulate.click(availableMenuOption);
|
||||
|
||||
expect(navigator.mozLoop.doNotDisturb).eql(false);
|
||||
});
|
||||
|
||||
it("should toggle the dropdown menu", function() {
|
||||
var availableMenuOption = view.getDOMNode()
|
||||
.querySelector(".dnd-status span");
|
||||
|
||||
TestUtils.Simulate.click(availableMenuOption);
|
||||
|
||||
expect(view.state.showMenu).eql(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.PanelView", function() {
|
||||
var fakeClient, dispatcher, roomStore, callUrlData;
|
||||
|
||||
|
@ -389,6 +351,46 @@ describe("loop.panel", function() {
|
|||
|
||||
sinon.assert.calledOnce(navigator.mozLoop.logOutFromFxA);
|
||||
});
|
||||
|
||||
describe("Toggle Notifications", function() {
|
||||
var view;
|
||||
|
||||
beforeEach(function() {
|
||||
view = mountTestComponent();
|
||||
});
|
||||
|
||||
it("should toggle mozLoop.doNotDisturb to false", function() {
|
||||
navigator.mozLoop.doNotDisturb = true;
|
||||
var toggleNotificationsMenuOption = view.getDOMNode()
|
||||
.querySelector(".entry-settings-notifications");
|
||||
|
||||
TestUtils.Simulate.click(toggleNotificationsMenuOption);
|
||||
|
||||
expect(navigator.mozLoop.doNotDisturb).eql(false);
|
||||
});
|
||||
|
||||
it("should toggle mozLoop.doNotDisturb to true", function() {
|
||||
navigator.mozLoop.doNotDisturb = false;
|
||||
var toggleNotificationsMenuOption = view.getDOMNode()
|
||||
.querySelector(".entry-settings-notifications");
|
||||
|
||||
TestUtils.Simulate.click(toggleNotificationsMenuOption);
|
||||
|
||||
expect(navigator.mozLoop.doNotDisturb).eql(true);
|
||||
});
|
||||
|
||||
it("should close dropdown menu", function() {
|
||||
navigator.mozLoop.doNotDisturb = true;
|
||||
var toggleNotificationsMenuOption = view.getDOMNode()
|
||||
.querySelector(".entry-settings-notifications");
|
||||
|
||||
view.setState({ showMenu: true });
|
||||
|
||||
TestUtils.Simulate.click(toggleNotificationsMenuOption);
|
||||
|
||||
expect(view.state.showMenu).eql(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Help", function() {
|
||||
|
@ -826,19 +828,6 @@ describe("loop.panel", function() {
|
|||
}));
|
||||
}
|
||||
|
||||
it("should dispatch a CreateRoom action when clicking on the Start a " +
|
||||
"conversation button",
|
||||
function() {
|
||||
navigator.mozLoop.userProfile = {email: fakeEmail};
|
||||
var view = createTestComponent(false);
|
||||
|
||||
TestUtils.Simulate.click(view.getDOMNode().querySelector(".new-room-button"));
|
||||
|
||||
sinon.assert.calledWith(dispatch, new sharedActions.CreateRoom({
|
||||
nameTemplate: "Fake title"
|
||||
}));
|
||||
});
|
||||
|
||||
it("should dispatch a CreateRoom action with context when clicking on the " +
|
||||
"Start a conversation button", function() {
|
||||
fakeMozLoop.userProfile = {email: fakeEmail};
|
||||
|
@ -859,9 +848,6 @@ describe("loop.panel", function() {
|
|||
|
||||
var node = view.getDOMNode();
|
||||
|
||||
// Select the checkbox
|
||||
TestUtils.Simulate.click(node.querySelector(".checkbox-wrapper"));
|
||||
|
||||
TestUtils.Simulate.click(node.querySelector(".new-room-button"));
|
||||
|
||||
sinon.assert.calledWith(dispatch, new sharedActions.CreateRoom({
|
||||
|
@ -881,116 +867,6 @@ describe("loop.panel", function() {
|
|||
var buttonNode = view.getDOMNode().querySelector(".new-room-button[disabled]");
|
||||
expect(buttonNode).to.not.equal(null);
|
||||
});
|
||||
|
||||
it("should show context information when a URL is available", function() {
|
||||
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||
callback({
|
||||
url: "https://www.example.com",
|
||||
description: "fake description",
|
||||
previews: [""]
|
||||
});
|
||||
};
|
||||
|
||||
var view = createTestComponent(false);
|
||||
|
||||
// Simulate being visible
|
||||
view.onDocumentVisible();
|
||||
|
||||
var contextContent = view.getDOMNode().querySelector(".context-content");
|
||||
expect(contextContent).to.not.equal(null);
|
||||
});
|
||||
|
||||
it("should cancel the checkbox when a new URL is available", function() {
|
||||
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||
callback({
|
||||
url: "https://www.example.com",
|
||||
description: "fake description",
|
||||
previews: [""]
|
||||
});
|
||||
};
|
||||
|
||||
var view = createTestComponent(false);
|
||||
|
||||
view.setState({ checked: true });
|
||||
|
||||
// Simulate being visible
|
||||
view.onDocumentVisible();
|
||||
|
||||
expect(view.state.checked).eql(false);
|
||||
});
|
||||
|
||||
it("should show a default favicon when none is available", function() {
|
||||
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||
callback({
|
||||
url: "https://www.example.com",
|
||||
description: "fake description",
|
||||
previews: [""]
|
||||
});
|
||||
};
|
||||
|
||||
var view = createTestComponent(false);
|
||||
|
||||
// Simulate being visible
|
||||
view.onDocumentVisible();
|
||||
|
||||
var previewImage = view.getDOMNode().querySelector(".context-preview");
|
||||
expect(previewImage.src).to.match(/loop\/shared\/img\/icons-16x16.svg#globe$/);
|
||||
});
|
||||
|
||||
it("should not show context information when a URL is unavailable", function() {
|
||||
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||
callback({
|
||||
url: "",
|
||||
description: "fake description",
|
||||
previews: [""]
|
||||
});
|
||||
};
|
||||
|
||||
var view = createTestComponent(false);
|
||||
|
||||
view.onDocumentVisible();
|
||||
|
||||
var contextInfo = view.getDOMNode().querySelector(".context");
|
||||
expect(contextInfo.classList.contains("hide")).to.equal(true);
|
||||
});
|
||||
|
||||
it("should show only the hostname of the url", function() {
|
||||
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||
callback({
|
||||
url: "https://www.example.com:1234",
|
||||
description: "fake description",
|
||||
previews: [""]
|
||||
});
|
||||
};
|
||||
|
||||
var view = createTestComponent(false);
|
||||
|
||||
// Simulate being visible
|
||||
view.onDocumentVisible();
|
||||
|
||||
var contextHostname = view.getDOMNode().querySelector(".context-url");
|
||||
expect(contextHostname.textContent).eql("www.example.com");
|
||||
});
|
||||
|
||||
it("should show the favicon when available", function() {
|
||||
var favicon = "data:image/x-icon;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
|
||||
fakeMozLoop.getSelectedTabMetadata = function (callback) {
|
||||
callback({
|
||||
url: "https://www.example.com:1234",
|
||||
description: "fake description",
|
||||
favicon: favicon,
|
||||
previews: ["foo.gif"]
|
||||
});
|
||||
};
|
||||
|
||||
var view = createTestComponent(false);
|
||||
|
||||
// Simulate being visible.
|
||||
view.onDocumentVisible();
|
||||
|
||||
var contextPreview = view.getDOMNode().querySelector(".context-preview");
|
||||
expect(contextPreview.src).eql(favicon);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.SignInRequestView", function() {
|
||||
|
|
|
@ -215,7 +215,6 @@ var fakeFewerContacts = fakeManyContacts.slice(0, 4);
|
|||
// Ensure we skip FTE completely.
|
||||
case "gettingStarted.seen":
|
||||
case "contacts.gravatars.promo":
|
||||
case "contextInConversations.enabled":
|
||||
return true;
|
||||
case "contacts.gravatars.show":
|
||||
return false;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
// 1. Desktop components
|
||||
// 1.1 Panel
|
||||
var AvailabilityDropdown = loop.panel.AvailabilityDropdown;
|
||||
var PanelView = loop.panel.PanelView;
|
||||
var SignInRequestView = loop.panel.SignInRequestView;
|
||||
var ContactDetailsForm = loop.contacts.ContactDetailsForm;
|
||||
|
@ -536,8 +535,7 @@
|
|||
"google-active", "history", "history-hover", "history-active", "leave",
|
||||
"screen-white", "screenmute-white", "settings", "settings-hover", "settings-active",
|
||||
"share-darkgrey", "tag", "tag-hover", "tag-active", "trash", "unblock",
|
||||
"unblock-hover", "unblock-active", "video", "video-hover", "video-active",
|
||||
"status-available", "status-unavailable"
|
||||
"unblock-hover", "unblock-active", "video", "video-hover", "video-active"
|
||||
]
|
||||
},
|
||||
|
||||
|
@ -726,20 +724,6 @@
|
|||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 410,
|
||||
summary: "Room list (No Context)",
|
||||
width: 330},
|
||||
React.createElement("div", {className: "panel"},
|
||||
React.createElement(PanelView, {client: mockClient,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: mockMozLoopLoggedInNoContext,
|
||||
notifications: notifications,
|
||||
roomStore: roomStore})
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 410,
|
||||
|
@ -754,20 +738,6 @@
|
|||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 410,
|
||||
summary: "Room list (no rooms and no context)",
|
||||
width: 330},
|
||||
React.createElement("div", {className: "panel"},
|
||||
React.createElement(PanelView, {client: mockClient,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: mockMozLoopNoRoomsNoContext,
|
||||
notifications: notifications,
|
||||
roomStore: roomStoreNoRooms})
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 410,
|
||||
|
@ -924,31 +894,6 @@
|
|||
)
|
||||
),
|
||||
|
||||
React.createElement(Section, {name: "Availability Dropdown"},
|
||||
React.createElement("p", {className: "note"},
|
||||
React.createElement("strong", null, "Note:"), " 332px wide."
|
||||
),
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 200,
|
||||
summary: "AvailabilityDropdown",
|
||||
width: 332},
|
||||
React.createElement("div", {className: "panel"},
|
||||
React.createElement(AvailabilityDropdown, null)
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 200,
|
||||
summary: "AvailabilityDropdown Expanded",
|
||||
width: 332},
|
||||
React.createElement("div", {className: "panel force-menu-show", style: {"height": "100%", "paddingTop": "50px"}},
|
||||
React.createElement(AvailabilityDropdown, null)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(Section, {name: "ContactDetail"},
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
// 1. Desktop components
|
||||
// 1.1 Panel
|
||||
var AvailabilityDropdown = loop.panel.AvailabilityDropdown;
|
||||
var PanelView = loop.panel.PanelView;
|
||||
var SignInRequestView = loop.panel.SignInRequestView;
|
||||
var ContactDetailsForm = loop.contacts.ContactDetailsForm;
|
||||
|
@ -536,8 +535,7 @@
|
|||
"google-active", "history", "history-hover", "history-active", "leave",
|
||||
"screen-white", "screenmute-white", "settings", "settings-hover", "settings-active",
|
||||
"share-darkgrey", "tag", "tag-hover", "tag-active", "trash", "unblock",
|
||||
"unblock-hover", "unblock-active", "video", "video-hover", "video-active",
|
||||
"status-available", "status-unavailable"
|
||||
"unblock-hover", "unblock-active", "video", "video-hover", "video-active"
|
||||
]
|
||||
},
|
||||
|
||||
|
@ -726,20 +724,6 @@
|
|||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={410}
|
||||
summary="Room list (No Context)"
|
||||
width={330}>
|
||||
<div className="panel">
|
||||
<PanelView client={mockClient}
|
||||
dispatcher={dispatcher}
|
||||
mozLoop={mockMozLoopLoggedInNoContext}
|
||||
notifications={notifications}
|
||||
roomStore={roomStore} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={410}
|
||||
|
@ -754,20 +738,6 @@
|
|||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={410}
|
||||
summary="Room list (no rooms and no context)"
|
||||
width={330}>
|
||||
<div className="panel">
|
||||
<PanelView client={mockClient}
|
||||
dispatcher={dispatcher}
|
||||
mozLoop={mockMozLoopNoRoomsNoContext}
|
||||
notifications={notifications}
|
||||
roomStore={roomStoreNoRooms} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={410}
|
||||
|
@ -924,31 +894,6 @@
|
|||
</FramedExample>
|
||||
</Section>
|
||||
|
||||
<Section name="Availability Dropdown">
|
||||
<p className="note">
|
||||
<strong>Note:</strong> 332px wide.
|
||||
</p>
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={200}
|
||||
summary="AvailabilityDropdown"
|
||||
width={332}>
|
||||
<div className="panel">
|
||||
<AvailabilityDropdown />
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={200}
|
||||
summary="AvailabilityDropdown Expanded"
|
||||
width={332}>
|
||||
<div className="panel force-menu-show" style={{"height": "100%", "paddingTop": "50px"}}>
|
||||
<AvailabilityDropdown />
|
||||
</div>
|
||||
</FramedExample>
|
||||
</Section>
|
||||
|
||||
<Section name="ContactDetail">
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
|
|
|
@ -1,14 +1,30 @@
|
|||
"use strict"
|
||||
|
||||
add_task(function* () {
|
||||
info("Bug 475529 - Add is the default button for the new folder dialog.");
|
||||
info("Bug 475529 - Add is the default button for the new folder dialog + " +
|
||||
"Bug 1206376 - Changing properties of a new bookmark while adding it " +
|
||||
"acts on the last bookmark in the current container");
|
||||
|
||||
// Add a new bookmark at index 0 in the unfiled folder.
|
||||
let insertionIndex = 0;
|
||||
let newBookmark = yield PlacesUtils.bookmarks.insert({
|
||||
index: insertionIndex,
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
});
|
||||
let newBookmarkId = yield PlacesUtils.promiseItemId(newBookmark.guid);
|
||||
|
||||
yield withSidebarTree("bookmarks", function* (tree) {
|
||||
// Select the new bookmark in the sidebar.
|
||||
let itemId = PlacesUIUtils.leftPaneQueries["UnfiledBookmarks"];
|
||||
tree.selectItems([itemId]);
|
||||
tree.selectItems([newBookmarkId]);
|
||||
ok(tree.controller.isCommandEnabled("placesCmd_new:folder"),
|
||||
"'placesCmd_new:folder' on current selected node is enabled");
|
||||
|
||||
// Create a new folder. Since the new bookmark is selected, and new items
|
||||
// are inserted at the index of the currently selected item, the new folder
|
||||
// will be inserted at index 0.
|
||||
yield withBookmarksDialog(
|
||||
false,
|
||||
function openDialog() {
|
||||
|
@ -24,13 +40,14 @@ add_task(function* () {
|
|||
EventUtils.synthesizeKey("VK_RETURN", {}, dialogWin);
|
||||
yield promiseTitleChangeNotification;
|
||||
|
||||
let bookmark = yield PlacesUtils.bookmarks.fetch({
|
||||
let newFolder = yield PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
index: insertionIndex,
|
||||
});
|
||||
|
||||
is(bookmark.title, "n", "folder name has been edited");
|
||||
yield PlacesUtils.bookmarks.remove(bookmark);
|
||||
is(newFolder.title, "n", "folder name has been edited");
|
||||
yield PlacesUtils.bookmarks.remove(newFolder);
|
||||
yield PlacesUtils.bookmarks.remove(newBookmark);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
// This 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/.
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
|
|
|
@ -274,8 +274,13 @@ var gPrivacyPane = {
|
|||
|
||||
// adjust the cookie controls status
|
||||
this.readAcceptCookies();
|
||||
document.getElementById("keepCookiesUntil").value = disabled ? 2 :
|
||||
document.getElementById("network.cookie.lifetimePolicy").value;
|
||||
let lifetimePolicy = document.getElementById("network.cookie.lifetimePolicy").value;
|
||||
if (lifetimePolicy != Ci.nsICookieService.ACCEPT_NORMALLY &&
|
||||
lifetimePolicy != Ci.nsICookieService.ACCEPT_SESSION &&
|
||||
lifetimePolicy != Ci.nsICookieService.ACCEPT_FOR_N_DAYS) {
|
||||
lifetimePolicy = Ci.nsICookieService.ACCEPT_NORMALLY;
|
||||
}
|
||||
document.getElementById("keepCookiesUntil").value = disabled ? 2 : lifetimePolicy;
|
||||
|
||||
// adjust the checked state of the sanitizeOnShutdown checkbox
|
||||
document.getElementById("alwaysClear").checked = disabled ? false :
|
||||
|
@ -408,7 +413,6 @@ var gPrivacyPane = {
|
|||
* network.cookie.lifetimePolicy
|
||||
* - determines how long cookies are stored:
|
||||
* 0 means keep cookies until they expire
|
||||
* 1 means ask how long to keep each cookie
|
||||
* 2 means keep cookies until the browser is closed
|
||||
*/
|
||||
|
||||
|
|
|
@ -226,7 +226,6 @@
|
|||
<menupopup>
|
||||
<menuitem label="&expire.label;" value="0"/>
|
||||
<menuitem label="&close.label;" value="2"/>
|
||||
<menuitem label="&askEachTime.label;" value="1"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<spacer flex="1"/>
|
||||
|
|
|
@ -8,7 +8,7 @@ browser.jar:
|
|||
content/browser/preferences/aboutPermissions.css
|
||||
content/browser/preferences/aboutPermissions.xml
|
||||
content/browser/preferences/applicationManager.xul
|
||||
* content/browser/preferences/applicationManager.js
|
||||
content/browser/preferences/applicationManager.js
|
||||
content/browser/preferences/blocklists.xul
|
||||
content/browser/preferences/blocklists.js
|
||||
* content/browser/preferences/colors.xul
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
skip-if = buildapp == "mulet"
|
||||
support-files =
|
||||
browser_privatebrowsing_concurrent_page.html
|
||||
browser_privatebrowsing_cookieacceptdialog.html
|
||||
browser_privatebrowsing_geoprompt_page.html
|
||||
browser_privatebrowsing_localStorage_before_after_page.html
|
||||
browser_privatebrowsing_localStorage_before_after_page2.html
|
||||
|
@ -23,7 +22,6 @@ tags = trackingprotection
|
|||
[browser_privatebrowsing_cache.js]
|
||||
[browser_privatebrowsing_certexceptionsui.js]
|
||||
[browser_privatebrowsing_concurrent.js]
|
||||
[browser_privatebrowsing_cookieacceptdialog.js]
|
||||
[browser_privatebrowsing_crh.js]
|
||||
[browser_privatebrowsing_downloadLastDir.js]
|
||||
[browser_privatebrowsing_downloadLastDir_c.js]
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>browser_privatebrowsing_cookieacceptdialog.html</title>
|
||||
<script type="application/javascript">
|
||||
document.cookie = "foo=bar";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -1,128 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This test makes sure that private browsing mode disables the "remember"
|
||||
// option in the cookie accept dialog.
|
||||
|
||||
add_task(function* test() {
|
||||
// initialization
|
||||
const TEST_URL = "http://mochi.test:8888/browser/browser/components/" +
|
||||
"privatebrowsing/test/browser/" +
|
||||
"browser_privatebrowsing_cookieacceptdialog.html";
|
||||
const BLANK_URL = "http://mochi.test:8888/";
|
||||
let cp = Cc["@mozilla.org/embedcomp/cookieprompt-service;1"].
|
||||
getService(Ci.nsICookiePromptService);
|
||||
|
||||
|
||||
function openCookieDialog(aWindow) {
|
||||
let remember = {};
|
||||
const time = (new Date("Jan 1, 2030")).getTime() / 1000;
|
||||
let cookie = {
|
||||
name: "foo",
|
||||
value: "bar",
|
||||
isDomain: true,
|
||||
host: "mozilla.org",
|
||||
path: "/baz",
|
||||
isSecure: false,
|
||||
expires: time,
|
||||
status: 0,
|
||||
policy: 0,
|
||||
isSession: false,
|
||||
expiry: time,
|
||||
isHttpOnly: true,
|
||||
QueryInterface: function(iid) {
|
||||
const validIIDs = [Ci.nsISupports, Ci.nsICookie, Ci.nsICookie2];
|
||||
for (var i = 0; i < validIIDs.length; ++i)
|
||||
if (iid == validIIDs[i])
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
|
||||
executeSoon(function () {
|
||||
cp.cookieDialog(aWindow, cookie, "mozilla.org", 10, false, remember);
|
||||
});
|
||||
return BrowserTestUtils.domWindowOpened();
|
||||
};
|
||||
|
||||
|
||||
function checkRememberOption(expectedDisabled, aWindow) {
|
||||
return Task.spawn(function* () {
|
||||
let dialogWin = yield openCookieDialog(aWindow);
|
||||
|
||||
yield new Promise(resolve => {
|
||||
dialogWin.addEventListener("load", function onLoad(event) {
|
||||
dialogWin.removeEventListener("load", onLoad, false);
|
||||
resolve();
|
||||
}, false);
|
||||
});
|
||||
|
||||
let doc = dialogWin.document;
|
||||
let remember = doc.getElementById("persistDomainAcceptance");
|
||||
ok(remember, "The remember checkbox should exist");
|
||||
|
||||
if (expectedDisabled)
|
||||
is(remember.getAttribute("disabled"), "true",
|
||||
"The checkbox should be disabled");
|
||||
else
|
||||
ok(!remember.hasAttribute("disabled"),
|
||||
"The checkbox should not be disabled");
|
||||
|
||||
yield BrowserTestUtils.closeWindow(dialogWin);
|
||||
});
|
||||
};
|
||||
|
||||
function checkSettingDialog(aIsPrivateWindow, aWindow) {
|
||||
return Task.spawn(function* () {
|
||||
let dialogOpened = false;
|
||||
let promiseDialogClosed = null;
|
||||
|
||||
function observer(subject, topic, data) {
|
||||
if (topic != "domwindowopened") { return; }
|
||||
Services.ww.unregisterNotification(observer);
|
||||
dialogOpened = true;
|
||||
|
||||
promiseDialogClosed = BrowserTestUtils.closeWindow(
|
||||
subject.QueryInterface(Ci.nsIDOMWindow));
|
||||
}
|
||||
Services.ww.registerNotification(observer);
|
||||
|
||||
let selectedBrowser = aWindow.gBrowser.selectedBrowser;
|
||||
selectedBrowser.loadURI(TEST_URL);
|
||||
yield BrowserTestUtils.browserLoaded(selectedBrowser);;
|
||||
|
||||
if (dialogOpened) {
|
||||
ok(!aIsPrivateWindow,
|
||||
"Setting dialog shown, confirm normal window");
|
||||
} else {
|
||||
Services.ww.unregisterNotification(observer);
|
||||
ok(aIsPrivateWindow,
|
||||
"Confirm setting dialog is not displayed for private window");
|
||||
}
|
||||
|
||||
yield promiseDialogClosed;
|
||||
});
|
||||
};
|
||||
|
||||
// Ask all cookies
|
||||
Services.prefs.setIntPref("network.cookie.lifetimePolicy", 1);
|
||||
|
||||
let win = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
info("Test on public window");
|
||||
|
||||
yield checkRememberOption(false, win);
|
||||
yield checkSettingDialog(false, win);
|
||||
|
||||
let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
|
||||
info("Test on private window");
|
||||
|
||||
yield checkRememberOption(true, privateWin);
|
||||
yield checkSettingDialog(true, privateWin);
|
||||
|
||||
|
||||
// Cleanup
|
||||
Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
|
||||
yield BrowserTestUtils.closeWindow(win);
|
||||
yield BrowserTestUtils.closeWindow(privateWin);
|
||||
});
|
|
@ -20,10 +20,6 @@ endif
|
|||
|
||||
DEFINES += -DMOZ_APP_NAME=$(MOZ_APP_NAME) -DPREF_DIR=$(PREF_DIR)
|
||||
|
||||
ifdef LIBXUL_SDK
|
||||
DEFINES += -DLIBXUL_SDK=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
DEFINES += -DMOZ_DEBUG=1
|
||||
endif
|
||||
|
@ -103,9 +99,7 @@ MOZ_PKG_MAC_ICON=branding/disk.icns
|
|||
MOZ_PKG_MAC_EXTRA=--symlink '/Applications:/ '
|
||||
endif
|
||||
|
||||
ifndef LIBXUL_SDK
|
||||
INSTALL_SDK = 1
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/signing.mk
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
||||
|
|
|
@ -709,15 +709,10 @@
|
|||
@RESPATH@/defaults/autoconfig/prefcalls.js
|
||||
@RESPATH@/browser/defaults/profile/prefs.js
|
||||
|
||||
#ifndef LIBXUL_SDK
|
||||
; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)
|
||||
; Technically this is an app pref file, but we are keeping it in the original
|
||||
; gre location for now.
|
||||
@RESPATH@/defaults/pref/channel-prefs.js
|
||||
#else
|
||||
; For Fx-on-xr, channel-prefs lives with the app preferences. (Bug 762588)
|
||||
@RESPATH@/@PREF_DIR@/channel-prefs.js
|
||||
#endif
|
||||
|
||||
; Services (gre) prefs
|
||||
#ifdef MOZ_SERVICES_NOTIFICATIONS
|
||||
|
|
|
@ -38,8 +38,6 @@ invite_facebook_button2=Share on Facebook
|
|||
|
||||
# Status text
|
||||
display_name_guest=Guest
|
||||
display_name_dnd_status=Do Not Disturb
|
||||
display_name_available_status=Available
|
||||
|
||||
# Error bars
|
||||
## LOCALIZATION NOTE(session_expired_error_description,could_not_authenticate,password_changed_question,try_again_later,could_not_connect,check_internet_connection,login_expired,service_not_available,problem_accessing_account):
|
||||
|
@ -86,6 +84,8 @@ settings_menu_item_account=Account
|
|||
settings_menu_item_settings=Settings
|
||||
settings_menu_item_signout=Sign Out
|
||||
settings_menu_item_signin=Sign In
|
||||
settings_menu_item_turnnotificationson=Turn Notifications On
|
||||
settings_menu_item_turnnotificationsoff=Turn Notifications Off
|
||||
settings_menu_button_tooltip=Settings
|
||||
|
||||
# Contact Strings (Panel)
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
|
||||
<!ENTITY expire.label "they expire">
|
||||
<!ENTITY close.label "I close &brandShortName;">
|
||||
<!ENTITY askEachTime.label "ask me every time">
|
||||
|
||||
<!ENTITY cookieExceptions.label "Exceptions…">
|
||||
<!ENTITY cookieExceptions.accesskey "E">
|
||||
|
|
|
@ -124,11 +124,6 @@
|
|||
background-color: -moz-Dialog;
|
||||
}
|
||||
|
||||
#urlbar:-moz-lwtheme:not([focused="true"]),
|
||||
.searchbar-textbox:-moz-lwtheme:not([focused="true"]) {
|
||||
opacity: .85;
|
||||
}
|
||||
|
||||
/* Places toolbar */
|
||||
toolbarbutton.bookmark-item:not(.subviewbutton),
|
||||
#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder {
|
||||
|
@ -577,13 +572,13 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
|
||||
/* Primary toolbar buttons */
|
||||
|
||||
.toolbarbutton-1 > .toolbarbutton-icon,
|
||||
.toolbarbutton-1 > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
toolbar .toolbarbutton-1 > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1 > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
max-width: 16px;
|
||||
}
|
||||
|
||||
.toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
||||
.toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon,
|
||||
#bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
max-width: 18px;
|
||||
}
|
||||
|
@ -622,7 +617,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) #bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
/* horizontal padding + border + actual icon width */
|
||||
max-width: 32px;
|
||||
max-width: 32px !important /* bug 561154 */;
|
||||
}
|
||||
|
||||
#nav-bar #PanelUI-menu-button {
|
||||
|
@ -707,12 +702,13 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
}
|
||||
|
||||
:-moz-any(#back-button, #forward-button) > .toolbarbutton-icon {
|
||||
border-color: ThreeDShadow !important /* bug 561154 */;
|
||||
border-color: var(--urlbar-border-color) !important /* bug 561154 */;
|
||||
}
|
||||
|
||||
:-moz-any(#back-button, #forward-button):not(:hover):not(:active):not([open=true]) > .toolbarbutton-icon,
|
||||
:-moz-any(#back-button, #forward-button)[disabled=true] > .toolbarbutton-icon {
|
||||
background-color: rgba(255,255,255,.15) !important /* bug 561154 */;
|
||||
background-color: rgba(255,255,255,.25) !important /* bug 561154 */;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#back-button {
|
||||
|
@ -845,12 +841,21 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
}
|
||||
|
||||
/* Location bar */
|
||||
#nav-bar {
|
||||
--urlbar-border-color: ThreeDShadow;
|
||||
}
|
||||
|
||||
#nav-bar:-moz-lwtheme {
|
||||
--urlbar-border-color: rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
#urlbar,
|
||||
.searchbar-textbox {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
border: 1px solid ThreeDShadow;
|
||||
border: 1px solid var(--urlbar-border-color);
|
||||
border-radius: 2px;
|
||||
background-clip: padding-box;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
|
@ -863,6 +868,17 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
background-color: -moz-field;
|
||||
}
|
||||
|
||||
#urlbar:-moz-lwtheme,
|
||||
.searchbar-textbox:-moz-lwtheme {
|
||||
background-color: rgba(255,255,255,.8);
|
||||
color: black;
|
||||
}
|
||||
|
||||
#urlbar:-moz-lwtheme[focused=true],
|
||||
.searchbar-textbox:-moz-lwtheme[focused=true] {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.urlbar-textbox-container {
|
||||
-moz-appearance: none;
|
||||
-moz-box-align: stretch;
|
||||
|
|
|
@ -596,14 +596,14 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
|
|||
|
||||
/* ----- PRIMARY TOOLBAR BUTTONS ----- */
|
||||
|
||||
.toolbarbutton-1 > .toolbarbutton-icon,
|
||||
.toolbarbutton-1 > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
toolbar .toolbarbutton-1 > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1 > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
max-width: 16px;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
.toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
||||
.toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
toolbar .toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
max-width: 18px;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -1195,8 +1195,9 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
|||
border-color: rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
#back-button:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
#back-button > .toolbarbutton-icon,
|
||||
#forward-button > .toolbarbutton-icon {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
/* Back button styles */
|
||||
|
@ -1209,6 +1210,10 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
|||
border-radius: 10000px;
|
||||
}
|
||||
|
||||
#back-button:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
#back-button:not(:-moz-lwtheme) {
|
||||
height: 33px;
|
||||
padding: 4px 5px 5px 3px;
|
||||
|
|
|
@ -685,13 +685,13 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
|||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
.toolbarbutton-1 > .toolbarbutton-icon,
|
||||
.toolbarbutton-1 > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
toolbar .toolbarbutton-1 > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1 > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon {
|
||||
max-width: 16px;
|
||||
}
|
||||
|
||||
.toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
||||
.toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > .toolbarbutton-icon,
|
||||
toolbar .toolbarbutton-1:-moz-any(@primaryToolbarButtons@) > :-moz-any(.toolbarbutton-menubutton-button, .toolbarbutton-badge-stack) > .toolbarbutton-icon,
|
||||
#bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
|
||||
max-width: 18px;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,7 @@ USE_RCS_MK := 1
|
|||
include $(topsrcdir)/config/makefiles/makeutils.mk
|
||||
|
||||
ifdef MOZ_APP_BASENAME
|
||||
ifdef LIBXUL_SDK
|
||||
APP_INI_DEPS = $(LIBXUL_DIST)/bin/platform.ini
|
||||
else
|
||||
APP_INI_DEPS = $(topsrcdir)/config/milestone.txt
|
||||
endif
|
||||
|
||||
MOZ_APP_BUILDID := $(shell cat $(DEPTH)/config/buildid)
|
||||
APP_INI_DEPS += $(DEPTH)/config/buildid
|
||||
|
|
|
@ -157,16 +157,11 @@ if test -n "$MOZ_NATIVE_NSPR" -o -n "$NSPR_CFLAGS" -o -n "$NSPR_LIBS"; then
|
|||
AC_MSG_ERROR([system NSPR does not support PR_UINT64 or including prtypes.h does not provide it]))
|
||||
CFLAGS=$_SAVE_CFLAGS
|
||||
elif test -z "$JS_POSIX_NSPR"; then
|
||||
if test -z "$LIBXUL_SDK"; then
|
||||
NSPR_CFLAGS="-I${LIBXUL_DIST}/include/nspr"
|
||||
if test -n "$GNU_CC"; then
|
||||
NSPR_LIBS="-L${LIBXUL_DIST}/lib -lnspr${NSPR_VERSION} -lplc${NSPR_VERSION} -lplds${NSPR_VERSION}"
|
||||
else
|
||||
NSPR_LIBS="${LIBXUL_DIST}/lib/nspr${NSPR_VERSION}.lib ${LIBXUL_DIST}/lib/plc${NSPR_VERSION}.lib ${LIBXUL_DIST}/lib/plds${NSPR_VERSION}.lib "
|
||||
fi
|
||||
NSPR_CFLAGS="-I${LIBXUL_DIST}/include/nspr"
|
||||
if test -n "$GNU_CC"; then
|
||||
NSPR_LIBS="-L${LIBXUL_DIST}/lib -lnspr${NSPR_VERSION} -lplc${NSPR_VERSION} -lplds${NSPR_VERSION}"
|
||||
else
|
||||
NSPR_CFLAGS=`"${LIBXUL_DIST}"/sdk/bin/nspr-config --prefix="${LIBXUL_DIST}" --includedir="${LIBXUL_DIST}/include/nspr" --cflags`
|
||||
NSPR_LIBS=`"${LIBXUL_DIST}"/sdk/bin/nspr-config --prefix="${LIBXUL_DIST}" --libdir="${LIBXUL_DIST}"/lib --libs`
|
||||
NSPR_LIBS="${LIBXUL_DIST}/lib/nspr${NSPR_VERSION}.lib ${LIBXUL_DIST}/lib/plc${NSPR_VERSION}.lib ${LIBXUL_DIST}/lib/plds${NSPR_VERSION}.lib "
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -101,17 +101,13 @@ automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
|
|||
AUTOMATION_EXTRA_CMDLINE-l10n-check = -j1
|
||||
AUTOMATION_EXTRA_CMDLINE-pretty-l10n-check = -j1
|
||||
|
||||
# And force -j1 here until bug 1077670 is fixed.
|
||||
AUTOMATION_EXTRA_CMDLINE-package-tests = -j1
|
||||
AUTOMATION_EXTRA_CMDLINE-pretty-package-tests = -j1
|
||||
|
||||
# The commands only run if the corresponding MOZ_AUTOMATION_* variable is
|
||||
# enabled. This means, for example, if we enable MOZ_AUTOMATION_UPLOAD, then
|
||||
# 'buildsymbols' will only run if MOZ_AUTOMATION_BUILD_SYMBOLS is also set.
|
||||
# However, the target automation/buildsymbols will still be executed in this
|
||||
# case because it is a prerequisite of automation/upload.
|
||||
define automation_commands
|
||||
@$(MAKE) $1 $(AUTOMATION_EXTRA_CMDLINE-$1)
|
||||
@+$(MAKE) $1 $(AUTOMATION_EXTRA_CMDLINE-$1)
|
||||
$(call BUILDSTATUS,TIER_FINISH $1)
|
||||
endef
|
||||
|
||||
|
|
|
@ -64,7 +64,9 @@ def updated_env(env):
|
|||
def build_tar_package(tar, name, base, directory):
|
||||
name = os.path.realpath(name)
|
||||
run_in(base, [tar,
|
||||
"-c -%s -f" % ("J" if ".xz" in name else "j"),
|
||||
"-c",
|
||||
"-%s" % ("J" if ".xz" in name else "j"),
|
||||
"-f",
|
||||
name, directory])
|
||||
|
||||
|
||||
|
|
|
@ -301,7 +301,6 @@ ifndef IS_GYP_DIR
|
|||
# NSPR_CFLAGS and NSS_CFLAGS must appear ahead of the other flags to avoid Linux
|
||||
# builds wrongly picking up system NSPR/NSS header files.
|
||||
OS_INCLUDES := \
|
||||
$(if $(LIBXUL_SDK),-I$(LIBXUL_SDK)/include) \
|
||||
$(NSPR_CFLAGS) $(NSS_CFLAGS) \
|
||||
$(MOZ_JPEG_CFLAGS) \
|
||||
$(MOZ_PNG_CFLAGS) \
|
||||
|
@ -432,13 +431,8 @@ HOST_CXXFLAGS += $(HOST_DEFINES) $(MOZBUILD_HOST_CXXFLAGS)
|
|||
# Override defaults
|
||||
|
||||
# Default location of include files
|
||||
ifndef LIBXUL_SDK
|
||||
IDL_PARSER_DIR = $(topsrcdir)/xpcom/idl-parser
|
||||
IDL_PARSER_CACHE_DIR = $(DEPTH)/xpcom/idl-parser
|
||||
else
|
||||
IDL_PARSER_DIR = $(LIBXUL_SDK)/sdk/bin
|
||||
IDL_PARSER_CACHE_DIR = $(LIBXUL_SDK)/sdk/bin
|
||||
endif
|
||||
|
||||
SDK_LIB_DIR = $(DIST)/sdk/lib
|
||||
SDK_BIN_DIR = $(DIST)/sdk/bin
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifdef LIBXUL_SDK
|
||||
$(error config/external/nspr/Makefile.in is not compatible with --enable-libxul-sdk=)
|
||||
endif
|
||||
ifdef MOZ_BUILD_NSPR
|
||||
|
||||
# Copy NSPR to the SDK
|
||||
|
|
|
@ -30,10 +30,6 @@ dist_idl_dir := $(DIST)/idl
|
|||
dist_include_dir := $(DIST)/include
|
||||
process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
|
||||
|
||||
ifdef LIBXUL_SDK
|
||||
libxul_sdk_includes := -I$(LIBXUL_SDK)/idl
|
||||
endif
|
||||
|
||||
# TODO we should use py_action, but that would require extra directories to be
|
||||
# in the virtualenv.
|
||||
%.xpt:
|
||||
|
|
|
@ -1148,7 +1148,7 @@ PREF_DIR = defaults/pref
|
|||
# If DIST_SUBDIR is defined it indicates that app and gre dirs are
|
||||
# different and that we are building app related resources. Hence,
|
||||
# PREF_DIR should point to the app prefs location.
|
||||
ifneq (,$(DIST_SUBDIR)$(XPI_NAME)$(LIBXUL_SDK))
|
||||
ifneq (,$(DIST_SUBDIR)$(XPI_NAME))
|
||||
PREF_DIR = defaults/preferences
|
||||
endif
|
||||
|
||||
|
|
28
configure.in
28
configure.in
|
@ -3344,11 +3344,7 @@ MOZ_CONFIG_NSPR()
|
|||
|
||||
dnl set GRE_MILESTONE
|
||||
dnl ========================================================
|
||||
if test -n "$LIBXUL_SDK"; then
|
||||
GRE_MILESTONE=`$PYTHON "$_topsrcdir"/config/printconfigsetting.py "$LIBXUL_DIST"/bin/platform.ini Build Milestone`
|
||||
else
|
||||
GRE_MILESTONE=`tail -n 1 "$_topsrcdir"/config/milestone.txt 2>/dev/null || tail -1 "$_topsrcdir"/config/milestone.txt`
|
||||
fi
|
||||
GRE_MILESTONE=`tail -n 1 "$_topsrcdir"/config/milestone.txt 2>/dev/null || tail -1 "$_topsrcdir"/config/milestone.txt`
|
||||
AC_SUBST(GRE_MILESTONE)
|
||||
|
||||
# set RELEASE_BUILD and NIGHTLY_BUILD variables depending on the cycle we're in
|
||||
|
@ -3989,15 +3985,6 @@ if test -n "$WITH_APP_BASENAME" ; then
|
|||
MOZ_APP_BASENAME="$WITH_APP_BASENAME"
|
||||
fi
|
||||
|
||||
# Now is a good time to test for logic errors, define mismatches, etc.
|
||||
case "$MOZ_BUILD_APP" in
|
||||
xulrunner)
|
||||
if test "$LIBXUL_SDK"; then
|
||||
AC_MSG_ERROR([Building XULRunner --with-libxul-sdk doesn't make sense; XULRunner provides the libxul SDK.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Special cases where we need to AC_DEFINE something. Also a holdover for apps
|
||||
# that haven't made a confvars.sh yet. Don't add new stuff here, use
|
||||
# MOZ_BUILD_APP.
|
||||
|
@ -6276,11 +6263,6 @@ if test -z "$MOZ_ENABLE_GIO" -a `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; th
|
|||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
|
||||
fi
|
||||
|
||||
dnl Do not build gio with libxul based apps
|
||||
if test -n "$LIBXUL_SDK_DIR" -a `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
|
||||
fi
|
||||
|
||||
if test `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
|
||||
MOZ_GIO_COMPONENT=1
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
|
||||
|
@ -9139,8 +9121,7 @@ AC_SUBST(JS_SHARED_LIBRARY)
|
|||
|
||||
MOZ_CREATE_CONFIG_STATUS()
|
||||
|
||||
# No need to run subconfigures when building with LIBXUL_SDK_DIR
|
||||
if test "$COMPILE_ENVIRONMENT" -a -z "$LIBXUL_SDK_DIR"; then
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
MOZ_SUBCONFIGURE_ICU()
|
||||
MOZ_SUBCONFIGURE_FFI()
|
||||
MOZ_SUBCONFIGURE_JEMALLOC()
|
||||
|
@ -9208,8 +9189,7 @@ if test -n "$_subconfigure_subdir"; then
|
|||
srcdir="$_save_srcdir"
|
||||
fi
|
||||
|
||||
# No need to run subconfigures when building with LIBXUL_SDK_DIR
|
||||
if test "$COMPILE_ENVIRONMENT" -a -z "$LIBXUL_SDK_DIR"; then
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
|
||||
export WRAP_LDFLAGS
|
||||
|
||||
|
@ -9288,7 +9268,7 @@ fi
|
|||
AC_OUTPUT_SUBDIRS(js/src,$cache_file)
|
||||
ac_configure_args="$_SUBDIR_CONFIG_ARGS"
|
||||
|
||||
fi # COMPILE_ENVIRONMENT && !LIBXUL_SDK_DIR
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
export WRITE_MOZINFO=1
|
||||
dnl we need to run config.status after js/src subconfigure because we're
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<button id="toggle-all" standalone="true" class="devtools-button pause-button"></button>
|
||||
</div>
|
||||
<div id="timeline-toolbar" class="theme-toolbar">
|
||||
<button id="rewind-timeline" standalone="true" class="devtools-button"></button>
|
||||
<button id="pause-resume-timeline" standalone="true" class="devtools-button pause-button paused"></button>
|
||||
</div>
|
||||
<div id="players"></div>
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
const {AnimationsTimeline} = require("devtools/client/animationinspector/components");
|
||||
|
||||
var $ = (selector, target = document) => target.querySelector(selector);
|
||||
|
||||
/**
|
||||
* The main animations panel UI.
|
||||
*/
|
||||
|
@ -29,22 +31,23 @@ var AnimationsPanel = {
|
|||
}
|
||||
this.initialized = promise.defer();
|
||||
|
||||
this.playersEl = document.querySelector("#players");
|
||||
this.errorMessageEl = document.querySelector("#error-message");
|
||||
this.pickerButtonEl = document.querySelector("#element-picker");
|
||||
this.toggleAllButtonEl = document.querySelector("#toggle-all");
|
||||
this.playTimelineButtonEl = document.querySelector("#pause-resume-timeline");
|
||||
this.playersEl = $("#players");
|
||||
this.errorMessageEl = $("#error-message");
|
||||
this.pickerButtonEl = $("#element-picker");
|
||||
this.toggleAllButtonEl = $("#toggle-all");
|
||||
this.playTimelineButtonEl = $("#pause-resume-timeline");
|
||||
this.rewindTimelineButtonEl = $("#rewind-timeline");
|
||||
|
||||
// If the server doesn't support toggling all animations at once, hide the
|
||||
// whole global toolbar.
|
||||
if (!AnimationsController.traits.hasToggleAll) {
|
||||
document.querySelector("#global-toolbar").style.display = "none";
|
||||
$("#global-toolbar").style.display = "none";
|
||||
}
|
||||
|
||||
// Binding functions that need to be called in scope.
|
||||
for (let functionName of ["onPickerStarted", "onPickerStopped",
|
||||
"refreshAnimations", "toggleAll", "onTabNavigated",
|
||||
"onTimelineDataChanged", "playPauseTimeline"]) {
|
||||
"refreshAnimationsUI", "toggleAll", "onTabNavigated",
|
||||
"onTimelineDataChanged", "playPauseTimeline", "rewindTimeline"]) {
|
||||
this[functionName] = this[functionName].bind(this);
|
||||
}
|
||||
let hUtils = gToolbox.highlighterUtils;
|
||||
|
@ -55,7 +58,7 @@ var AnimationsPanel = {
|
|||
|
||||
this.startListeners();
|
||||
|
||||
yield this.refreshAnimations();
|
||||
yield this.refreshAnimationsUI();
|
||||
|
||||
this.initialized.resolve();
|
||||
|
||||
|
@ -80,14 +83,14 @@ var AnimationsPanel = {
|
|||
|
||||
this.playersEl = this.errorMessageEl = null;
|
||||
this.toggleAllButtonEl = this.pickerButtonEl = null;
|
||||
this.playTimelineButtonEl = null;
|
||||
this.playTimelineButtonEl = this.rewindTimelineButtonEl = null;
|
||||
|
||||
this.destroyed.resolve();
|
||||
}),
|
||||
|
||||
startListeners: function() {
|
||||
AnimationsController.on(AnimationsController.PLAYERS_UPDATED_EVENT,
|
||||
this.refreshAnimations);
|
||||
this.refreshAnimationsUI);
|
||||
|
||||
this.pickerButtonEl.addEventListener("click", this.togglePicker);
|
||||
gToolbox.on("picker-started", this.onPickerStarted);
|
||||
|
@ -95,6 +98,8 @@ var AnimationsPanel = {
|
|||
|
||||
this.toggleAllButtonEl.addEventListener("click", this.toggleAll);
|
||||
this.playTimelineButtonEl.addEventListener("click", this.playPauseTimeline);
|
||||
this.rewindTimelineButtonEl.addEventListener("click", this.rewindTimeline);
|
||||
|
||||
gToolbox.target.on("navigate", this.onTabNavigated);
|
||||
|
||||
this.animationsTimelineComponent.on("timeline-data-changed",
|
||||
|
@ -103,7 +108,7 @@ var AnimationsPanel = {
|
|||
|
||||
stopListeners: function() {
|
||||
AnimationsController.off(AnimationsController.PLAYERS_UPDATED_EVENT,
|
||||
this.refreshAnimations);
|
||||
this.refreshAnimationsUI);
|
||||
|
||||
this.pickerButtonEl.removeEventListener("click", this.togglePicker);
|
||||
gToolbox.off("picker-started", this.onPickerStarted);
|
||||
|
@ -111,6 +116,8 @@ var AnimationsPanel = {
|
|||
|
||||
this.toggleAllButtonEl.removeEventListener("click", this.toggleAll);
|
||||
this.playTimelineButtonEl.removeEventListener("click", this.playPauseTimeline);
|
||||
this.rewindTimelineButtonEl.removeEventListener("click", this.rewindTimeline);
|
||||
|
||||
gToolbox.target.off("navigate", this.onTabNavigated);
|
||||
|
||||
this.animationsTimelineComponent.off("timeline-data-changed",
|
||||
|
@ -147,16 +154,21 @@ var AnimationsPanel = {
|
|||
* If the animations are playing, this will pause them.
|
||||
* If the animations are paused, this will resume them.
|
||||
*/
|
||||
playPauseTimeline: Task.async(function*() {
|
||||
yield AnimationsController.toggleCurrentAnimations(this.timelineData.isMoving);
|
||||
playPauseTimeline: function() {
|
||||
AnimationsController.toggleCurrentAnimations(this.timelineData.isMoving)
|
||||
.then(() => this.refreshAnimationsStateAndUI())
|
||||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
// Now that the playState have been changed make sure the player (the
|
||||
// fronts) are up to date, and then refresh the UI.
|
||||
for (let player of AnimationsController.animationPlayers) {
|
||||
yield player.refreshState();
|
||||
}
|
||||
yield this.refreshAnimations();
|
||||
}),
|
||||
/**
|
||||
* Reset the startTime of all current animations shown in the timeline and
|
||||
* pause them.
|
||||
*/
|
||||
rewindTimeline: function() {
|
||||
AnimationsController.setCurrentTimeAll(0, true)
|
||||
.then(() => this.refreshAnimationsStateAndUI())
|
||||
.catch(e => console.error(e));
|
||||
},
|
||||
|
||||
onTabNavigated: function() {
|
||||
this.toggleAllButtonEl.classList.remove("paused");
|
||||
|
@ -180,7 +192,23 @@ var AnimationsPanel = {
|
|||
}
|
||||
},
|
||||
|
||||
refreshAnimations: Task.async(function*() {
|
||||
/**
|
||||
* Make sure all known animations have their states up to date (which is
|
||||
* useful after the playState or currentTime has been changed and in case the
|
||||
* animations aren't auto-refreshing), and then refresh the UI.
|
||||
*/
|
||||
refreshAnimationsStateAndUI: Task.async(function*() {
|
||||
for (let player of AnimationsController.animationPlayers) {
|
||||
yield player.refreshState();
|
||||
}
|
||||
yield this.refreshAnimationsUI();
|
||||
}),
|
||||
|
||||
/**
|
||||
* Refresh the list of animations UI. This will empty the panel and re-render
|
||||
* the various components again.
|
||||
*/
|
||||
refreshAnimationsUI: Task.async(function*() {
|
||||
let done = gInspector.updating("animationspanel");
|
||||
|
||||
// Empty the whole panel first.
|
||||
|
|
|
@ -650,7 +650,9 @@ AnimationsTimeline.prototype = {
|
|||
this.scrubberEl.style.display = "none";
|
||||
} else {
|
||||
this.scrubberEl.style.display = "block";
|
||||
this.startAnimatingScrubber(documentCurrentTime);
|
||||
this.startAnimatingScrubber(this.wasRewound()
|
||||
? TimeScale.minStartTime
|
||||
: documentCurrentTime);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -658,6 +660,11 @@ AnimationsTimeline.prototype = {
|
|||
return this.animations.some(({state}) => state.playState === "running");
|
||||
},
|
||||
|
||||
wasRewound: function() {
|
||||
return !this.isAtLeastOneAnimationPlaying() &&
|
||||
this.animations.every(({state}) => state.currentTime === 0);
|
||||
},
|
||||
|
||||
startAnimatingScrubber: function(time) {
|
||||
let x = TimeScale.startTimeToDistance(time, this.timeHeaderEl.offsetWidth);
|
||||
this.scrubberEl.style.left = x + "px";
|
||||
|
|
|
@ -26,6 +26,7 @@ support-files =
|
|||
[browser_animation_target_highlighter_lock.js]
|
||||
[browser_animation_timeline_header.js]
|
||||
[browser_animation_timeline_pause_button.js]
|
||||
[browser_animation_timeline_rewind_button.js]
|
||||
[browser_animation_timeline_scrubber_exists.js]
|
||||
[browser_animation_timeline_scrubber_movable.js]
|
||||
[browser_animation_timeline_scrubber_moves.js]
|
||||
|
|
|
@ -20,48 +20,16 @@ add_task(function*() {
|
|||
"The play/pause button is in its playing state");
|
||||
|
||||
info("Click on the button to pause all timeline animations");
|
||||
yield clickPlayPauseButton(panel);
|
||||
yield clickTimelinePlayPauseButton(panel);
|
||||
|
||||
ok(btn.classList.contains("paused"),
|
||||
"The play/pause button is in its paused state");
|
||||
yield checkIfScrubberMoving(panel, false);
|
||||
yield assertScrubberMoving(panel, false);
|
||||
|
||||
info("Click again on the button to play all timeline animations");
|
||||
yield clickPlayPauseButton(panel);
|
||||
yield clickTimelinePlayPauseButton(panel);
|
||||
|
||||
ok(!btn.classList.contains("paused"),
|
||||
"The play/pause button is in its playing state again");
|
||||
yield checkIfScrubberMoving(panel, true);
|
||||
yield assertScrubberMoving(panel, true);
|
||||
});
|
||||
|
||||
function* clickPlayPauseButton(panel) {
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
|
||||
let btn = panel.playTimelineButtonEl;
|
||||
let win = btn.ownerDocument.defaultView;
|
||||
EventUtils.sendMouseEvent({type: "click"}, btn, win);
|
||||
|
||||
yield onUiUpdated;
|
||||
yield waitForAllAnimationTargets(panel);
|
||||
}
|
||||
|
||||
function* checkIfScrubberMoving(panel, isMoving) {
|
||||
let timeline = panel.animationsTimelineComponent;
|
||||
let scrubberEl = timeline.scrubberEl;
|
||||
|
||||
if (isMoving) {
|
||||
// If we expect the scrubber to move, just wait for a couple of
|
||||
// timeline-data-changed events and compare times.
|
||||
let {time: time1} = yield timeline.once("timeline-data-changed");
|
||||
let {time: time2} = yield timeline.once("timeline-data-changed");
|
||||
ok(time2 > time1, "The scrubber is moving");
|
||||
} else {
|
||||
// If instead we expect the scrubber to remain at its position, just wait
|
||||
// for some time. A relatively long timeout is used because the test page
|
||||
// has long running animations, so the scrubber doesn't move that quickly.
|
||||
let startOffset = scrubberEl.offsetLeft;
|
||||
yield new Promise(r => setTimeout(r, 2000));
|
||||
let endOffset = scrubberEl.offsetLeft;
|
||||
is(startOffset, endOffset, "The scrubber is not moving");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* 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";
|
||||
|
||||
// Check that the timeline toolbar contains a rewind button and that it can be
|
||||
// clicked. Check that when it is, the current animations displayed in the
|
||||
// timeline get their playstates changed to paused, and their currentTimes
|
||||
// reset to 0, and that the scrubber stops moving and is positioned to the
|
||||
// start.
|
||||
|
||||
add_task(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||
|
||||
let {panel, controller} = yield openAnimationInspector();
|
||||
let btn = panel.rewindTimelineButtonEl;
|
||||
|
||||
ok(btn, "The rewind button exists");
|
||||
|
||||
info("Click on the button to rewind all timeline animations");
|
||||
yield clickTimelineRewindButton(panel);
|
||||
|
||||
info("Check that the scrubber has stopped moving");
|
||||
yield assertScrubberMoving(panel, false);
|
||||
|
||||
ok(controller.animationPlayers.every(({state}) => state.currentTime === 0),
|
||||
"All animations' currentTimes have been set to 0");
|
||||
ok(controller.animationPlayers.every(({state}) => state.playState === "paused"),
|
||||
"All animations have been paused");
|
||||
|
||||
info("Play the animations again");
|
||||
yield clickTimelinePlayPauseButton(panel);
|
||||
|
||||
info("And pause them after a short while");
|
||||
yield new Promise(r => setTimeout(r, 200));
|
||||
|
||||
info("Check that rewinding when animations are paused works too");
|
||||
yield clickTimelineRewindButton(panel);
|
||||
|
||||
info("Check that the scrubber has stopped moving");
|
||||
yield assertScrubberMoving(panel, false);
|
||||
|
||||
ok(controller.animationPlayers.every(({state}) => state.currentTime === 0),
|
||||
"All animations' currentTimes have been set to 0");
|
||||
ok(controller.animationPlayers.every(({state}) => state.playState === "paused"),
|
||||
"All animations have been paused");
|
||||
});
|
|
@ -449,3 +449,50 @@ var waitForAllAnimationTargets = Task.async(function*(panel) {
|
|||
}));
|
||||
return targets;
|
||||
});
|
||||
|
||||
/**
|
||||
* Check the scrubber element in the timeline is moving.
|
||||
* @param {AnimationPanel} panel
|
||||
* @param {Boolean} isMoving
|
||||
*/
|
||||
function* assertScrubberMoving(panel, isMoving) {
|
||||
let timeline = panel.animationsTimelineComponent;
|
||||
let scrubberEl = timeline.scrubberEl;
|
||||
|
||||
if (isMoving) {
|
||||
// If we expect the scrubber to move, just wait for a couple of
|
||||
// timeline-data-changed events and compare times.
|
||||
let {time: time1} = yield timeline.once("timeline-data-changed");
|
||||
let {time: time2} = yield timeline.once("timeline-data-changed");
|
||||
ok(time2 > time1, "The scrubber is moving");
|
||||
} else {
|
||||
// If instead we expect the scrubber to remain at its position, just wait
|
||||
// for some time and make sure timeline-data-changed isn't emitted.
|
||||
let hasMoved = false;
|
||||
timeline.once("timeline-data-changed", () => hasMoved = true);
|
||||
yield new Promise(r => setTimeout(r, 500));
|
||||
ok(!hasMoved, "The scrubber is not moving");
|
||||
}
|
||||
}
|
||||
|
||||
function* clickTimelinePlayPauseButton(panel) {
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
|
||||
let btn = panel.playTimelineButtonEl;
|
||||
let win = btn.ownerDocument.defaultView;
|
||||
EventUtils.sendMouseEvent({type: "click"}, btn, win);
|
||||
|
||||
yield onUiUpdated;
|
||||
yield waitForAllAnimationTargets(panel);
|
||||
}
|
||||
|
||||
function* clickTimelineRewindButton(panel) {
|
||||
let onUiUpdated = panel.once(panel.UI_UPDATED_EVENT);
|
||||
|
||||
let btn = panel.rewindTimelineButtonEl;
|
||||
let win = btn.ownerDocument.defaultView;
|
||||
EventUtils.sendMouseEvent({type: "click"}, btn, win);
|
||||
|
||||
yield onUiUpdated;
|
||||
yield waitForAllAnimationTargets(panel);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main",
|
|||
const DefaultTools = require("devtools/client/definitions").defaultTools;
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
const {JsonView} = require("devtools/client/jsonview/main");
|
||||
|
||||
const TABS_OPEN_PEAK_HISTOGRAM = "DEVTOOLS_TABS_OPEN_PEAK_LINEAR";
|
||||
const TABS_OPEN_AVG_HISTOGRAM = "DEVTOOLS_TABS_OPEN_AVERAGE_LINEAR";
|
||||
|
@ -51,6 +52,9 @@ this.DevTools = function DevTools() {
|
|||
this.destroy = this.destroy.bind(this);
|
||||
this._teardown = this._teardown.bind(this);
|
||||
|
||||
// JSON Viewer for 'application/json' documents.
|
||||
JsonView.initialize();
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
Services.obs.addObserver(this._teardown, "devtools-unloaded", false);
|
||||
|
@ -490,6 +494,8 @@ DevTools.prototype = {
|
|||
this.unregisterTool(key, true);
|
||||
}
|
||||
|
||||
JsonView.destroy();
|
||||
|
||||
this._pingTelemetry();
|
||||
this._telemetry = null;
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./reps/rep-utils");
|
||||
const { Headers } = createFactories(require("./headers"));
|
||||
const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
|
||||
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* This template represents the 'Headers' panel
|
||||
* s responsible for rendering its content.
|
||||
*/
|
||||
var HeadersPanel = React.createClass({
|
||||
displayName: "HeadersPanel",
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
data: {}
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var data = this.props.data;
|
||||
|
||||
return (
|
||||
DOM.div({className: "headersPanelBox"},
|
||||
HeadersToolbar({actions: this.props.actions}),
|
||||
DOM.div({className: "panelContent"},
|
||||
Headers({data: data})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This template is responsible for rendering a toolbar
|
||||
* within the 'Headers' panel.
|
||||
*/
|
||||
var HeadersToolbar = React.createFactory(React.createClass({
|
||||
displayName: "HeadersToolbar",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
Toolbar({},
|
||||
ToolbarButton({className: "btn copy", onClick: this.onCopy},
|
||||
Locale.$STR("jsonViewer.Copy")
|
||||
)
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
// Commands
|
||||
|
||||
onCopy: function(event) {
|
||||
this.props.actions.onCopyHeaders();
|
||||
},
|
||||
}));
|
||||
|
||||
// Exports from this module
|
||||
exports.HeadersPanel = HeadersPanel;
|
||||
});
|
|
@ -0,0 +1,100 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
|
||||
// Constants
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* This template is responsible for rendering basic layout
|
||||
* of the 'Headers' panel. It displays HTTP headers groups such as
|
||||
* received or response headers.
|
||||
*/
|
||||
var Headers = React.createClass({
|
||||
displayName: "Headers",
|
||||
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var data = this.props.data;
|
||||
|
||||
return (
|
||||
DOM.div({className: "netInfoHeadersTable"},
|
||||
DOM.div({className: "netHeadersGroup"},
|
||||
DOM.div({className: "netInfoHeadersGroup"},
|
||||
DOM.span({className: "netHeader twisty"},
|
||||
Locale.$STR("jsonViewer.responseHeaders")
|
||||
)
|
||||
),
|
||||
DOM.table({cellPadding: 0, cellSpacing: 0},
|
||||
HeaderList({headers: data.response})
|
||||
)
|
||||
),
|
||||
DOM.div({className: "netHeadersGroup"},
|
||||
DOM.div({className: "netInfoHeadersGroup"},
|
||||
DOM.span({className: "netHeader twisty"},
|
||||
Locale.$STR("jsonViewer.requestHeaders")
|
||||
)
|
||||
),
|
||||
DOM.table({cellPadding: 0, cellSpacing: 0},
|
||||
HeaderList({headers: data.request})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This template renders headers list,
|
||||
* name + value pairs.
|
||||
*/
|
||||
var HeaderList = React.createFactory(React.createClass({
|
||||
displayName: "HeaderList",
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
headers: []
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var headers = this.props.headers;
|
||||
|
||||
headers.sort(function(a, b) {
|
||||
return a.name > b.name ? 1 : -1;
|
||||
});
|
||||
|
||||
var rows = [];
|
||||
headers.forEach(header => {
|
||||
rows.push(
|
||||
DOM.tr({key: header.name},
|
||||
DOM.td({className: "netInfoParamName"},
|
||||
DOM.span({title: header.name}, header.name)
|
||||
),
|
||||
DOM.td({className: "netInfoParamValue"},
|
||||
DOM.code({}, header.value)
|
||||
)
|
||||
)
|
||||
)
|
||||
});
|
||||
|
||||
return (
|
||||
DOM.tbody({},
|
||||
rows
|
||||
)
|
||||
)
|
||||
}
|
||||
}));
|
||||
|
||||
// Exports from this module
|
||||
exports.Headers = Headers;
|
||||
});
|
|
@ -0,0 +1,108 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./reps/rep-utils");
|
||||
const { TreeView } = createFactories(require("./reps/tree-view"));
|
||||
const { SearchBox } = createFactories(require("./search-box"));
|
||||
const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* This template represents the 'JSON' panel. The panel is
|
||||
* responsible for rendering an expandable tree that allows simple
|
||||
* inspection of JSON structure.
|
||||
*/
|
||||
var JsonPanel = React.createClass({
|
||||
displayName: "JsonPanel",
|
||||
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
document.addEventListener("keypress", this.onKeyPress, true);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
document.removeEventListener("keypress", this.onKeyPress, true);
|
||||
},
|
||||
|
||||
onKeyPress: function(e) {
|
||||
// XXX shortcut for focusing the Filter field (see Bug 1178771).
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var content;
|
||||
var data = this.props.data;
|
||||
|
||||
try {
|
||||
if (typeof data == "object") {
|
||||
content = TreeView({
|
||||
data: this.props.data,
|
||||
mode: "tiny",
|
||||
searchFilter: this.props.searchFilter
|
||||
});
|
||||
} else {
|
||||
content = DOM.div({className: "jsonParseError"},
|
||||
data + ""
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
content = DOM.div({className: "jsonParseError"},
|
||||
err + ""
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
DOM.div({className: "jsonPanelBox"},
|
||||
JsonToolbar({actions: this.props.actions}),
|
||||
DOM.div({className: "panelContent"},
|
||||
content
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This template represents a toolbar within the 'JSON' panel.
|
||||
*/
|
||||
var JsonToolbar = React.createFactory(React.createClass({
|
||||
displayName: "JsonToolbar",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
Toolbar({},
|
||||
ToolbarButton({className: "btn save", onClick: this.onSave},
|
||||
Locale.$STR("jsonViewer.Save")
|
||||
),
|
||||
ToolbarButton({className: "btn copy", onClick: this.onCopy},
|
||||
Locale.$STR("jsonViewer.Copy")
|
||||
),
|
||||
SearchBox({
|
||||
actions: this.props.actions
|
||||
})
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
// Commands
|
||||
|
||||
onSave: function(event) {
|
||||
this.props.actions.onSaveJson();
|
||||
},
|
||||
|
||||
onCopy: function(event) {
|
||||
this.props.actions.onCopyJson();
|
||||
},
|
||||
}));
|
||||
|
||||
// Exports from this module
|
||||
exports.JsonPanel = JsonPanel;
|
||||
});
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./reps/rep-utils");
|
||||
const { JsonPanel } = createFactories(require("./json-panel"));
|
||||
const { TextPanel } = createFactories(require("./text-panel"));
|
||||
const { HeadersPanel } = createFactories(require("./headers-panel"));
|
||||
const { Tabs, TabPanel } = createFactories(require("./reps/tabs"));
|
||||
|
||||
/**
|
||||
* This object represents the root application template
|
||||
* responsible for rendering the basic tab layout.
|
||||
*/
|
||||
var MainTabbedArea = React.createClass({
|
||||
displayName: "MainTabbedArea",
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
json: {},
|
||||
headers: {},
|
||||
jsonText: this.props.jsonText,
|
||||
tabActive: this.props.tabActive
|
||||
};
|
||||
},
|
||||
|
||||
onTabChanged: function(index) {
|
||||
this.setState({tabActive: index});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
Tabs({tabActive: this.state.tabActive, onAfterChange: this.onTabChanged},
|
||||
TabPanel({className: "json", title: Locale.$STR("jsonViewer.tab.JSON")},
|
||||
JsonPanel({
|
||||
data: this.props.json,
|
||||
actions: this.props.actions,
|
||||
searchFilter: this.state.searchFilter
|
||||
})
|
||||
),
|
||||
TabPanel({className: "rawdata", title: Locale.$STR("jsonViewer.tab.RawData")},
|
||||
TextPanel({
|
||||
data: this.state.jsonText,
|
||||
actions: this.props.actions
|
||||
})
|
||||
),
|
||||
TabPanel({className: "headers", title: Locale.$STR("jsonViewer.tab.Headers")},
|
||||
HeadersPanel({
|
||||
data: this.props.headers,
|
||||
actions: this.props.actions,
|
||||
searchFilter: this.props.searchFilter
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
exports.MainTabbedArea = MainTabbedArea;
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'reps'
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'headers-panel.js',
|
||||
'headers.js',
|
||||
'json-panel.js',
|
||||
'main-tabbed-area.js',
|
||||
'search-box.js',
|
||||
'text-panel.js'
|
||||
)
|
|
@ -0,0 +1,189 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./rep-utils");
|
||||
const { Rep } = createFactories(require("./rep"));
|
||||
const { ObjectBox } = createFactories(require("./object-box"));
|
||||
const { Caption } = createFactories(require("./caption"));
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* Renders an array. The array is enclosed by left and right bracket
|
||||
* and the max number of rendered items depends on the current mode.
|
||||
*/
|
||||
var ArrayRep = React.createClass({
|
||||
displayName: "ArrayRep",
|
||||
|
||||
render: function() {
|
||||
var mode = this.props.mode || "short";
|
||||
var object = this.props.object;
|
||||
var hasTwisty = this.hasSpecialProperties(object);
|
||||
|
||||
var items;
|
||||
|
||||
if (mode == "tiny") {
|
||||
items = object.length;
|
||||
} else {
|
||||
var max = (mode == "short") ? 3 : 300;
|
||||
items = this.arrayIterator(object, max);
|
||||
}
|
||||
|
||||
return (
|
||||
ObjectBox({className: "array", onClick: this.onToggleProperties},
|
||||
DOM.a({className: "objectLink", onclick: this.onClickBracket},
|
||||
DOM.span({className: "arrayLeftBracket", role: "presentation"}, "[")
|
||||
),
|
||||
items,
|
||||
DOM.a({className: "objectLink", onclick: this.onClickBracket},
|
||||
DOM.span({className: "arrayRightBracket", role: "presentation"}, "]")
|
||||
),
|
||||
DOM.span({className: "arrayProperties", role: "group"})
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
getTitle: function(object, context) {
|
||||
return "[" + object.length + "]";
|
||||
},
|
||||
|
||||
arrayIterator: function(array, max) {
|
||||
var items = [];
|
||||
|
||||
for (var i=0; i<array.length && i<=max; i++) {
|
||||
try {
|
||||
var delim = (i == array.length-1 ? "" : ", ");
|
||||
var value = array[i];
|
||||
|
||||
if (value === array) {
|
||||
items.push(Reference({
|
||||
key: i,
|
||||
object: value,
|
||||
delim: delim
|
||||
}));
|
||||
} else {
|
||||
items.push(ItemRep({
|
||||
key: i,
|
||||
object: value,
|
||||
delim: delim
|
||||
}));
|
||||
}
|
||||
} catch (exc) {
|
||||
items.push(ItemRep({object: exc, delim: delim, key: i}));
|
||||
}
|
||||
}
|
||||
|
||||
if (array.length > max + 1) {
|
||||
items.pop();
|
||||
items.push(Caption({
|
||||
key: "more",
|
||||
object: Locale.$STR("jsonViewer.reps.more"),
|
||||
}));
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the passed object is an array with additional (custom)
|
||||
* properties, otherwise returns false. Custom properties should be
|
||||
* displayed in extra expandable section.
|
||||
*
|
||||
* Example array with a custom property.
|
||||
* let arr = [0, 1];
|
||||
* arr.myProp = "Hello";
|
||||
*
|
||||
* @param {Array} array The array object.
|
||||
*/
|
||||
hasSpecialProperties: function(array) {
|
||||
function isInteger(x) {
|
||||
var y = parseInt(x, 10);
|
||||
if (isNaN(y)) {
|
||||
return false;
|
||||
}
|
||||
return x === y.toString();
|
||||
}
|
||||
|
||||
var n = 0;
|
||||
var props = Object.getOwnPropertyNames(array);
|
||||
for (var i=0; i<props.length; i++) {
|
||||
var p = props[i];
|
||||
|
||||
// Valid indexes are skipped
|
||||
if (isInteger(p)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore standard 'length' property, anything else is custom.
|
||||
if (p != "length") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
// Event Handlers
|
||||
|
||||
onToggleProperties: function(event) {
|
||||
},
|
||||
|
||||
onClickBracket: function(event) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders array item. Individual values are separated by a comma.
|
||||
*/
|
||||
var ItemRep = React.createFactory(React.createClass({
|
||||
displayName: "ItemRep",
|
||||
|
||||
render: function(){
|
||||
var object = this.props.object;
|
||||
var delim = this.props.delim;
|
||||
return (
|
||||
DOM.span({},
|
||||
Rep({object: object}),
|
||||
delim
|
||||
)
|
||||
)
|
||||
}
|
||||
}));
|
||||
|
||||
/**
|
||||
* Renders cycle references in an array.
|
||||
*/
|
||||
var Reference = React.createFactory(React.createClass({
|
||||
displayName: "Reference",
|
||||
|
||||
render: function(){
|
||||
var tooltip = Locale.$STR("jsonView.reps.reference");
|
||||
return (
|
||||
span({title: tooltip},
|
||||
"[...]")
|
||||
)
|
||||
}
|
||||
}));
|
||||
|
||||
function supportsObject(object, type) {
|
||||
return Array.isArray(object) ||
|
||||
Object.prototype.toString.call(object) === "[object Arguments]";
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
exports.ArrayRep = {
|
||||
rep: ArrayRep,
|
||||
supportsObject: supportsObject
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* Renders a caption. This template is used by other components
|
||||
* that needs to distinguish between a simple text/value and a label.
|
||||
*/
|
||||
const Caption = React.createClass({
|
||||
displayName: "Caption",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
DOM.span({"className": "caption"}, this.props.object)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
exports.Caption = Caption;
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'array.js',
|
||||
'caption.js',
|
||||
'null.js',
|
||||
'number.js',
|
||||
'object-box.js',
|
||||
'object-link.js',
|
||||
'object.js',
|
||||
'rep-utils.js',
|
||||
'rep.js',
|
||||
'string.js',
|
||||
'tabs.js',
|
||||
'toolbar.js',
|
||||
'tree-view.js',
|
||||
'undefined.js',
|
||||
)
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./rep-utils");
|
||||
const { ObjectBox } = createFactories(require("./object-box"));
|
||||
|
||||
/**
|
||||
* Renders null value
|
||||
*/
|
||||
const Null = React.createClass({
|
||||
displayName: "NullRep",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
ObjectBox({className: "null"},
|
||||
"null"
|
||||
)
|
||||
)
|
||||
},
|
||||
});
|
||||
|
||||
function supportsObject(object, type) {
|
||||
if (object && object.type && object.type == "null") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (object == null);
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
|
||||
exports.Null = {
|
||||
rep: Null,
|
||||
supportsObject: supportsObject
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./rep-utils");
|
||||
const { ObjectBox } = createFactories(require("./object-box"));
|
||||
|
||||
/**
|
||||
* Renders a number
|
||||
*/
|
||||
const Number = React.createClass({
|
||||
displayName: "Number",
|
||||
|
||||
render: function() {
|
||||
var value = this.props.object;
|
||||
return (
|
||||
ObjectBox({className: "number"},
|
||||
this.stringify(value)
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
stringify: function(object) {
|
||||
return (Object.is(object, -0) ? "-0" : String(object));
|
||||
},
|
||||
});
|
||||
|
||||
function supportsObject(object, type) {
|
||||
return type == "boolean" || type == "number";
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
|
||||
exports.Number = {
|
||||
rep: Number,
|
||||
supportsObject: supportsObject
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* Renders a box for given object.
|
||||
*/
|
||||
const ObjectBox = React.createClass({
|
||||
displayName: "ObjectBox",
|
||||
|
||||
render: function() {
|
||||
var className = this.props.className;
|
||||
var boxClassName = className ? " objectBox-" + className : "";
|
||||
|
||||
return (
|
||||
DOM.span({className: "objectBox" + boxClassName, role: "presentation"},
|
||||
this.props.children
|
||||
)
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
exports.ObjectBox = ObjectBox;
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* Renders a link for given object.
|
||||
*/
|
||||
const ObjectLink = React.createClass({
|
||||
displayName: "ObjectLink",
|
||||
|
||||
render: function() {
|
||||
var className = this.props.className;
|
||||
var objectClassName = className ? " objectLink-" + className : "";
|
||||
var linkClassName = "objectLink" + objectClassName + " a11yFocus";
|
||||
|
||||
return (
|
||||
DOM.a({className: linkClassName, _repObject: this.props.object},
|
||||
this.props.children
|
||||
)
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
exports.ObjectLink = ObjectLink;
|
||||
});
|
|
@ -0,0 +1,178 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./rep-utils");
|
||||
const { ObjectBox } = createFactories(require("./object-box"));
|
||||
const { Caption } = createFactories(require("./caption"));
|
||||
|
||||
// Shortcuts
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* Renders an object. An object is represented by a list of its
|
||||
* properties enclosed in curly brackets.
|
||||
*/
|
||||
const Obj = React.createClass({
|
||||
displayName: "Obj",
|
||||
|
||||
render: function() {
|
||||
var object = this.props.object;
|
||||
var props = this.shortPropIterator(object);
|
||||
|
||||
return (
|
||||
ObjectBox({className: "object"},
|
||||
DOM.span({className: "objectTitle"}, this.getTitle(object)),
|
||||
DOM.span({className: "objectLeftBrace", role: "presentation"}, "{"),
|
||||
props,
|
||||
DOM.span({className: "objectRightBrace"}, "}")
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
getTitle: function() {
|
||||
return ""; // Could also be "Object";
|
||||
},
|
||||
|
||||
longPropIterator: function (object) {
|
||||
try {
|
||||
return this.propIterator(object, 100);
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
},
|
||||
|
||||
shortPropIterator: function (object) {
|
||||
try {
|
||||
return this.propIterator(object, /*could be a pref*/ 3);
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
},
|
||||
|
||||
propIterator: function(object, max) {
|
||||
function isInterestingProp(t, value) {
|
||||
return (t == "boolean" || t == "number" || (t == "string" && value) ||
|
||||
(t == "object" && value && value.toString));
|
||||
}
|
||||
|
||||
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=945377
|
||||
if (Object.prototype.toString.call(object) === "[object Generator]") {
|
||||
object = Object.getPrototypeOf(object);
|
||||
}
|
||||
|
||||
// Object members with non-empty values are preferred since it gives the
|
||||
// user a better overview of the object.
|
||||
var props = [];
|
||||
this.getProps(props, object, max, isInterestingProp);
|
||||
|
||||
if (props.length <= max) {
|
||||
// There are not enough props yet (or at least, not enough props to
|
||||
// be able to know whether we should print "more..." or not).
|
||||
// Let's display also empty members and functions.
|
||||
this.getProps(props, object, max, function(t, value) {
|
||||
return !isInterestingProp(t, value);
|
||||
});
|
||||
}
|
||||
|
||||
if (props.length > max) {
|
||||
props.pop();
|
||||
props.push(Caption({
|
||||
key: "more",
|
||||
object: Locale.$STR("jsonViewer.reps.more"),
|
||||
}));
|
||||
}
|
||||
else if (props.length > 0) {
|
||||
// Remove the last comma.
|
||||
props[props.length-1] = React.cloneElement(
|
||||
props[props.length-1], { delim: "" });
|
||||
}
|
||||
|
||||
return props;
|
||||
},
|
||||
|
||||
getProps: function (props, object, max, filter) {
|
||||
max = max || 3;
|
||||
if (!object) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var len = 0;
|
||||
var mode = this.props.mode;
|
||||
|
||||
try {
|
||||
for (var name in object) {
|
||||
if (props.length > max) {
|
||||
return;
|
||||
}
|
||||
|
||||
var value;
|
||||
try {
|
||||
value = object[name];
|
||||
}
|
||||
catch (exc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var t = typeof(value);
|
||||
if (filter(t, value)) {
|
||||
props.push(PropRep({
|
||||
key: name,
|
||||
mode: "short",
|
||||
name: name,
|
||||
object: value,
|
||||
equal: ": ",
|
||||
delim: ", ",
|
||||
mode: mode,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (exc) {
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders object property, name-value pair.
|
||||
*/
|
||||
var PropRep = React.createFactory(React.createClass({
|
||||
displayName: "PropRep",
|
||||
|
||||
render: function(){
|
||||
var { Rep } = createFactories(require("./rep"));
|
||||
var object = this.props.object;
|
||||
var mode = this.props.mode;
|
||||
return (
|
||||
DOM.span({},
|
||||
DOM.span({"className": "nodeName"}, this.props.name),
|
||||
DOM.span({"className": "objectEqual", role: "presentation"}, this.props.equal),
|
||||
Rep({object: object, mode: mode}),
|
||||
DOM.span({"className": "objectComma", role: "presentation"}, this.props.delim)
|
||||
)
|
||||
);
|
||||
}
|
||||
}));
|
||||
|
||||
function supportsObject(object, type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
|
||||
exports.Obj = {
|
||||
rep: Obj,
|
||||
supportsObject: supportsObject
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
|
||||
/**
|
||||
* Create React factories for given arguments.
|
||||
* Example:
|
||||
* const { Rep } = createFactories(require("./rep"));
|
||||
*/
|
||||
function createFactories(args) {
|
||||
var result = {};
|
||||
for (var p in args) {
|
||||
result[p] = React.createFactory(args[p]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
exports.createFactories = createFactories;
|
||||
});
|
|
@ -0,0 +1,87 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
|
||||
// Load all existing rep templates
|
||||
const { Undefined } = require("./undefined");
|
||||
const { Null } = require("./null");
|
||||
const { StringRep } = require("./string");
|
||||
const { Number } = require("./number");
|
||||
const { ArrayRep } = require("./array");
|
||||
const { Obj } = require("./object");
|
||||
|
||||
// List of all registered template.
|
||||
// XXX there should be a way for extensions to register a new
|
||||
// or modify an existing rep.
|
||||
var reps = [Undefined, Null, StringRep, Number, ArrayRep, Obj];
|
||||
var defaultRep;
|
||||
|
||||
/**
|
||||
* Generic rep that is using for rendering native JS types or an object.
|
||||
* The right template used for rendering is picked automatically according
|
||||
* to the current value type. The value must be passed is as 'object'
|
||||
* property.
|
||||
*/
|
||||
const Rep = React.createClass({
|
||||
displayName: "Rep",
|
||||
|
||||
render: function() {
|
||||
var rep = getRep(this.props.object);
|
||||
return rep(this.props);
|
||||
},
|
||||
});
|
||||
|
||||
// Helpers
|
||||
|
||||
/**
|
||||
* Return a rep object that is responsible for rendering given
|
||||
* object.
|
||||
*
|
||||
* @param object {Object} Object to be rendered in the UI. This
|
||||
* can be generic JS object as well as a grip (handle to a remote
|
||||
* debuggee object).
|
||||
*/
|
||||
function getRep(object) {
|
||||
var type = typeof(object);
|
||||
if (type == "object" && object instanceof String) {
|
||||
type = "string";
|
||||
}
|
||||
|
||||
if (isGrip(object)) {
|
||||
type = object.class;
|
||||
}
|
||||
|
||||
for (var i=0; i<reps.length; i++) {
|
||||
var rep = reps[i];
|
||||
try {
|
||||
// supportsObject could return weight (not only true/false
|
||||
// but a number), which would allow to priorities templates and
|
||||
// support better extensibility.
|
||||
if (rep.supportsObject(object, type)) {
|
||||
return React.createFactory(rep.rep);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.error("reps.getRep; EXCEPTION ", err, err);
|
||||
}
|
||||
}
|
||||
|
||||
return React.createFactory(defaultRep.rep);
|
||||
}
|
||||
|
||||
function isGrip(object) {
|
||||
return object && object.actor;
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
exports.Rep = Rep;
|
||||
});
|
|
@ -0,0 +1,102 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./rep-utils");
|
||||
const { ObjectBox } = createFactories(require("./object-box"));
|
||||
|
||||
/**
|
||||
* Renders a string. String value is enclosed within quotes.
|
||||
*/
|
||||
const StringRep = React.createClass({
|
||||
displayName: "StringRep",
|
||||
|
||||
render: function() {
|
||||
var text = this.props.object;
|
||||
var member = this.props.member;
|
||||
if (member && member.open) {
|
||||
return (
|
||||
ObjectBox({className: "string"},
|
||||
"\"" + text + "\""
|
||||
)
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
ObjectBox({className: "string"},
|
||||
"\"" + cropMultipleLines(text) + "\""
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Helpers
|
||||
|
||||
function escapeNewLines(value) {
|
||||
return value.replace(/\r/gm, "\\r").replace(/\n/gm, "\\n");
|
||||
};
|
||||
|
||||
function cropMultipleLines(text, limit) {
|
||||
return escapeNewLines(cropString(text, limit));
|
||||
};
|
||||
|
||||
function cropString(text, limit, alternativeText) {
|
||||
if (!alternativeText) {
|
||||
alternativeText = "...";
|
||||
}
|
||||
|
||||
// Make sure it's a string.
|
||||
text = text + "";
|
||||
|
||||
// Use default limit if necessary.
|
||||
if (!limit) {
|
||||
limit = 50;
|
||||
}
|
||||
|
||||
// Crop the string only if a limit is actually specified.
|
||||
if (limit <= 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
// Set the limit at least to the length of the alternative text
|
||||
// plus one character of the original text.
|
||||
if (limit <= alternativeText.length) {
|
||||
limit = alternativeText.length + 1;
|
||||
}
|
||||
|
||||
var halfLimit = (limit - alternativeText.length) / 2;
|
||||
|
||||
if (text.length > limit) {
|
||||
return text.substr(0, Math.ceil(halfLimit)) + alternativeText +
|
||||
text.substr(text.length - Math.floor(halfLimit));
|
||||
}
|
||||
|
||||
return text;
|
||||
};
|
||||
|
||||
function isCropped(value) {
|
||||
var cropLength = 50;
|
||||
return typeof(value) == "string" && value.length > cropLength;
|
||||
}
|
||||
|
||||
function supportsObject(object, type) {
|
||||
return (type == "string");
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
|
||||
exports.StringRep = {
|
||||
rep: StringRep,
|
||||
supportsObject: supportsObject,
|
||||
isCropped: isCropped
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,192 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* Renders simple 'tab' widget.
|
||||
*
|
||||
* Based on ReactSimpleTabs component
|
||||
* https://github.com/pedronauck/react-simpletabs
|
||||
*
|
||||
* Component markup (+CSS) example:
|
||||
*
|
||||
* <div class='tabs'>
|
||||
* <nav class='tabs-navigation'>
|
||||
* <ul class='tabs-menu'>
|
||||
* <li class='tabs-menu-item is-active'>Tab #1</li>
|
||||
* <li class='tabs-menu-item'>Tab #2</li>
|
||||
* </ul>
|
||||
* </nav>
|
||||
* <article class='tab-panel'>
|
||||
* The content of active panel here
|
||||
* </article>
|
||||
* <div>
|
||||
*/
|
||||
var Tabs = React.createClass({
|
||||
displayName: "Tabs",
|
||||
|
||||
propTypes: {
|
||||
className: React.PropTypes.oneOfType([
|
||||
React.PropTypes.array,
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.object
|
||||
]),
|
||||
tabActive: React.PropTypes.number,
|
||||
onMount: React.PropTypes.func,
|
||||
onBeforeChange: React.PropTypes.func,
|
||||
onAfterChange: React.PropTypes.func,
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.array,
|
||||
React.PropTypes.element
|
||||
]).isRequired
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
tabActive: 1
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
tabActive: this.props.tabActive
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
var index = this.state.tabActive;
|
||||
if (this.props.onMount) {
|
||||
this.props.onMount(index);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps){
|
||||
if (newProps.tabActive) {
|
||||
this.setState({tabActive: newProps.tabActive})
|
||||
}
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var classNames = ["tabs", this.props.className].join(" ");
|
||||
|
||||
return (
|
||||
DOM.div({className: classNames},
|
||||
this.getMenuItems(),
|
||||
this.getSelectedPanel()
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
setActive: function(index, e) {
|
||||
var onAfterChange = this.props.onAfterChange;
|
||||
var onBeforeChange = this.props.onBeforeChange;
|
||||
|
||||
if (onBeforeChange) {
|
||||
var cancel = onBeforeChange(index);
|
||||
if (cancel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var newState = {
|
||||
tabActive: index
|
||||
};
|
||||
|
||||
this.setState(newState, () => {
|
||||
if (onAfterChange) {
|
||||
onAfterChange(index);
|
||||
}
|
||||
});
|
||||
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
getMenuItems: function () {
|
||||
if (!this.props.children) {
|
||||
throw new Error("Tabs must contain at least one Panel");
|
||||
}
|
||||
|
||||
if (!Array.isArray(this.props.children)) {
|
||||
this.props.children = [this.props.children];
|
||||
}
|
||||
|
||||
var menuItems = this.props.children
|
||||
.map(function(panel) {
|
||||
return typeof panel === "function" ? panel() : panel;
|
||||
}).filter(function(panel) {
|
||||
return panel;
|
||||
}).map(function(panel, index) {
|
||||
var ref = ("tab-menu-" + (index + 1));
|
||||
var title = panel.props.title;
|
||||
var tabClassName = panel.props.className;
|
||||
|
||||
var classes = [
|
||||
"tabs-menu-item",
|
||||
tabClassName,
|
||||
this.state.tabActive === (index + 1) && "is-active"
|
||||
].join(" ");
|
||||
|
||||
return (
|
||||
DOM.li({ref: ref, key: index, className: classes},
|
||||
DOM.a({href: "#", onClick: this.setActive.bind(this, index + 1)},
|
||||
title
|
||||
)
|
||||
)
|
||||
);
|
||||
}.bind(this));
|
||||
|
||||
return (
|
||||
DOM.nav({className: "tabs-navigation"},
|
||||
DOM.ul({className: "tabs-menu"},
|
||||
menuItems
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
getSelectedPanel: function () {
|
||||
var index = this.state.tabActive - 1;
|
||||
var panel = this.props.children[index];
|
||||
|
||||
return (
|
||||
DOM.article({ref: "tab-panel", className: "tab-panel"},
|
||||
panel
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders simple tab 'panel'.
|
||||
*/
|
||||
var Panel = React.createClass({
|
||||
displayName: "Panel",
|
||||
|
||||
propTypes: {
|
||||
title: React.PropTypes.string.isRequired,
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.array,
|
||||
React.PropTypes.element
|
||||
]).isRequired
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return DOM.div({},
|
||||
this.props.children
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
exports.TabPanel = Panel;
|
||||
exports.Tabs = Tabs;
|
||||
});
|
|
@ -0,0 +1,51 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* Renders a simple toolbar.
|
||||
*/
|
||||
var Toolbar = React.createClass({
|
||||
displayName: "Toolbar",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
DOM.div({className: "toolbar"},
|
||||
this.props.children
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders a simple toolbar button.
|
||||
*/
|
||||
var ToolbarButton = React.createClass({
|
||||
displayName: "ToolbarButton",
|
||||
|
||||
propTypes: {
|
||||
active: React.PropTypes.bool,
|
||||
disabled: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var props = Object.assign({className: "btn"}, this.props);
|
||||
return (
|
||||
DOM.button(props, this.props.children)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
exports.Toolbar = Toolbar;
|
||||
exports.ToolbarButton = ToolbarButton;
|
||||
});
|
|
@ -0,0 +1,261 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./rep-utils");
|
||||
const { Rep } = createFactories(require("./rep"));
|
||||
const { StringRep } = require("./string");
|
||||
const DOM = React.DOM;
|
||||
|
||||
var uid = 0;
|
||||
|
||||
/**
|
||||
* Renders a tree view with expandable/collapsible items.
|
||||
*/
|
||||
var TreeView = React.createClass({
|
||||
displayName: "TreeView",
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
data: {},
|
||||
searchFilter: null
|
||||
};
|
||||
},
|
||||
|
||||
// Rendering
|
||||
|
||||
render: function() {
|
||||
var mode = this.props.mode;
|
||||
var root = this.state.data;
|
||||
|
||||
var children = [];
|
||||
|
||||
if (Array.isArray(root)) {
|
||||
for (var i=0; i<root.length; i++) {
|
||||
var child = root[i];
|
||||
children.push(TreeNode({
|
||||
key: child.key,
|
||||
data: child,
|
||||
mode: mode,
|
||||
searchFilter: this.state.searchFilter || this.props.searchFilter
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
children.push(React.addons.createFragment(root));
|
||||
}
|
||||
|
||||
return (
|
||||
DOM.div({className: "domTable", cellPadding: 0, cellSpacing: 0,
|
||||
onClick: this.onClick},
|
||||
children
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
// Data
|
||||
|
||||
componentDidMount: function() {
|
||||
var members = initMembers(this.props.data, 0);
|
||||
this.setState({data: members, searchFilter: this.props.searchFilter});
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
var updatedState = {
|
||||
searchFilter: nextProps.searchFilter
|
||||
};
|
||||
|
||||
if (this.props.data !== nextProps.data) {
|
||||
updatedState.data = initMembers(nextProps.data, 0);
|
||||
}
|
||||
|
||||
this.setState(updatedState);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Represents a node within the tree.
|
||||
*/
|
||||
var TreeNode = React.createFactory(React.createClass({
|
||||
displayName: "TreeNode",
|
||||
|
||||
getInitialState: function() {
|
||||
return { data: {}, searchFilter: null };
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.setState({data: this.props.data});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var member = this.state.data;
|
||||
var mode = this.props.mode;
|
||||
|
||||
var classNames = ["memberRow"];
|
||||
classNames.push(member.type + "Row");
|
||||
|
||||
if (member.hasChildren) {
|
||||
classNames.push("hasChildren");
|
||||
}
|
||||
|
||||
if (member.open) {
|
||||
classNames.push("opened");
|
||||
}
|
||||
|
||||
if (!member.children) {
|
||||
// Cropped strings are expandable, but they don't have children.
|
||||
var isString = typeof(member.value) == "string";
|
||||
if (member.hasChildren && !isString) {
|
||||
member.children = initMembers(member.value);
|
||||
} else {
|
||||
member.children = [];
|
||||
}
|
||||
}
|
||||
|
||||
var children = [];
|
||||
if (member.open && member.children.length) {
|
||||
for (var i in member.children) {
|
||||
var child = member.children[i];
|
||||
children.push(TreeNode({
|
||||
key: child.key,
|
||||
data: child,
|
||||
mode: mode,
|
||||
searchFilter: this.state.searchFilter || this.props.searchFilter
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
var filter = this.props.searchFilter || "";
|
||||
var name = member.name || "";
|
||||
var value = member.value || "";
|
||||
|
||||
// Filtering is case-insensitive
|
||||
filter = filter.toLowerCase();
|
||||
name = name.toLowerCase();
|
||||
|
||||
if (filter && (name.indexOf(filter) < 0)) {
|
||||
// Cache the stringify result, so the filtering is fast
|
||||
// the next time.
|
||||
if (!member.valueString) {
|
||||
member.valueString = JSON.stringify(value).toLowerCase();
|
||||
}
|
||||
|
||||
if (member.valueString && member.valueString.indexOf(filter) < 0) {
|
||||
classNames.push("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
DOM.div({className: classNames.join(" "), onClick: this.onClick},
|
||||
DOM.span({className: "memberLabelCell"},
|
||||
DOM.span({className: "memberLabel " + member.type + "Label"},
|
||||
member.name)
|
||||
),
|
||||
DOM.span({className: "memberValueCell"},
|
||||
DOM.span({},
|
||||
Rep({
|
||||
object: member.value,
|
||||
mode: this.props.mode,
|
||||
member: member
|
||||
})
|
||||
)
|
||||
),
|
||||
DOM.div({className: "memberChildren"},
|
||||
children
|
||||
)
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
onClick: function(e) {
|
||||
var member = this.state.data;
|
||||
member.open = !member.open;
|
||||
|
||||
this.setState({data: member});
|
||||
|
||||
e.stopPropagation();
|
||||
},
|
||||
}));
|
||||
|
||||
// Helpers
|
||||
|
||||
function initMembers(parent) {
|
||||
var members = getMembers(parent);
|
||||
return members;
|
||||
}
|
||||
|
||||
function getMembers(object) {
|
||||
var members = [];
|
||||
getObjectProperties(object, function(prop, value) {
|
||||
var valueType = typeof(value);
|
||||
var hasChildren = (valueType === "object" && hasProperties(value));
|
||||
|
||||
// Cropped strings are expandable, so the user can see the
|
||||
// entire original value.
|
||||
if (StringRep.isCropped(value)) {
|
||||
hasChildren = true;
|
||||
}
|
||||
|
||||
var type = getType(value);
|
||||
var member = createMember(type, prop, value, hasChildren);
|
||||
members.push(member);
|
||||
});
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
function createMember(type, name, value, hasChildren) {
|
||||
var member = {
|
||||
name: name,
|
||||
type: type,
|
||||
rowClass: "memberRow-" + type,
|
||||
open: "",
|
||||
hasChildren: hasChildren,
|
||||
value: value,
|
||||
open: false,
|
||||
key: uid++
|
||||
};
|
||||
|
||||
return member;
|
||||
}
|
||||
|
||||
function getObjectProperties(obj, callback) {
|
||||
for (var p in obj) {
|
||||
try {
|
||||
callback.call(this, p, obj[p]);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hasProperties(obj) {
|
||||
if (typeof(obj) == "string") {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
for (var name in obj) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (exc) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getType(object) {
|
||||
// A type provider (or a decorator) should be used here.
|
||||
return "dom";
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
exports.TreeView = TreeView;
|
||||
});
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
// Dependencies
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./rep-utils");
|
||||
const { ObjectBox } = createFactories(require("./object-box"));
|
||||
|
||||
/**
|
||||
* Renders undefined value
|
||||
*/
|
||||
const Undefined = React.createClass({
|
||||
displayName: "UndefinedRep",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
ObjectBox({className: "undefined"},
|
||||
"undefined"
|
||||
)
|
||||
)
|
||||
},
|
||||
});
|
||||
|
||||
function supportsObject(object, type) {
|
||||
if (object && object.type && object.type == "undefined") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (type == "undefined");
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
|
||||
exports.Undefined = {
|
||||
rep: Undefined,
|
||||
supportsObject: supportsObject
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
|
||||
const DOM = React.DOM;
|
||||
|
||||
// For smooth incremental searching (in case the user is typing quickly).
|
||||
const searchDelay = 250;
|
||||
|
||||
/**
|
||||
* This object represents a search box located at the
|
||||
* top right corner of the application.
|
||||
*/
|
||||
var SearchBox = React.createClass({
|
||||
displayName: "SearchBox",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
DOM.input({className: "searchBox",
|
||||
placeholder: Locale.$STR("jsonViewer.filterJSON"),
|
||||
onChange: this.onSearch})
|
||||
)
|
||||
},
|
||||
|
||||
onSearch: function(event) {
|
||||
var searchBox = event.target;
|
||||
var win = searchBox.ownerDocument.defaultView;
|
||||
|
||||
if (this.searchTimeout) {
|
||||
win.clearTimeout(this.searchTimeout);
|
||||
}
|
||||
|
||||
var callback = this.doSearch.bind(this, searchBox);
|
||||
this.searchTimeout = win.setTimeout(callback, searchDelay);
|
||||
},
|
||||
|
||||
doSearch: function(searchBox) {
|
||||
this.props.actions.onSearch(searchBox.value);
|
||||
}
|
||||
});
|
||||
|
||||
// Exports from this module
|
||||
exports.SearchBox = SearchBox;
|
||||
});
|
|
@ -0,0 +1,79 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
const React = require("react");
|
||||
const { createFactories } = require("./reps/rep-utils");
|
||||
const { Toolbar, ToolbarButton } = createFactories(require("./reps/toolbar"));
|
||||
const DOM = React.DOM;
|
||||
|
||||
/**
|
||||
* This template represents the 'Raw Data' panel displaying
|
||||
* JSON as a text received from the server.
|
||||
*/
|
||||
var TextPanel = React.createClass({
|
||||
displayName: "TextPanel",
|
||||
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
DOM.div({className: "textPanelBox"},
|
||||
TextToolbar({actions: this.props.actions}),
|
||||
DOM.div({className: "panelContent"},
|
||||
DOM.pre({className: "data"},
|
||||
this.props.data
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* This object represents a toolbar displayed within the
|
||||
* 'Raw Data' panel.
|
||||
*/
|
||||
var TextToolbar = React.createFactory(React.createClass({
|
||||
displayName: "TextToolbar",
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
Toolbar({},
|
||||
ToolbarButton({className: "btn prettyprint",onClick: this.onPrettify},
|
||||
Locale.$STR("jsonViewer.PrettyPrint")
|
||||
),
|
||||
ToolbarButton({className: "btn save", onClick: this.onSave},
|
||||
Locale.$STR("jsonViewer.Save")
|
||||
),
|
||||
ToolbarButton({className: "btn copy", onClick: this.onCopy},
|
||||
Locale.$STR("jsonViewer.Copy")
|
||||
)
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
// Commands
|
||||
|
||||
onPrettify: function(event) {
|
||||
this.props.actions.onPrettify();
|
||||
},
|
||||
|
||||
onSave: function(event) {
|
||||
this.props.actions.onSaveJson();
|
||||
},
|
||||
|
||||
onCopy: function(event) {
|
||||
this.props.actions.onCopyJson();
|
||||
},
|
||||
}));
|
||||
|
||||
// Exports from this module
|
||||
exports.TextPanel = TextPanel;
|
||||
});
|
|
@ -0,0 +1,309 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Cu, Cc, Ci, components} = require("chrome");
|
||||
const {Class} = require("sdk/core/heritage");
|
||||
const {Unknown} = require("sdk/platform/xpcom");
|
||||
const xpcom = require("sdk/platform/xpcom");
|
||||
const Events = require("sdk/dom/events");
|
||||
const Clipboard = require("sdk/clipboard");
|
||||
|
||||
loader.lazyRequireGetter(this, "NetworkHelper",
|
||||
"devtools/shared/webconsole/network-helper");
|
||||
loader.lazyRequireGetter(this, "JsonViewUtils",
|
||||
"devtools/client/jsonview/utils");
|
||||
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
const childProcessMessageManager =
|
||||
Cc["@mozilla.org/childprocessmessagemanager;1"].
|
||||
getService(Ci.nsISyncMessageSender);
|
||||
|
||||
// Amount of space that will be allocated for the stream's backing-store.
|
||||
// Must be power of 2. Used to copy the data stream in onStopRequest.
|
||||
const SEGMENT_SIZE = Math.pow(2, 17);
|
||||
|
||||
const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
|
||||
const CONTRACT_ID = "@mozilla.org/streamconv;1?from=" + JSON_VIEW_MIME_TYPE + "&to=*/*";
|
||||
const CLASS_ID = "{d8c9acee-dec5-11e4-8c75-1681e6b88ec1}";
|
||||
|
||||
// Localization
|
||||
var jsonViewStrings = Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/jsonview.properties");
|
||||
|
||||
/**
|
||||
* This object detects 'application/vnd.mozilla.json.view' content type
|
||||
* and converts it into a JSON Viewer application that allows simple
|
||||
* JSON inspection.
|
||||
*
|
||||
* Inspired by JSON View: https://github.com/bhollis/jsonview/
|
||||
*/
|
||||
var Converter = Class({
|
||||
extends: Unknown,
|
||||
|
||||
interfaces: [
|
||||
"nsIStreamConverter",
|
||||
"nsIStreamListener",
|
||||
"nsIRequestObserver"
|
||||
],
|
||||
|
||||
get wrappedJSObject() this,
|
||||
|
||||
/**
|
||||
* This component works as such:
|
||||
* 1. asyncConvertData captures the listener
|
||||
* 2. onStartRequest fires, initializes stuff, modifies the listener to match our output type
|
||||
* 3. onDataAvailable transcodes the data into a UTF-8 string
|
||||
* 4. onStopRequest gets the collected data and converts it, spits it to the listener
|
||||
* 5. convert does nothing, it's just the synchronous version of asyncConvertData
|
||||
*/
|
||||
convert: function(aFromStream, aFromType, aToType, aCtxt) {
|
||||
return aFromStream;
|
||||
},
|
||||
|
||||
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
||||
this.listener = aListener;
|
||||
},
|
||||
|
||||
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
|
||||
// From https://developer.mozilla.org/en/Reading_textual_data
|
||||
var is = Cc["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Ci.nsIConverterInputStream);
|
||||
is.init(aInputStream, this.charset, -1,
|
||||
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||
|
||||
// Seed it with something positive
|
||||
var bytesRead = 1;
|
||||
while (aCount) {
|
||||
var str = {};
|
||||
var bytesRead = is.readString(aCount, str);
|
||||
if (!bytesRead) {
|
||||
throw new Error("Stream converter failed to read the input stream!");
|
||||
}
|
||||
aCount -= bytesRead;
|
||||
this.data += str.value;
|
||||
}
|
||||
},
|
||||
|
||||
onStartRequest: function(aRequest, aContext) {
|
||||
this.data = "";
|
||||
this.uri = aRequest.QueryInterface(Ci.nsIChannel).URI.spec;
|
||||
|
||||
// Sets the charset if it is available. (For documents loaded from the
|
||||
// filesystem, this is not set.)
|
||||
this.charset = aRequest.QueryInterface(Ci.nsIChannel).contentCharset || 'UTF-8';
|
||||
|
||||
this.channel = aRequest;
|
||||
this.channel.contentType = "text/html";
|
||||
this.channel.contentCharset = "UTF-8";
|
||||
|
||||
this.listener.onStartRequest(this.channel, aContext);
|
||||
},
|
||||
|
||||
/**
|
||||
* This should go something like this:
|
||||
* 1. Make sure we have a unicode string.
|
||||
* 2. Convert it to a Javascript object.
|
||||
* 2.1 Removes the callback
|
||||
* 3. Convert that to HTML? Or XUL?
|
||||
* 4. Spit it back out at the listener
|
||||
*/
|
||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||
let headers = {
|
||||
response: [],
|
||||
request: []
|
||||
}
|
||||
|
||||
let win = NetworkHelper.getWindowForRequest(aRequest);
|
||||
|
||||
let Locale = {
|
||||
$STR: key => {
|
||||
try {
|
||||
return jsonViewStrings.GetStringFromName(key);
|
||||
} catch (err) {
|
||||
Cu.reportError(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
JsonViewUtils.exportIntoContentScope(win, Locale, "Locale");
|
||||
|
||||
Events.once(win, "DOMContentLoaded", event => {
|
||||
Cu.exportFunction(this.postChromeMessage.bind(this), win, {
|
||||
defineAs: "postChromeMessage"
|
||||
});
|
||||
})
|
||||
|
||||
// The request doesn't have to be always nsIHttpChannel
|
||||
// (e.g. in case of data: URLs)
|
||||
if (aRequest instanceof Ci.nsIHttpChannel) {
|
||||
aRequest.visitResponseHeaders({
|
||||
visitHeader: function(name, value) {
|
||||
headers.response.push({name: name, value: value});
|
||||
}
|
||||
});
|
||||
|
||||
aRequest.visitRequestHeaders({
|
||||
visitHeader: function(name, value) {
|
||||
headers.request.push({name: name, value: value});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let outputDoc = "";
|
||||
|
||||
try {
|
||||
headers = JSON.stringify(headers);
|
||||
outputDoc = this.toHTML(this.data, headers, this.uri);
|
||||
} catch (e) {
|
||||
Cu.reportError("JSON Viewer ERROR " + e);
|
||||
outputDoc = this.toErrorPage(e, this.data, this.uri);
|
||||
}
|
||||
|
||||
var storage = Cc["@mozilla.org/storagestream;1"].createInstance(Ci.nsIStorageStream);
|
||||
storage.init(SEGMENT_SIZE, 0xffffffff, null);
|
||||
var out = storage.getOutputStream(0);
|
||||
|
||||
var binout = Cc["@mozilla.org/binaryoutputstream;1"]
|
||||
.createInstance(Ci.nsIBinaryOutputStream);
|
||||
|
||||
binout.setOutputStream(out);
|
||||
binout.writeUtf8Z(outputDoc);
|
||||
binout.close();
|
||||
|
||||
// We need to trim 4 bytes off the front (this could be underlying bug).
|
||||
var trunc = 4;
|
||||
var instream = storage.newInputStream(trunc);
|
||||
|
||||
// Pass the data to the main content listener
|
||||
this.listener.onDataAvailable(this.channel, aContext, instream, 0,
|
||||
instream.available());
|
||||
|
||||
this.listener.onStopRequest(this.channel, aContext, aStatusCode);
|
||||
|
||||
this.listener = null;
|
||||
},
|
||||
|
||||
htmlEncode: function(t) {
|
||||
return t !== null ? t.toString().replace(/&/g,"&").
|
||||
replace(/"/g,""").replace(/</g,"<").replace(/>/g,">") : '';
|
||||
},
|
||||
|
||||
toHTML: function(json, headers, title) {
|
||||
var themeClassName = "theme-" + JsonViewUtils.getCurrentTheme();
|
||||
var baseUrl = "resource:///modules/devtools/client/jsonview/";
|
||||
var theme = (themeClassName == "theme-light") ? "light" : "dark";
|
||||
var themeUrl = '<link rel="stylesheet" type="text/css" ' +
|
||||
'href="css/' + theme + '-theme.css">';
|
||||
|
||||
return '<!DOCTYPE html>\n' +
|
||||
'<html><head><title>' + this.htmlEncode(title) + '</title>' +
|
||||
'<base href="' + this.htmlEncode(baseUrl) + '">' +
|
||||
'<link rel="stylesheet" type="text/css" href="css/main.css">' +
|
||||
themeUrl +
|
||||
'<script data-main="viewer-config" src="lib/require.js"></script>' +
|
||||
'</head><body class="' + themeClassName + '">' +
|
||||
'<div id="content"></div>' +
|
||||
'<div id="json">' + this.htmlEncode(json) + '</div>' +
|
||||
'<div id="headers">' + this.htmlEncode(headers) + '</div>' +
|
||||
'</body></html>';
|
||||
},
|
||||
|
||||
toErrorPage: function(error, data, uri) {
|
||||
// Escape unicode nulls
|
||||
data = data.replace("\u0000", "\uFFFD");
|
||||
|
||||
var errorInfo = error + "";
|
||||
|
||||
var output = '<div id="error">' + _('errorParsing')
|
||||
if (errorInfo.message) {
|
||||
output += '<div class="errormessage">' + errorInfo.message + '</div>';
|
||||
}
|
||||
|
||||
output += '</div><div id="json">' + this.highlightError(data,
|
||||
errorInfo.line, errorInfo.column) + '</div>';
|
||||
|
||||
return '<!DOCTYPE html>\n' +
|
||||
'<html><head><title>' + this.htmlEncode(uri + ' - Error') + '</title>' +
|
||||
'<base href="' + this.htmlEncode(self.data.url()) + '">' +
|
||||
'</head><body>' +
|
||||
output +
|
||||
'</body></html>';
|
||||
},
|
||||
|
||||
// Chrome <-> Content communication
|
||||
|
||||
postChromeMessage: function(type, args, objects) {
|
||||
var value = args;
|
||||
|
||||
switch (type) {
|
||||
case "copy":
|
||||
Clipboard.set(value, "text");
|
||||
break;
|
||||
|
||||
case "copy-headers":
|
||||
this.copyHeaders(value);
|
||||
break;
|
||||
|
||||
case "save":
|
||||
childProcessMessageManager.sendAsyncMessage(
|
||||
"devtools:jsonview:save", value);
|
||||
}
|
||||
},
|
||||
|
||||
copyHeaders: function(headers) {
|
||||
var value = "";
|
||||
var eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n";
|
||||
|
||||
var responseHeaders = headers.response;
|
||||
for (var i=0; i<responseHeaders.length; i++) {
|
||||
var header = responseHeaders[i];
|
||||
value += header.name + ": " + header.value + eol;
|
||||
}
|
||||
|
||||
value += eol;
|
||||
|
||||
var requestHeaders = headers.request;
|
||||
for (var i=0; i<requestHeaders.length; i++) {
|
||||
var header = requestHeaders[i];
|
||||
value += header.name + ": " + header.value + eol;
|
||||
}
|
||||
|
||||
Clipboard.set(value, "text");
|
||||
}
|
||||
});
|
||||
|
||||
// Stream converter component definition
|
||||
var service = xpcom.Service({
|
||||
id: components.ID(CLASS_ID),
|
||||
contract: CONTRACT_ID,
|
||||
Component: Converter,
|
||||
register: false,
|
||||
unregister: false
|
||||
});
|
||||
|
||||
function register() {
|
||||
if (!xpcom.isRegistered(service)) {
|
||||
xpcom.register(service);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function unregister() {
|
||||
if (xpcom.isRegistered(service)) {
|
||||
xpcom.unregister(service);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
exports.JsonViewService = {
|
||||
register: register,
|
||||
unregister: unregister
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
const {devtools} = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
|
||||
// Load JsonView services lazily.
|
||||
XPCOMUtils.defineLazyGetter(this, "JsonViewService", function() {
|
||||
const {JsonViewService} = devtools.require("devtools/client/jsonview/converter-child");
|
||||
return JsonViewService;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "JsonViewSniffer", function() {
|
||||
const {JsonViewSniffer} = devtools.require("devtools/client/jsonview/converter-sniffer");
|
||||
return JsonViewSniffer;
|
||||
});
|
||||
|
||||
// Constants
|
||||
const JSON_VIEW_PREF = "devtools.jsonview.enabled";
|
||||
|
||||
/**
|
||||
* Listen for 'devtools.jsonview.enabled' preference changes and
|
||||
* register/unregister the JSON View XPCOM services as appropriate.
|
||||
*/
|
||||
function ConverterObserver() {
|
||||
}
|
||||
|
||||
ConverterObserver.prototype = {
|
||||
initialize: function() {
|
||||
// Only the DevEdition has this feature available by default.
|
||||
// Users need to manually flip 'devtools.jsonview.enabled' preference
|
||||
// to have it available in other distributions.
|
||||
if (this.isEnabled()) {
|
||||
this.register();
|
||||
}
|
||||
|
||||
Services.prefs.addObserver(JSON_VIEW_PREF, this, false);
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "xpcom-shutdown":
|
||||
this.onShutdown();
|
||||
break;
|
||||
case "nsPref:changed":
|
||||
this.onPrefChanged();
|
||||
break;
|
||||
};
|
||||
},
|
||||
|
||||
onShutdown: function() {
|
||||
Services.prefs.removeObserver(JSON_VIEW_PREF, observer);
|
||||
Services.obs.removeObserver(observer, "xpcom-shutdown");
|
||||
},
|
||||
|
||||
onPrefChanged: function() {
|
||||
if (this.isEnabled()) {
|
||||
this.register();
|
||||
} else {
|
||||
this.unregister();
|
||||
}
|
||||
},
|
||||
|
||||
register: function() {
|
||||
JsonViewSniffer.register();
|
||||
JsonViewService.register();
|
||||
},
|
||||
|
||||
unregister: function() {
|
||||
JsonViewSniffer.unregister();
|
||||
JsonViewService.unregister();
|
||||
},
|
||||
|
||||
isEnabled: function() {
|
||||
return Services.prefs.getBoolPref(JSON_VIEW_PREF);
|
||||
},
|
||||
};
|
||||
|
||||
// Listen to JSON View 'enable' pref and perform dynamic
|
||||
// registration or unregistration of the main application
|
||||
// component.
|
||||
var observer = new ConverterObserver();
|
||||
observer.initialize();
|
|
@ -0,0 +1,102 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Ci, components} = require("chrome");
|
||||
const xpcom = require("sdk/platform/xpcom");
|
||||
const {Unknown} = require("sdk/platform/xpcom");
|
||||
const {Class} = require("sdk/core/heritage");
|
||||
|
||||
const categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
|
||||
|
||||
loader.lazyRequireGetter(this, "NetworkHelper",
|
||||
"devtools/shared/webconsole/network-helper");
|
||||
|
||||
// Constants
|
||||
const JSON_TYPE = "application/json";
|
||||
const CONTRACT_ID = "@mozilla.org/devtools/jsonview-sniffer;1";
|
||||
const CLASS_ID = "{4148c488-dca1-49fc-a621-2a0097a62422}";
|
||||
const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view";
|
||||
const JSON_VIEW_TYPE = "JSON View";
|
||||
const CONTENT_SNIFFER_CATEGORY = "net-content-sniffers";
|
||||
|
||||
/**
|
||||
* This component represents a sniffer (implements nsIContentSniffer
|
||||
* interface) responsible for changing top level 'application/json'
|
||||
* document types to: 'application/vnd.mozilla.json.view'.
|
||||
*
|
||||
* This internal type is consequently rendered by JSON View component
|
||||
* that represents the JSON through a viewer interface.
|
||||
*/
|
||||
var Sniffer = Class({
|
||||
extends: Unknown,
|
||||
|
||||
interfaces: [
|
||||
"nsIContentSniffer",
|
||||
],
|
||||
|
||||
get wrappedJSObject() this,
|
||||
|
||||
getMIMETypeFromContent: function(aRequest, aData, aLength) {
|
||||
// JSON View is enabled only for top level loads only.
|
||||
if (!NetworkHelper.isTopLevelLoad(aRequest)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (aRequest instanceof Ci.nsIChannel) {
|
||||
try {
|
||||
if (aRequest.contentDisposition == Ci.nsIChannel.DISPOSITION_ATTACHMENT) {
|
||||
return "";
|
||||
}
|
||||
} catch (e) {
|
||||
// Channel doesn't support content dispositions
|
||||
}
|
||||
|
||||
// Check the response content type and if it's application/json
|
||||
// change it to new internal type consumed by JSON View.
|
||||
if (aRequest.contentType == JSON_TYPE) {
|
||||
return JSON_VIEW_MIME_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
var service = xpcom.Service({
|
||||
id: components.ID(CLASS_ID),
|
||||
contract: CONTRACT_ID,
|
||||
Component: Sniffer,
|
||||
register: false,
|
||||
unregister: false
|
||||
});
|
||||
|
||||
function register() {
|
||||
if (!xpcom.isRegistered(service)) {
|
||||
xpcom.register(service);
|
||||
categoryManager.addCategoryEntry(CONTENT_SNIFFER_CATEGORY, JSON_VIEW_TYPE,
|
||||
CONTRACT_ID, false, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function unregister() {
|
||||
if (xpcom.isRegistered(service)) {
|
||||
categoryManager.deleteCategoryEntry(CONTENT_SNIFFER_CATEGORY,
|
||||
JSON_VIEW_TYPE, false)
|
||||
xpcom.unregister(service);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
exports.JsonViewSniffer = {
|
||||
register: register,
|
||||
unregister: unregister
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Dark Theme (copied from themes/dark-theme.css) */
|
||||
|
||||
:root {
|
||||
--theme-body-background: #14171a;
|
||||
|
||||
--theme-tab-toolbar-background: #252c33;
|
||||
--theme-toolbar-background: #343c45;
|
||||
--theme-selection-background: #1d4f73;
|
||||
--theme-splitter-color: black;
|
||||
--theme-selection-color: #f5f7fa;
|
||||
--theme-comment: #757873;
|
||||
|
||||
--theme-body-color: #8fa1b2;
|
||||
--theme-body-color-alt: #b6babf;
|
||||
--theme-content-color1: #a9bacb;
|
||||
|
||||
--theme-highlight-green: #70bf53;
|
||||
--theme-highlight-blue: #46afe3;
|
||||
--theme-highlight-orange: #d96629;
|
||||
--theme-highlight-bluegrey: #5e88b0;
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
.domTable {
|
||||
font-size: 11px;
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
line-height: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.domTable > tbody > tr > td {
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.memberLabelCell {
|
||||
padding: 2px 0 2px 0px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.memberValueCell {
|
||||
padding: 2px 0 2px 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.memberLabel {
|
||||
cursor: default;
|
||||
overflow: hidden;
|
||||
padding-left: 18px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.memberLabelPrefix {
|
||||
color: gray;
|
||||
margin-right: 3px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.memberValueIcon > div {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Read Only Properties */
|
||||
|
||||
.memberValueCell.readOnly {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.memberValueIcon.readOnly {
|
||||
background: url("read-only-prop.svg") no-repeat;
|
||||
background-position: 4px 4px;
|
||||
background-size: 10px 10px;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.memberRow.hasChildren > .memberLabelCell > .memberLabel:hover,
|
||||
.memberRow.cropped > .memberLabelCell > .memberLabel:hover {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.memberRow:hover {
|
||||
background-color: #EFEFEF;
|
||||
}
|
||||
|
||||
.panelNode-dom .memberRow td,
|
||||
.panelNode-domSide .memberRow td {
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.userLabel,
|
||||
.userClassLabel,
|
||||
.userFunctionLabel {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.userLabel {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.userClassLabel {
|
||||
color: #E90000;
|
||||
}
|
||||
|
||||
.userFunctionLabel {
|
||||
color: #025E2A;
|
||||
}
|
||||
|
||||
.domLabel {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.domClassLabel {
|
||||
color: #E90000;
|
||||
}
|
||||
|
||||
.domFunctionLabel {
|
||||
color: #025E2A;
|
||||
}
|
||||
|
||||
.ordinalLabel {
|
||||
color: SlateBlue;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Twisties */
|
||||
|
||||
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
|
||||
.memberRow.cropped > .memberLabelCell > .memberLabel {
|
||||
background-image: url(twisty-closed.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 2px calc(0.5em - 3px);
|
||||
min-height: 12px;
|
||||
}
|
||||
|
||||
.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,
|
||||
.memberRow.cropped.opened > .memberLabelCell > .memberLabel {
|
||||
background-image: url(twisty-open.svg);
|
||||
background-repeat: no-repeat;
|
||||
min-height: 12px;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Layout support */
|
||||
|
||||
.memberChildren {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.memberLabelCell,
|
||||
.memberValueCell {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.memberLabelCell {
|
||||
min-width: 30px;
|
||||
}
|
||||
|
||||
.memberRow:hover {
|
||||
background-color: transparent !important;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* General */
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
*:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
#content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: white;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#json,
|
||||
#headers {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Dark Theme */
|
||||
|
||||
body.theme-dark {
|
||||
color: var(--theme-body-color);
|
||||
background-color: var(--theme-body-background);
|
||||
}
|
||||
|
||||
.theme-dark pre {
|
||||
background-color: var(--theme-body-background);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Headers Panel */
|
||||
|
||||
.headersPanelBox {
|
||||
height: 100%;
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.headersPanelBox .netInfoHeadersTable {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.headersPanelBox .netHeadersGroup {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.headersPanelBox .netInfoHeadersGroup {
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid #D7D7D7;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 4px;
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
font-weight: bold;
|
||||
color: #565656;
|
||||
}
|
||||
|
||||
.headersPanelBox .netHeader.twisty {
|
||||
background-image: url(twisty-open.svg);
|
||||
background-repeat: no-repeat;
|
||||
min-height: 12px;
|
||||
background-position: 2px 50%;
|
||||
}
|
||||
|
||||
.headersPanelBox .netHeader {
|
||||
cursor: pointer;
|
||||
padding-left: 17px;
|
||||
position: static;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.headersPanelBox .netInfoParamValue code {
|
||||
display: block;
|
||||
color: #18191A;
|
||||
font-size: 11px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.headersPanelBox .netInfoParamName {
|
||||
padding: 2px 10px 0 0;
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
font-weight: bold;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Dark Theme */
|
||||
|
||||
|
||||
.theme-dark .headersPanelBox .netInfoParamName {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.theme-dark .headersPanelBox .netInfoParamValue code {
|
||||
color: var(--theme-highlight-orange);
|
||||
}
|
||||
|
||||
.theme-dark .headersPanelBox .netInfoHeadersGroup {
|
||||
color: var(--theme-body-color-alt);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* JSON Panel */
|
||||
|
||||
.jsonParseError {
|
||||
font-size: 12px;
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
line-height: 15px;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
color: red;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Light Theme Constants (copied from themes/light-theme.css) */
|
||||
|
||||
:root {
|
||||
--theme-body-background: #fcfcfc;
|
||||
|
||||
--theme-tab-toolbar-background: #ebeced;
|
||||
--theme-toolbar-background: #f0f1f2;
|
||||
--theme-selection-background: #4c9ed9;
|
||||
--theme-splitter-color: #aaaaaa;
|
||||
--theme-selection-color: #f5f7fa;
|
||||
--theme-comment: #757873;
|
||||
|
||||
--theme-body-color: #18191a;
|
||||
--theme-body-color-alt: #585959;
|
||||
--theme-content-color1: #292e33;
|
||||
|
||||
--theme-highlight-green: #2cbb0f;
|
||||
--theme-highlight-blue: #0088cc;
|
||||
--theme-highlight-orange: #f13c00;
|
||||
--theme-highlight-bluegrey: #0072ab;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@import "general.css";
|
||||
@import "reps.css";
|
||||
@import "dom-tree.css";
|
||||
@import "search-box.css";
|
||||
@import "tabs.css";
|
||||
@import "toolbar.css";
|
||||
@import "json-panel.css";
|
||||
@import "text-panel.css";
|
||||
@import "headers-panel.css";
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Panel Content */
|
||||
|
||||
.panelContent {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Theme Firebug */
|
||||
|
||||
.theme-firebug .panelContent {
|
||||
height: calc(100% - 30px);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Theme Light & Theme Dark*/
|
||||
|
||||
.theme-dark .panelContent,
|
||||
.theme-light .panelContent {
|
||||
height: calc(100% - 27px);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
|
||||
DevToolsModules(
|
||||
'dark-theme.css',
|
||||
'dom-tree.css',
|
||||
'general.css',
|
||||
'headers-panel.css',
|
||||
'json-panel.css',
|
||||
'light-theme.css',
|
||||
'main.css',
|
||||
'read-only-prop.svg',
|
||||
'reps.css',
|
||||
'search-box.css',
|
||||
'search.svg',
|
||||
'tabs.css',
|
||||
'text-panel.css',
|
||||
'toolbar.css',
|
||||
'twisty-closed.svg',
|
||||
'twisty-open.svg'
|
||||
)
|
|
@ -0,0 +1,256 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- 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/. -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
width="12"
|
||||
height="12"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3892">
|
||||
<stop
|
||||
id="stop3894"
|
||||
style="stop-color:#787878;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3896"
|
||||
style="stop-color:#b4b4b4;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3765">
|
||||
<stop
|
||||
id="stop3767"
|
||||
style="stop-color:#505050;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3769"
|
||||
style="stop-color:#787878;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3757">
|
||||
<stop
|
||||
id="stop3759"
|
||||
style="stop-color:#c8c8c8;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3761"
|
||||
style="stop-color:#dcdcdc;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3765-6">
|
||||
<stop
|
||||
id="stop3767-0"
|
||||
style="stop-color:#a0a0a0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3769-4"
|
||||
style="stop-color:#c8c8c8;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="11.376831"
|
||||
y1="1052.0852"
|
||||
x2="4.5592546"
|
||||
y2="1040.6658"
|
||||
id="linearGradient3830"
|
||||
xlink:href="#linearGradient3757"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.87012989,0,0,0.82456145,1.0389611,183.57212)" />
|
||||
<linearGradient
|
||||
x1="8.8415442"
|
||||
y1="1053.3849"
|
||||
x2="1.9174434"
|
||||
y2="1041.9227"
|
||||
id="linearGradient3832"
|
||||
xlink:href="#linearGradient3765-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.87012989,0,0,0.82456145,1.0389611,183.57212)" />
|
||||
<linearGradient
|
||||
x1="8.6370001"
|
||||
y1="4.3111062"
|
||||
x2="6.3403625"
|
||||
y2="0.58274388"
|
||||
id="linearGradient3861"
|
||||
xlink:href="#linearGradient3757"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.89600004,0,0,0.97745455,0.83199985,0.9945)" />
|
||||
<linearGradient
|
||||
x1="7.1882658"
|
||||
y1="5.0780835"
|
||||
x2="4.9555426"
|
||||
y2="1.392331"
|
||||
id="linearGradient3866"
|
||||
xlink:href="#linearGradient3765-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.89600004,0,0,0.97745455,0.83199985,0.9945)" />
|
||||
<linearGradient
|
||||
x1="9.3919191"
|
||||
y1="12.115811"
|
||||
x2="7.4015098"
|
||||
y2="7.4140091"
|
||||
id="linearGradient3909"
|
||||
xlink:href="#linearGradient3892"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="8.5397177"
|
||||
y1="12.497831"
|
||||
x2="6.6080809"
|
||||
y2="7.825417"
|
||||
id="linearGradient3917"
|
||||
xlink:href="#linearGradient3765"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="8.5397177"
|
||||
y1="12.497831"
|
||||
x2="6.6080809"
|
||||
y2="7.825417"
|
||||
id="linearGradient3039"
|
||||
xlink:href="#linearGradient3765"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.71428573,0,0,0.71492245,0.28571425,0.27617311)" />
|
||||
<linearGradient
|
||||
x1="9.3919191"
|
||||
y1="12.115811"
|
||||
x2="7.4015098"
|
||||
y2="7.4140091"
|
||||
id="linearGradient3041"
|
||||
xlink:href="#linearGradient3892"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.71428573,0,0,0.71492245,0.28571425,0.27617311)" />
|
||||
<linearGradient
|
||||
x1="11.376831"
|
||||
y1="1052.0852"
|
||||
x2="4.5592546"
|
||||
y2="1040.6658"
|
||||
id="linearGradient3044"
|
||||
xlink:href="#linearGradient3757"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.62152136,0,0,0.58949749,1.0278293,-609.4026)" />
|
||||
<linearGradient
|
||||
x1="8.8415442"
|
||||
y1="1053.3849"
|
||||
x2="1.9174434"
|
||||
y2="1041.9227"
|
||||
id="linearGradient3046"
|
||||
xlink:href="#linearGradient3765-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.62152136,0,0,0.58949749,1.0278293,-609.4026)" />
|
||||
<linearGradient
|
||||
x1="8.6370001"
|
||||
y1="4.3111062"
|
||||
x2="6.3403625"
|
||||
y2="0.58274388"
|
||||
id="linearGradient3049"
|
||||
xlink:href="#linearGradient3757"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.64000004,0,0,0.6988042,0.87999987,0.98716349)" />
|
||||
<linearGradient
|
||||
x1="7.1882658"
|
||||
y1="5.0780835"
|
||||
x2="4.9555426"
|
||||
y2="1.392331"
|
||||
id="linearGradient3051"
|
||||
xlink:href="#linearGradient3765-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.64000004,0,0,0.6988042,0.87999987,0.98716349)" />
|
||||
<linearGradient
|
||||
x1="8.6370001"
|
||||
y1="4.3111062"
|
||||
x2="6.3403625"
|
||||
y2="0.58274388"
|
||||
id="linearGradient3826"
|
||||
xlink:href="#linearGradient3757"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.64000004,0,0,0.6988042,0.87999987,0.98716349)" />
|
||||
<linearGradient
|
||||
x1="7.1882658"
|
||||
y1="5.0780835"
|
||||
x2="4.9555426"
|
||||
y2="1.392331"
|
||||
id="linearGradient3828"
|
||||
xlink:href="#linearGradient3765-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.64000004,0,0,0.6988042,0.87999987,0.98716349)" />
|
||||
<linearGradient
|
||||
x1="11.376831"
|
||||
y1="1052.0852"
|
||||
x2="4.5592546"
|
||||
y2="1040.6658"
|
||||
id="linearGradient3831"
|
||||
xlink:href="#linearGradient3757"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.62152136,0,0,0.58949749,1.0278293,-609.4026)" />
|
||||
<linearGradient
|
||||
x1="8.8415442"
|
||||
y1="1053.3849"
|
||||
x2="1.9174434"
|
||||
y2="1041.9227"
|
||||
id="linearGradient3833"
|
||||
xlink:href="#linearGradient3765-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.62152136,0,0,0.58949749,1.0278293,-609.4026)" />
|
||||
<linearGradient
|
||||
x1="8.5397177"
|
||||
y1="12.497831"
|
||||
x2="6.6080809"
|
||||
y2="7.825417"
|
||||
id="linearGradient3835"
|
||||
xlink:href="#linearGradient3765"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.71428573,0,0,0.71492245,0.28571425,0.27617311)" />
|
||||
<linearGradient
|
||||
x1="9.3919191"
|
||||
y1="12.115811"
|
||||
x2="7.4015098"
|
||||
y2="7.4140091"
|
||||
id="linearGradient3837"
|
||||
xlink:href="#linearGradient3892"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.71428573,0,0,0.71492245,0.28571425,0.27617311)" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="matrix(1.1910164,0,0,1.1910639,-1.146234,-1.1462857)"
|
||||
id="g3821">
|
||||
<path
|
||||
d="m 6.0000001,1.2145088 c -1.6317576,0 -2.9446627,1.2860444 -2.9910715,2.9043725 0.1136269,-0.018496 0.2381347,-0.044683 0.3571429,-0.044683 l 0.9375,0 c 0.082361,-0.8799332 0.7978203,-1.6532581 1.6964286,-1.6532581 0.8986083,0 1.6140679,0.7733249 1.6964286,1.6532581 l 0.9375,0 c 0.1190079,0 0.2435157,0.026187 0.3571429,0.044683 C 8.944663,2.5005532 7.6317573,1.2145088 6.0000001,1.2145088 z"
|
||||
id="path3773"
|
||||
style="fill:url(#linearGradient3826);fill-opacity:1;stroke:url(#linearGradient3828);stroke-width:0.50376141;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<rect
|
||||
width="9.5714283"
|
||||
height="6.7202706"
|
||||
rx="1.679238"
|
||||
ry="1.6791711"
|
||||
x="1.2142856"
|
||||
y="4.0652847"
|
||||
id="rect2987-9"
|
||||
style="fill:url(#linearGradient3831);fill-opacity:1;stroke:url(#linearGradient3833);stroke-width:0.50376141;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 6.0000001,5.5040435 c -0.6706315,0 -1.2053572,0.5352023 -1.2053572,1.2064317 0,0.5619236 0.3753047,1.0226472 0.8928572,1.1617489 l 0,1.4745276 0.625,0 0,-1.4745276 C 6.8300525,7.7331224 7.2053573,7.2723988 7.2053573,6.7104752 c 0,-0.6712294 -0.5347257,-1.2064317 -1.2053572,-1.2064317 z"
|
||||
id="path3898"
|
||||
style="fill:url(#linearGradient3835);fill-opacity:1;stroke:url(#linearGradient3837);stroke-width:0.33584094;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 8.8 KiB |
|
@ -0,0 +1,211 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
.objectLink:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.objectBox-object {
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-weight: bold;
|
||||
color: DarkGreen;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.objectBox-string,
|
||||
.objectBox-text,
|
||||
.objectBox-number,
|
||||
.objectLink-element,
|
||||
.objectLink-textNode,
|
||||
.objectLink-function,
|
||||
.objectBox-stackTrace,
|
||||
.objectLink-profile,
|
||||
.objectBox-table {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.objectBox-string,
|
||||
.objectBox-text,
|
||||
.objectLink-textNode,
|
||||
.objectBox-table {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.objectBox-number,
|
||||
.objectLink-styleRule,
|
||||
.objectLink-element,
|
||||
.objectLink-textNode {
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.objectBox-string {
|
||||
color: #FF0000;
|
||||
}
|
||||
|
||||
.objectLink-function,
|
||||
.objectBox-stackTrace,
|
||||
.objectLink-profile {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
.objectBox-null,
|
||||
.objectBox-undefined,
|
||||
.objectBox-hint,
|
||||
.logRowHint {
|
||||
font-style: italic;
|
||||
color: #787878;
|
||||
}
|
||||
|
||||
.objectBox-scope {
|
||||
color: #707070;
|
||||
}
|
||||
.objectBox-optimizedAway {
|
||||
color: #909090;
|
||||
}
|
||||
|
||||
.objectLink-sourceLink {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 2px;
|
||||
padding-left: 8px;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-weight: bold;
|
||||
color: #0000FF;
|
||||
}
|
||||
|
||||
.objectLink-sourceLink > .systemLink {
|
||||
float: right;
|
||||
color: #FF0000;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.objectLink-event,
|
||||
.objectLink-eventLog,
|
||||
.objectLink-regexp,
|
||||
.objectLink-object,
|
||||
.objectLink-Date {
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-weight: bold;
|
||||
color: DarkGreen;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.objectLink-object .nodeName,
|
||||
.objectLink-NamedNodeMap .nodeName,
|
||||
.objectLink-NamedNodeMap .objectEqual,
|
||||
.objectLink-NamedNodeMap .arrayLeftBracket,
|
||||
.objectLink-NamedNodeMap .arrayRightBracket,
|
||||
.objectLink-Attr .attrEqual,
|
||||
.objectLink-Attr .attrTitle {
|
||||
color: rgb(0, 0, 136)
|
||||
}
|
||||
|
||||
.objectLink-object .nodeName {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.objectLeftBrace,
|
||||
.objectRightBrace,
|
||||
.objectEqual,
|
||||
.objectComma,
|
||||
.arrayLeftBracket,
|
||||
.arrayRightBracket,
|
||||
.arrayComma {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.objectLeftBrace,
|
||||
.objectRightBrace,
|
||||
.arrayLeftBracket,
|
||||
.arrayRightBracket {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.objectLeftBrace,
|
||||
.arrayLeftBracket {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.objectRightBrace,
|
||||
.arrayRightBracket {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cycle reference*/
|
||||
|
||||
.objectLink-Reference {
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
color: rgb(102, 102, 255);
|
||||
}
|
||||
|
||||
.objectBox-array > .objectTitle {
|
||||
font-weight: bold;
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.caption {
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
font-weight: bold;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Light Theme & Dark Theme */
|
||||
|
||||
.theme-dark .domLabel,
|
||||
.theme-light .domLabel {
|
||||
color: var(--theme-highlight-bluegrey);
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-number,
|
||||
.theme-light .objectBox-number {
|
||||
color: var(--theme-highlight-green);
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-string,
|
||||
.theme-light .objectBox-string {
|
||||
color: var(--theme-highlight-orange)
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-null,
|
||||
.theme-dark .objectBox-undefined,
|
||||
.theme-light .objectBox-null,
|
||||
.theme-light .objectBox-undefined {
|
||||
font-style: normal;
|
||||
color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.theme-dark .objectBox-object,
|
||||
.theme-light .objectBox-object {
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-weight: normal;
|
||||
color: var(--theme-highlight-bluegrey);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.theme-dark .caption,
|
||||
.theme-light .caption {
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
font-weight: normal;
|
||||
color: var(--theme-highlight-bluegrey);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Search Box */
|
||||
|
||||
.searchBox {
|
||||
height: 18px;
|
||||
font-size: 12px;
|
||||
margin-top: 0;
|
||||
border: 1px solid rgb(170, 188, 207);
|
||||
width: 200px;
|
||||
position: fixed;
|
||||
right: 5px;
|
||||
background-image: url("search.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 2px center;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Light Theme & Dark Theme*/
|
||||
|
||||
.theme-dark .searchBox,
|
||||
.theme-light .searchBox {
|
||||
border: 1px solid rgb(170, 170, 170);
|
||||
background-image: url("chrome://browser/skin/devtools/magnifying-glass-light.png");
|
||||
background-position: 8px center;
|
||||
border-radius: 2px;
|
||||
padding-left: 25px;
|
||||
margin-top: 1px;
|
||||
height: 16px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Dark Theme */
|
||||
|
||||
.theme-dark .searchBox {
|
||||
background-color: rgba(24, 29, 32, 1);
|
||||
color: rgba(184, 200, 217, 1);
|
||||
border-color: var(--theme-splitter-color);
|
||||
background-image: url("chrome://browser/skin/devtools/magnifying-glass.png");
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- 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/. -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3841">
|
||||
<stop
|
||||
id="stop3843"
|
||||
style="stop-color:#427dc2;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3845"
|
||||
style="stop-color:#5e9fce;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3795">
|
||||
<stop
|
||||
id="stop3797"
|
||||
style="stop-color:#2f5d93;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3799"
|
||||
style="stop-color:#3a87bd;stop-opacity:0.99215686"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
x="-0.1195599"
|
||||
y="-0.12044335"
|
||||
width="1.2391198"
|
||||
height="1.2408867"
|
||||
color-interpolation-filters="sRGB"
|
||||
id="filter2984">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur2986"
|
||||
stdDeviation="0.63671875" />
|
||||
</filter>
|
||||
<linearGradient
|
||||
x1="4.0935063"
|
||||
y1="13.423457"
|
||||
x2="4.0935063"
|
||||
y2="2.742672"
|
||||
id="linearGradient3800"
|
||||
xlink:href="#linearGradient3841"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
x1="8.7112017"
|
||||
y1="13.579539"
|
||||
x2="8.7112017"
|
||||
y2="2.5663419"
|
||||
id="linearGradient3808"
|
||||
xlink:href="#linearGradient3795"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
d="m 10.140619,1.656256 c -2.3511382,0 -4.2500001,1.898862 -4.2500001,4.2500004 0,0.751994 0.189088,1.449383 0.53125,2.0625 l -4.8125,4.8124996 1.5625001,1.5625 4.7812499,-4.7812496 c 0.6402543,0.38528 1.3858221,0.5937496 2.1875001,0.5937496 2.351138,0 4.25,-1.8988616 4.25,-4.2499996 0,-2.3511384 -1.898862,-4.2500004 -4.25,-4.2500004 z m 0,1.53125 c 1.503797,0 2.71875,1.214953 2.71875,2.7187504 0,1.503798 -1.214953,2.71875 -2.71875,2.71875 -1.5037975,0 -2.7187501,-1.214952 -2.7187501,-2.71875 0,-1.5037974 1.2149526,-2.7187504 2.7187501,-2.7187504 z"
|
||||
id="path3014-7"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter2984)" />
|
||||
<path
|
||||
d="M 10,2 C 7.7908609,2 6,3.7908609 6,6 6,6.8284272 6.2562027,7.6115959 6.6875,8.25 L 1.8125,13.125 2.875,14.1875 7.75,9.3125 C 8.3884041,9.7437973 9.1715728,10 10,10 12.209139,10 14,8.2091391 14,6 14,3.7908609 12.209139,2 10,2 z m 0,1 c 1.656854,0 3,1.3431458 3,3 0,1.6568542 -1.343146,3 -3,3 C 8.3431458,9 7,7.6568542 7,6 7,4.3431458 8.3431458,3 10,3 z"
|
||||
id="path2994"
|
||||
style="fill:url(#linearGradient3800);fill-opacity:1;stroke:url(#linearGradient3808);stroke-width:0.60000002;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.5 KiB |
|
@ -0,0 +1,205 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Tabs General Styles */
|
||||
|
||||
.tabs {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tabs .tabs-navigation {
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
font-size: 14px;
|
||||
border-bottom-color: rgb(170, 188, 207);
|
||||
}
|
||||
|
||||
.tabs .tabs-menu {
|
||||
display: table;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tabs .tabs-menu-item {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.tabs .tabs-menu-item a {
|
||||
display: block;
|
||||
color: #A9A9A9;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.tabs .tabs-menu-item a {
|
||||
border: 1px solid transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tabs .tab-panel {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.tabs .tab-panel > DIV,
|
||||
.tabs .tab-panel > DIV > DIV {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Firebug Theme */
|
||||
|
||||
.theme-firebug .tabs {
|
||||
background-color: rgb(219, 234, 249);
|
||||
background-image: linear-gradient(rgba(253, 253, 253, 0.2), rgba(253, 253, 253, 0));
|
||||
}
|
||||
|
||||
.theme-firebug .tabs .tabs-navigation {
|
||||
padding-top: 3px;
|
||||
padding-left: 3px;
|
||||
height: 27px;
|
||||
border-bottom: 1px solid rgb(170, 188, 207);
|
||||
}
|
||||
|
||||
.theme-firebug .tabs .tab-panel {
|
||||
height: calc(100% - 31px); /* minus the height of the tab bar */
|
||||
}
|
||||
|
||||
.theme-firebug .tabs .tabs-menu-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.theme-firebug .tabs .tabs-menu-item a {
|
||||
padding: 5px 8px 4px 8px;;
|
||||
font-weight: bold;
|
||||
color: #565656;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.theme-firebug .tabs .tabs-menu-item.is-active a,
|
||||
.theme-firebug .tabs .tabs-menu-item.is-active a:focus {
|
||||
background-color: rgb(247, 251, 254);
|
||||
border: 1px solid rgb(170, 188, 207);
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.theme-firebug .tabs .tabs-menu-item:hover a {
|
||||
border: 1px solid #C8C8C8;
|
||||
border-bottom: 1px solid transparent;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.theme-firebug .tabs .tabs-menu-item.is-active:hover a {
|
||||
border: 1px solid rgb(170, 188, 207) !important;
|
||||
background-color: rgb(247, 251, 254) !important;
|
||||
border-bottom-color: transparent !important;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Light Theme */
|
||||
|
||||
.theme-dark .tabs,
|
||||
.theme-light .tabs {
|
||||
background: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-navigation,
|
||||
.theme-light .tabs .tabs-navigation {
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
box-shadow: 0 -2px 0 rgba(170, 170, 170,.1) inset;
|
||||
height: 24px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tab-panel,
|
||||
.theme-light .tabs .tab-panel {
|
||||
height: calc(100% - 24px); /* minus the height of the tab bar */
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item,
|
||||
.theme-light .tabs .tabs-menu-item {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
-moz-border-start-width: 1px;
|
||||
border-color: var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item a,
|
||||
.theme-light .tabs .tabs-menu-item a {
|
||||
color: var(--theme-content-color1);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item a:hover,
|
||||
.theme-dark .tabs .tabs-menu-item a,
|
||||
.theme-light .tabs .tabs-menu-item a:hover,
|
||||
.theme-light .tabs .tabs-menu-item a {
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item:hover,
|
||||
.theme-light .tabs .tabs-menu-item:hover {
|
||||
background-color: rgba(170,170,170,.2);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item.is-active,
|
||||
.theme-dark .tabs .tabs-menu-item.is-active:hover,
|
||||
.theme-light .tabs .tabs-menu-item.is-active,
|
||||
.theme-light .tabs .tabs-menu-item.is-active:hover {
|
||||
background-color: var(--theme-selection-background);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item.is-active a,
|
||||
.theme-dark .tabs .tabs-menu-item.is-active:hover a,
|
||||
.theme-light .tabs .tabs-menu-item.is-active a,
|
||||
.theme-light .tabs .tabs-menu-item.is-active:hover a {
|
||||
color: var(--theme-selection-color);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item:active:hover,
|
||||
.theme-light .tabs .tabs-menu-item:active:hover {
|
||||
background-color: rgba(170,170,170,.4);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item.is-active,
|
||||
.theme-light .tabs .tabs-menu-item.is-active {
|
||||
box-shadow: 0 2px 0 #d7f1ff inset,
|
||||
0 8px 3px -5px #2b82bf inset,
|
||||
0 -2px 0 rgba(0,0,0,.06) inset;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Dark Theme */
|
||||
|
||||
.theme-dark .tabs .tabs-navigation {
|
||||
box-shadow: 0px -2px 0px rgba(0, 0, 0, 0.1) inset;
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item a {
|
||||
color: #CED3D9;
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item a:hover,
|
||||
.theme-dark .tabs .tabs-menu-item a {
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item:active:hover {
|
||||
background-color: hsla(206,37%,4%,.4);
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tabs-menu-item.is-active {
|
||||
box-shadow: 0px 2px 0px #D7F1FF inset,
|
||||
0px 8px 3px -5px #2B82BF inset,
|
||||
0px -2px 0px rgba(0, 0, 0, 0.2) inset;
|
||||
}
|
||||
|
||||
.theme-dark .tabs .tab-panel {
|
||||
background-color: var(--theme-body-background);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Text Panel */
|
||||
|
||||
.textPanelBox {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.textPanelBox .data {
|
||||
font-size: 11px;
|
||||
font-family: monospace;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.textPanelBox pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Dark Theme */
|
||||
|
||||
.theme-dark .textPanelBox {
|
||||
color: var(--theme-content-color1);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Toolbar */
|
||||
|
||||
.toolbar {
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
height: 22px;
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
padding: 4px 0 3px 0;
|
||||
}
|
||||
|
||||
.toolbar .btn {
|
||||
margin-left: 5px;
|
||||
background-color: #E6E6E6;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
-moz-user-select: none;
|
||||
padding: 0 2px 1px 2px;
|
||||
}
|
||||
|
||||
.toolbar .btn::-moz-focus-inner {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Firebug Theme */
|
||||
|
||||
.theme-firebug .toolbar {
|
||||
border-bottom: 1px solid rgb(170, 188, 207);
|
||||
background-color: rgb(219, 234, 249) !important;
|
||||
background-image: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.2));
|
||||
}
|
||||
|
||||
.theme-firebug .toolbar .btn {
|
||||
border-radius: 2px;
|
||||
color: #141414;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.theme-firebug .toolbar .btn:hover {
|
||||
color: #333;
|
||||
background-color: #e6e6e6;
|
||||
border-color: #adadad;
|
||||
}
|
||||
|
||||
.theme-firebug .toolbar .btn:active {
|
||||
background-image: none;
|
||||
outline: 0;
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Light Theme & Dark Theme*/
|
||||
|
||||
.theme-dark .toolbar,
|
||||
.theme-light .toolbar {
|
||||
background-color: var(--theme-toolbar-background);
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
padding: 1px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.theme-dark .toolbar .btn,
|
||||
.theme-light .toolbar .btn {
|
||||
min-width: 78px;
|
||||
min-height: 18px;
|
||||
color: var(--theme-content-color1);
|
||||
text-shadow: none;
|
||||
margin: 1px 2px 1px 2px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background-color: rgba(170, 170, 170, .2); /* Splitter */
|
||||
transition: background 0.05s ease-in-out;
|
||||
}
|
||||
|
||||
.theme-dark .toolbar .btn:hover,
|
||||
.theme-light .toolbar .btn:hover {
|
||||
background: rgba(170, 170, 170, .3); /* Splitters */
|
||||
}
|
||||
|
||||
.theme-dark .toolbar .btn:not([disabled]):hover:active,
|
||||
.theme-light .toolbar .btn:not([disabled]):hover:active {
|
||||
background: rgba(170, 170, 170, .4); /* Splitters */
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- 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/. -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
width="11"
|
||||
height="11"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3792">
|
||||
<stop
|
||||
id="stop3795"
|
||||
style="stop-color:#c3baaa;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3797"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="6.0530181"
|
||||
y1="7.092885"
|
||||
x2="2.8882971"
|
||||
y2="1.7999334"
|
||||
id="linearGradient3799"
|
||||
xlink:href="#linearGradient3792"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0256411,0,0,1.0256411,-0.11538478,1.8846152)" />
|
||||
<linearGradient
|
||||
x1="6.0530181"
|
||||
y1="7.092885"
|
||||
x2="2.8882971"
|
||||
y2="1.7999334"
|
||||
id="linearGradient2992"
|
||||
xlink:href="#linearGradient3792"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0256411,0,0,1.0256411,-0.11538478,1.8846152)" />
|
||||
<linearGradient
|
||||
x1="6.0530181"
|
||||
y1="7.092885"
|
||||
x2="2.8882971"
|
||||
y2="1.7999334"
|
||||
id="linearGradient2996"
|
||||
xlink:href="#linearGradient3792"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0256411,0,0,1.0256411,0.88461522,0.8846152)" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect
|
||||
width="8"
|
||||
height="8"
|
||||
rx="1"
|
||||
ry="1"
|
||||
x="1.5"
|
||||
y="1.5"
|
||||
id="rect3022"
|
||||
style="fill:url(#linearGradient2996);fill-opacity:1;stroke:#7898b5;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
d="M 5,3 5,5 3,5 3,6 5,6 5,8 6,8 6,6 8,6 8,5 6,5 6,3 5,3 z"
|
||||
id="rect3801"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" />
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.5 KiB |
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- 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/. -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
width="11"
|
||||
height="11"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3792">
|
||||
<stop
|
||||
id="stop3795"
|
||||
style="stop-color:#c3baaa;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3797"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="6.0530181"
|
||||
y1="7.092885"
|
||||
x2="2.8882971"
|
||||
y2="1.7999334"
|
||||
id="linearGradient3799"
|
||||
xlink:href="#linearGradient3792"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0256411,0,0,1.0256411,-0.11538478,1.8846152)" />
|
||||
<linearGradient
|
||||
x1="6.0530181"
|
||||
y1="7.092885"
|
||||
x2="2.8882971"
|
||||
y2="1.7999334"
|
||||
id="linearGradient2992"
|
||||
xlink:href="#linearGradient3792"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0256411,0,0,1.0256411,-0.11538478,1.8846152)" />
|
||||
<linearGradient
|
||||
x1="6.0530181"
|
||||
y1="7.092885"
|
||||
x2="2.8882971"
|
||||
y2="1.7999334"
|
||||
id="linearGradient2996"
|
||||
xlink:href="#linearGradient3792"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0256411,0,0,1.0256411,0.88461522,0.8846152)" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect
|
||||
width="8"
|
||||
height="8"
|
||||
rx="1"
|
||||
ry="1"
|
||||
x="1.5"
|
||||
y="1.5"
|
||||
id="rect3022"
|
||||
style="fill:url(#linearGradient2996);fill-opacity:1;stroke:#7898b5;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<rect
|
||||
width="5"
|
||||
height="1"
|
||||
x="3"
|
||||
y="5"
|
||||
id="rect3801"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" />
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.5 KiB |
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче