зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to s-c.
This commit is contained in:
Коммит
f6dfd7b2d3
2
CLOBBER
2
CLOBBER
|
@ -17,4 +17,4 @@
|
||||||
#
|
#
|
||||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||||
#
|
#
|
||||||
Bug 856349 broke Windows b2g builds.
|
Bug 859894: Hopefully the final WebIDL clobber.
|
||||||
|
|
|
@ -102,7 +102,6 @@ pref("dom.disable_open_during_load", true);
|
||||||
pref("privacy.popups.showBrowserMessage", true);
|
pref("privacy.popups.showBrowserMessage", true);
|
||||||
|
|
||||||
pref("keyword.enabled", true);
|
pref("keyword.enabled", true);
|
||||||
pref("keyword.URL", "https://www.google.com/m?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=");
|
|
||||||
|
|
||||||
pref("accessibility.typeaheadfind", false);
|
pref("accessibility.typeaheadfind", false);
|
||||||
pref("accessibility.typeaheadfind.timeout", 5000);
|
pref("accessibility.typeaheadfind.timeout", 5000);
|
||||||
|
|
|
@ -102,7 +102,7 @@ textarea,
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: #7d7d7d;
|
border-color: #7d7d7d;
|
||||||
color: #414141;
|
color: #414141;
|
||||||
background: white -moz-linear-gradient(top, rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 3px, rgba(255,255,255,0.2) 16px);
|
background: white linear-gradient(rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 3px, rgba(255,255,255,0.2) 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Selects are handled by the form helper, see bug 685197 */
|
/* Selects are handled by the form helper, see bug 685197 */
|
||||||
|
@ -120,15 +120,15 @@ button {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: #7d7d7d;
|
border-color: #7d7d7d;
|
||||||
color: #414141;
|
color: #414141;
|
||||||
background: white -moz-linear-gradient(top, rgba(255,255,255,0.2) 0, rgba(215,215,215,0.5) 18px, rgba(115,115,115,0.5) 100%);
|
background: white linear-gradient(rgba(255,255,255,0.2) 0, rgba(215,215,215,0.5) 18px, rgba(115,115,115,0.5) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
background: white -moz-linear-gradient(top, rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 2px, rgba(255,255,255,0.2) 6px);
|
background: white linear-gradient(rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 2px, rgba(255,255,255,0.2) 6px);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"] {
|
input[type="radio"] {
|
||||||
background: -moz-radial-gradient(6px 6px, cover, rgba(255,255,255,0.2) 3px, rgba(195,195,195,0.5) 5px, rgba(115,115,115,0.5) 100%);
|
background: radial-gradient(at 6px 6px, rgba(255,255,255,0.2) 3px, rgba(195,195,195,0.5) 5px, rgba(115,115,115,0.5) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
@ -176,7 +176,7 @@ select > button {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
color: #414141;
|
color: #414141;
|
||||||
|
|
||||||
background-image: -moz-radial-gradient(bottom left, #bbbbbb 40%, #f5f5f5), url(arrow.svg) !important;
|
background-image: radial-gradient(at bottom left, #bbbbbb 40%, #f5f5f5), url(arrow.svg) !important;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
background-position: -15px center, 4px center !important;
|
background-position: -15px center, 4px center !important;
|
||||||
background-repeat: no-repeat, no-repeat !important;
|
background-repeat: no-repeat, no-repeat !important;
|
||||||
|
@ -196,7 +196,7 @@ input[type="file"]:focus > input[type="text"],
|
||||||
outline: 0px !important;
|
outline: 0px !important;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: rgb(94,128,153);
|
border-color: rgb(94,128,153);
|
||||||
background: white -moz-linear-gradient(top, rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 3px, rgba(255,255,255,0.2) 16px);
|
background: white linear-gradient(rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 3px, rgba(255,255,255,0.2) 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
select:not([size]):not([multiple]):focus,
|
select:not([size]):not([multiple]):focus,
|
||||||
|
@ -209,7 +209,7 @@ button:focus {
|
||||||
outline: 0px !important;
|
outline: 0px !important;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: rgb(94,128,153);
|
border-color: rgb(94,128,153);
|
||||||
background: white -moz-linear-gradient(top, rgba(255,255,255,0.2) 0, rgba(198,225,256,0.2) 18px, rgba(27,113,177,0.5) 100%);
|
background: white linear-gradient(rgba(255,255,255,0.2) 0, rgba(198,225,256,0.2) 18px, rgba(27,113,177,0.5) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:focus,
|
input[type="checkbox"]:focus,
|
||||||
|
@ -218,11 +218,11 @@ input[type="radio"]:focus {
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:focus {
|
input[type="checkbox"]:focus {
|
||||||
background: white -moz-linear-gradient(top, rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 2px, rgba(255,255,255,0.2) 6px);
|
background: white linear-gradient(rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 2px, rgba(255,255,255,0.2) 6px);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:focus {
|
input[type="radio"]:focus {
|
||||||
background: -moz-radial-gradient(6px 6px, cover, rgba(255,255,255,0.2) 3px, rgba(198,225,246,0.2) 5px, rgba(27,113,177,0.5) 100%);
|
background: radial-gradient(at 6px 6px, rgba(255,255,255,0.2) 3px, rgba(198,225,246,0.2) 5px, rgba(27,113,177,0.5) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we need to be specific for selects because the above rules are specific too */
|
/* we need to be specific for selects because the above rules are specific too */
|
||||||
|
@ -239,13 +239,13 @@ button[disabled],
|
||||||
border-color: rgba(125,125,125,0.4);
|
border-color: rgba(125,125,125,0.4);
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
background: transparent -moz-linear-gradient(top, rgba(185,185,185,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(255,255,255,0.4) 100%);
|
background: transparent linear-gradient(rgba(185,185,185,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(255,255,255,0.4) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
select:not([size]):not([multiple])[disabled],
|
select:not([size]):not([multiple])[disabled],
|
||||||
select[size="0"][disabled],
|
select[size="0"][disabled],
|
||||||
select[size="1"][disabled] {
|
select[size="1"][disabled] {
|
||||||
background: transparent -moz-linear-gradient(top, rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
|
background: transparent linear-gradient(rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="button"][disabled],
|
input[type="button"][disabled],
|
||||||
|
@ -253,7 +253,7 @@ input[type="submit"][disabled],
|
||||||
input[type="reset"][disabled],
|
input[type="reset"][disabled],
|
||||||
button[disabled="true"] {
|
button[disabled="true"] {
|
||||||
padding: 0 7px 0 7px;
|
padding: 0 7px 0 7px;
|
||||||
background: transparent -moz-linear-gradient(top, rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
|
background: transparent linear-gradient(rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"][disabled],
|
input[type="radio"][disabled],
|
||||||
|
|
|
@ -66,10 +66,6 @@ ifdef MOZ_LINKER
|
||||||
LIBS += $(MOZ_ZLIB_LIBS)
|
LIBS += $(MOZ_ZLIB_LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef HAVE_CLOCK_MONOTONIC
|
|
||||||
LIBS += $(REALTIME_LIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef MOZ_WINCONSOLE
|
ifndef MOZ_WINCONSOLE
|
||||||
ifdef MOZ_DEBUG
|
ifdef MOZ_DEBUG
|
||||||
MOZ_WINCONSOLE = 1
|
MOZ_WINCONSOLE = 1
|
||||||
|
|
|
@ -13,13 +13,12 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#elif defined(XP_UNIX)
|
#elif defined(XP_UNIX)
|
||||||
|
#include <sys/time.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
#include <mach/mach_time.h>
|
|
||||||
#include "MacQuirks.h"
|
#include "MacQuirks.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -389,80 +388,25 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
|
||||||
return 255;
|
return 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
/* Local implementation of PR_Now, since the executable can't depend on NSPR */
|
||||||
|
static PRTime _PR_Now()
|
||||||
/**
|
|
||||||
* Used only when GetTickCount64 is not available on the platform.
|
|
||||||
* Last result of GetTickCount call. Kept in [ms].
|
|
||||||
*/
|
|
||||||
static DWORD sLastGTCResult = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Higher part of the 64-bit value of MozGetTickCount64,
|
|
||||||
* incremented atomically.
|
|
||||||
*/
|
|
||||||
static DWORD sLastGTCRollover = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function protecting GetTickCount result from rolling over. The original
|
|
||||||
* code comes from the Windows implementation of the TimeStamp class minus the
|
|
||||||
* locking harness which isn't needed here.
|
|
||||||
*
|
|
||||||
* @returns The current time in milliseconds
|
|
||||||
*/
|
|
||||||
static ULONGLONG WINAPI
|
|
||||||
MozGetTickCount64()
|
|
||||||
{
|
{
|
||||||
DWORD GTC = ::GetTickCount();
|
#ifdef XP_WIN
|
||||||
|
MOZ_STATIC_ASSERT(sizeof(PRTime) == sizeof(FILETIME), "PRTime must have the same size as FILETIME");
|
||||||
/* Pull the rollover counter forward only if new value of GTC goes way
|
FILETIME ft;
|
||||||
* down under the last saved result */
|
GetSystemTimeAsFileTime(&ft);
|
||||||
if ((sLastGTCResult > GTC) && ((sLastGTCResult - GTC) > (1UL << 30)))
|
PRTime now;
|
||||||
++sLastGTCRollover;
|
CopyMemory(&now, &ft, sizeof(PRTime));
|
||||||
|
#ifdef __GNUC__
|
||||||
sLastGTCResult = GTC;
|
return (now - 116444736000000000LL) / 10LL;
|
||||||
return (ULONGLONG)sLastGTCRollover << 32 | sLastGTCResult;
|
#else
|
||||||
}
|
return (now - 116444736000000000i64) / 10i64;
|
||||||
|
|
||||||
typedef ULONGLONG (WINAPI* GetTickCount64_t)();
|
|
||||||
static GetTickCount64_t sGetTickCount64 = nullptr;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
#else
|
||||||
* Local TimeStamp::Now()-compatible implementation used to record timestamps
|
struct timeval tm;
|
||||||
* which will be passed to XRE_StartupTimelineRecord().
|
gettimeofday(&tm, 0);
|
||||||
*/
|
return (((PRTime)tm.tv_sec * 1000000LL) + (PRTime)tm.tv_usec);
|
||||||
static uint64_t
|
|
||||||
TimeStamp_Now()
|
|
||||||
{
|
|
||||||
#ifdef XP_WIN
|
|
||||||
LARGE_INTEGER freq;
|
|
||||||
::QueryPerformanceFrequency(&freq);
|
|
||||||
|
|
||||||
HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll");
|
|
||||||
sGetTickCount64 = reinterpret_cast<GetTickCount64_t>
|
|
||||||
(GetProcAddress(kernelDLL, "GetTickCount64"));
|
|
||||||
|
|
||||||
if (!sGetTickCount64) {
|
|
||||||
/* If the platform does not support the GetTickCount64 (Windows XP doesn't),
|
|
||||||
* then use our fallback implementation based on GetTickCount. */
|
|
||||||
sGetTickCount64 = MozGetTickCount64;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sGetTickCount64() * freq.QuadPart;
|
|
||||||
#elif defined(XP_MACOSX)
|
|
||||||
return mach_absolute_time();
|
|
||||||
#elif defined(HAVE_CLOCK_MONOTONIC)
|
|
||||||
struct timespec ts;
|
|
||||||
int rv = clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
||||||
|
|
||||||
if (rv != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000;
|
|
||||||
return baseNs + (uint64_t)ts.tv_nsec;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +528,7 @@ int main(int argc, char* argv[])
|
||||||
#ifdef DEBUG_delay_start_metro
|
#ifdef DEBUG_delay_start_metro
|
||||||
Sleep(5000);
|
Sleep(5000);
|
||||||
#endif
|
#endif
|
||||||
uint64_t start = TimeStamp_Now();
|
PRTime start = _PR_Now();
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
TriggerQuirks();
|
TriggerQuirks();
|
||||||
|
|
|
@ -210,9 +210,6 @@ pref("xpinstall.whitelist.add.180", "marketplace.firefox.com");
|
||||||
pref("lightweightThemes.update.enabled", true);
|
pref("lightweightThemes.update.enabled", true);
|
||||||
|
|
||||||
pref("keyword.enabled", true);
|
pref("keyword.enabled", true);
|
||||||
// Override the default keyword.URL. Empty value means
|
|
||||||
// "use the search service's default engine"
|
|
||||||
pref("keyword.URL", "");
|
|
||||||
|
|
||||||
pref("general.useragent.locale", "@AB_CD@");
|
pref("general.useragent.locale", "@AB_CD@");
|
||||||
pref("general.skins.selectedSkin", "classic/1.0");
|
pref("general.skins.selectedSkin", "classic/1.0");
|
||||||
|
@ -540,6 +537,8 @@ pref("browser.gesture.twist.left", "cmd_gestureRotateLeft");
|
||||||
pref("browser.gesture.twist.end", "cmd_gestureRotateEnd");
|
pref("browser.gesture.twist.end", "cmd_gestureRotateEnd");
|
||||||
pref("browser.gesture.tap", "cmd_fullZoomReset");
|
pref("browser.gesture.tap", "cmd_fullZoomReset");
|
||||||
|
|
||||||
|
pref("browser.snapshots.limit", 0);
|
||||||
|
|
||||||
// 0: Nothing happens
|
// 0: Nothing happens
|
||||||
// 1: Scrolling contents
|
// 1: Scrolling contents
|
||||||
// 2: Go back or go forward, in your history
|
// 2: Go back or go forward, in your history
|
||||||
|
|
|
@ -256,19 +256,6 @@ function onSearchSubmit(aEvent)
|
||||||
|
|
||||||
function setupSearchEngine()
|
function setupSearchEngine()
|
||||||
{
|
{
|
||||||
let searchEngineName = document.documentElement.getAttribute("searchEngineName");
|
|
||||||
let searchEngineInfo = SEARCH_ENGINES[searchEngineName];
|
|
||||||
if (!searchEngineInfo) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add search engine logo.
|
|
||||||
if (searchEngineInfo.image) {
|
|
||||||
let logoElt = document.getElementById("searchEngineLogo");
|
|
||||||
logoElt.src = searchEngineInfo.image;
|
|
||||||
logoElt.alt = searchEngineName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The "autofocus" attribute doesn't focus the form element
|
// The "autofocus" attribute doesn't focus the form element
|
||||||
// immediately when the element is first drawn, so the
|
// immediately when the element is first drawn, so the
|
||||||
// attribute is also used for styling when the page first loads.
|
// attribute is also used for styling when the page first loads.
|
||||||
|
@ -278,6 +265,26 @@ function setupSearchEngine()
|
||||||
searchText.removeAttribute("autofocus");
|
searchText.removeAttribute("autofocus");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let searchEngineName = document.documentElement.getAttribute("searchEngineName");
|
||||||
|
let searchEngineInfo = SEARCH_ENGINES[searchEngineName];
|
||||||
|
let logoElt = document.getElementById("searchEngineLogo");
|
||||||
|
|
||||||
|
// Add search engine logo.
|
||||||
|
if (searchEngineInfo && searchEngineInfo.image) {
|
||||||
|
logoElt.parentNode.hidden = false;
|
||||||
|
logoElt.src = searchEngineInfo.image;
|
||||||
|
#ifdef XP_MACOSX
|
||||||
|
if (searchEngineInfo.imageHD && !window.matchMedia("(max-resolution: 1dppx)").matches)
|
||||||
|
logoElt.src = searchEngineInfo.imageHD;
|
||||||
|
#endif
|
||||||
|
logoElt.alt = searchEngineName;
|
||||||
|
searchText.placeholder = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logoElt.parentNode.hidden = true;
|
||||||
|
searchText.placeholder = searchEngineName;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -149,6 +149,8 @@
|
||||||
observes="devtoolsMenuBroadcaster_DevToolbar"/>
|
observes="devtoolsMenuBroadcaster_DevToolbar"/>
|
||||||
<menuitem id="appmenu_chromeDebugger"
|
<menuitem id="appmenu_chromeDebugger"
|
||||||
observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
|
observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
|
||||||
|
<menuitem id="appmenu_browserConsole"
|
||||||
|
observes="devtoolsMenuBroadcaster_BrowserConsole"/>
|
||||||
<menuitem id="appmenu_responsiveUI"
|
<menuitem id="appmenu_responsiveUI"
|
||||||
observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
|
observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
|
||||||
<menuitem id="appmenu_scratchpad"
|
<menuitem id="appmenu_scratchpad"
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -576,6 +576,8 @@
|
||||||
accesskey="&devToolbarMenu.accesskey;"/>
|
accesskey="&devToolbarMenu.accesskey;"/>
|
||||||
<menuitem id="menu_chromeDebugger"
|
<menuitem id="menu_chromeDebugger"
|
||||||
observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
|
observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
|
||||||
|
<menuitem id="menu_browserConsole"
|
||||||
|
observes="devtoolsMenuBroadcaster_BrowserConsole"/>
|
||||||
<menuitem id="menu_responsiveUI"
|
<menuitem id="menu_responsiveUI"
|
||||||
observes="devtoolsMenuBroadcaster_ResponsiveUI"
|
observes="devtoolsMenuBroadcaster_ResponsiveUI"
|
||||||
accesskey="&responsiveDesignTool.accesskey;"/>
|
accesskey="&responsiveDesignTool.accesskey;"/>
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
|
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
|
||||||
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/>
|
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/>
|
||||||
<command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true" hidden="true"/>
|
<command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true" hidden="true"/>
|
||||||
|
<command id="Tools:BrowserConsole" oncommand="HUDConsoleUI.toggleBrowserConsole();" disabled="true" hidden="true"/>
|
||||||
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true" hidden="true"/>
|
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true" hidden="true"/>
|
||||||
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
|
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
|
||||||
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
|
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
|
||||||
|
@ -184,6 +185,9 @@
|
||||||
<broadcaster id="devtoolsMenuBroadcaster_ChromeDebugger"
|
<broadcaster id="devtoolsMenuBroadcaster_ChromeDebugger"
|
||||||
label="&chromeDebuggerMenu.label;"
|
label="&chromeDebuggerMenu.label;"
|
||||||
command="Tools:ChromeDebugger"/>
|
command="Tools:ChromeDebugger"/>
|
||||||
|
<broadcaster id="devtoolsMenuBroadcaster_BrowserConsole"
|
||||||
|
label="&browserConsoleCmd.label;"
|
||||||
|
command="Tools:BrowserConsole"/>
|
||||||
<broadcaster id="devtoolsMenuBroadcaster_Scratchpad"
|
<broadcaster id="devtoolsMenuBroadcaster_Scratchpad"
|
||||||
label="&scratchpad.label;"
|
label="&scratchpad.label;"
|
||||||
command="Tools:Scratchpad"
|
command="Tools:Scratchpad"
|
||||||
|
|
|
@ -358,6 +358,30 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||||
}
|
}
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
/* History Swipe Animation */
|
||||||
|
|
||||||
|
#historySwipeAnimationContainer {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#historySwipeAnimationPreviousPage,
|
||||||
|
#historySwipeAnimationCurrentPage,
|
||||||
|
#historySwipeAnimationNextPage {
|
||||||
|
background: none top left no-repeat white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#historySwipeAnimationPreviousPage {
|
||||||
|
background-image: -moz-element(#historySwipeAnimationPreviousPageSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
#historySwipeAnimationCurrentPage {
|
||||||
|
background-image: -moz-element(#historySwipeAnimationCurrentPageSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
#historySwipeAnimationNextPage {
|
||||||
|
background-image: -moz-element(#historySwipeAnimationNextPageSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
/* Identity UI */
|
/* Identity UI */
|
||||||
#identity-popup-content-box.unknownIdentity > #identity-popup-connectedToLabel ,
|
#identity-popup-content-box.unknownIdentity > #identity-popup-connectedToLabel ,
|
||||||
#identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel ,
|
#identity-popup-content-box.unknownIdentity > #identity-popup-runByLabel ,
|
||||||
|
|
|
@ -157,6 +157,7 @@ let gInitialPages = [
|
||||||
#include browser-tabview.js
|
#include browser-tabview.js
|
||||||
#include browser-thumbnails.js
|
#include browser-thumbnails.js
|
||||||
#include browser-webrtcUI.js
|
#include browser-webrtcUI.js
|
||||||
|
#include browser-gestureSupport.js
|
||||||
|
|
||||||
#ifdef MOZ_DATA_REPORTING
|
#ifdef MOZ_DATA_REPORTING
|
||||||
#include browser-data-submission-info-bar.js
|
#include browser-data-submission-info-bar.js
|
||||||
|
@ -724,396 +725,6 @@ const gFormSubmitObserver = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Simple gestures support
|
|
||||||
//
|
|
||||||
// As per bug #412486, web content must not be allowed to receive any
|
|
||||||
// simple gesture events. Multi-touch gesture APIs are in their
|
|
||||||
// infancy and we do NOT want to be forced into supporting an API that
|
|
||||||
// will probably have to change in the future. (The current Mac OS X
|
|
||||||
// API is undocumented and was reverse-engineered.) Until support is
|
|
||||||
// implemented in the event dispatcher to keep these events as
|
|
||||||
// chrome-only, we must listen for the simple gesture events during
|
|
||||||
// the capturing phase and call stopPropagation on every event.
|
|
||||||
|
|
||||||
let gGestureSupport = {
|
|
||||||
_currentRotation: 0,
|
|
||||||
_lastRotateDelta: 0,
|
|
||||||
_rotateMomentumThreshold: .75,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add or remove mouse gesture event listeners
|
|
||||||
*
|
|
||||||
* @param aAddListener
|
|
||||||
* True to add/init listeners and false to remove/uninit
|
|
||||||
*/
|
|
||||||
init: function GS_init(aAddListener) {
|
|
||||||
const gestureEvents = ["SwipeGesture",
|
|
||||||
"MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture",
|
|
||||||
"RotateGestureStart", "RotateGestureUpdate", "RotateGesture",
|
|
||||||
"TapGesture", "PressTapGesture"];
|
|
||||||
|
|
||||||
let addRemove = aAddListener ? window.addEventListener :
|
|
||||||
window.removeEventListener;
|
|
||||||
|
|
||||||
gestureEvents.forEach(function (event) addRemove("Moz" + event, this, true),
|
|
||||||
this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatch events based on the type of mouse gesture event. For now, make
|
|
||||||
* sure to stop propagation of every gesture event so that web content cannot
|
|
||||||
* receive gesture events.
|
|
||||||
*
|
|
||||||
* @param aEvent
|
|
||||||
* The gesture event to handle
|
|
||||||
*/
|
|
||||||
handleEvent: function GS_handleEvent(aEvent) {
|
|
||||||
if (!Services.prefs.getBoolPref(
|
|
||||||
"dom.debug.propagate_gesture_events_through_content")) {
|
|
||||||
aEvent.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a preference object with some defaults
|
|
||||||
let def = function(aThreshold, aLatched)
|
|
||||||
({ threshold: aThreshold, latched: !!aLatched });
|
|
||||||
|
|
||||||
switch (aEvent.type) {
|
|
||||||
case "MozSwipeGesture":
|
|
||||||
aEvent.preventDefault();
|
|
||||||
this.onSwipe(aEvent);
|
|
||||||
break;
|
|
||||||
case "MozMagnifyGestureStart":
|
|
||||||
aEvent.preventDefault();
|
|
||||||
#ifdef XP_WIN
|
|
||||||
this._setupGesture(aEvent, "pinch", def(25, 0), "out", "in");
|
|
||||||
#else
|
|
||||||
this._setupGesture(aEvent, "pinch", def(150, 1), "out", "in");
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case "MozRotateGestureStart":
|
|
||||||
aEvent.preventDefault();
|
|
||||||
this._setupGesture(aEvent, "twist", def(25, 0), "right", "left");
|
|
||||||
break;
|
|
||||||
case "MozMagnifyGestureUpdate":
|
|
||||||
case "MozRotateGestureUpdate":
|
|
||||||
aEvent.preventDefault();
|
|
||||||
this._doUpdate(aEvent);
|
|
||||||
break;
|
|
||||||
case "MozTapGesture":
|
|
||||||
aEvent.preventDefault();
|
|
||||||
this._doAction(aEvent, ["tap"]);
|
|
||||||
break;
|
|
||||||
case "MozRotateGesture":
|
|
||||||
aEvent.preventDefault();
|
|
||||||
this._doAction(aEvent, ["twist", "end"]);
|
|
||||||
break;
|
|
||||||
/* case "MozPressTapGesture":
|
|
||||||
break; */
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called at the start of "pinch" and "twist" gestures to setup all of the
|
|
||||||
* information needed to process the gesture
|
|
||||||
*
|
|
||||||
* @param aEvent
|
|
||||||
* The continual motion start event to handle
|
|
||||||
* @param aGesture
|
|
||||||
* Name of the gesture to handle
|
|
||||||
* @param aPref
|
|
||||||
* Preference object with the names of preferences and defaults
|
|
||||||
* @param aInc
|
|
||||||
* Command to trigger for increasing motion (without gesture name)
|
|
||||||
* @param aDec
|
|
||||||
* Command to trigger for decreasing motion (without gesture name)
|
|
||||||
*/
|
|
||||||
_setupGesture: function GS__setupGesture(aEvent, aGesture, aPref, aInc, aDec) {
|
|
||||||
// Try to load user-set values from preferences
|
|
||||||
for (let [pref, def] in Iterator(aPref))
|
|
||||||
aPref[pref] = this._getPref(aGesture + "." + pref, def);
|
|
||||||
|
|
||||||
// Keep track of the total deltas and latching behavior
|
|
||||||
let offset = 0;
|
|
||||||
let latchDir = aEvent.delta > 0 ? 1 : -1;
|
|
||||||
let isLatched = false;
|
|
||||||
|
|
||||||
// Create the update function here to capture closure state
|
|
||||||
this._doUpdate = function GS__doUpdate(aEvent) {
|
|
||||||
// Update the offset with new event data
|
|
||||||
offset += aEvent.delta;
|
|
||||||
|
|
||||||
// Check if the cumulative deltas exceed the threshold
|
|
||||||
if (Math.abs(offset) > aPref["threshold"]) {
|
|
||||||
// Trigger the action if we don't care about latching; otherwise, make
|
|
||||||
// sure either we're not latched and going the same direction of the
|
|
||||||
// initial motion; or we're latched and going the opposite way
|
|
||||||
let sameDir = (latchDir ^ offset) >= 0;
|
|
||||||
if (!aPref["latched"] || (isLatched ^ sameDir)) {
|
|
||||||
this._doAction(aEvent, [aGesture, offset > 0 ? aInc : aDec]);
|
|
||||||
|
|
||||||
// We must be getting latched or leaving it, so just toggle
|
|
||||||
isLatched = !isLatched;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset motion counter to prepare for more of the same gesture
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The start event also contains deltas, so handle an update right away
|
|
||||||
this._doUpdate(aEvent);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generator producing the powerset of the input array where the first result
|
|
||||||
* is the complete set and the last result (before StopIteration) is empty.
|
|
||||||
*
|
|
||||||
* @param aArray
|
|
||||||
* Source array containing any number of elements
|
|
||||||
* @yield Array that is a subset of the input array from full set to empty
|
|
||||||
*/
|
|
||||||
_power: function GS__power(aArray) {
|
|
||||||
// Create a bitmask based on the length of the array
|
|
||||||
let num = 1 << aArray.length;
|
|
||||||
while (--num >= 0) {
|
|
||||||
// Only select array elements where the current bit is set
|
|
||||||
yield aArray.reduce(function (aPrev, aCurr, aIndex) {
|
|
||||||
if (num & 1 << aIndex)
|
|
||||||
aPrev.push(aCurr);
|
|
||||||
return aPrev;
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine what action to do for the gesture based on which keys are
|
|
||||||
* pressed and which commands are set
|
|
||||||
*
|
|
||||||
* @param aEvent
|
|
||||||
* The original gesture event to convert into a fake click event
|
|
||||||
* @param aGesture
|
|
||||||
* Array of gesture name parts (to be joined by periods)
|
|
||||||
*/
|
|
||||||
_doAction: function GS__doAction(aEvent, aGesture) {
|
|
||||||
// Create an array of pressed keys in a fixed order so that a command for
|
|
||||||
// "meta" is preferred over "ctrl" when both buttons are pressed (and a
|
|
||||||
// command for both don't exist)
|
|
||||||
let keyCombos = [];
|
|
||||||
["shift", "alt", "ctrl", "meta"].forEach(function (key) {
|
|
||||||
if (aEvent[key + "Key"])
|
|
||||||
keyCombos.push(key);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Try each combination of key presses in decreasing order for commands
|
|
||||||
for (let subCombo of this._power(keyCombos)) {
|
|
||||||
// Convert a gesture and pressed keys into the corresponding command
|
|
||||||
// action where the preference has the gesture before "shift" before
|
|
||||||
// "alt" before "ctrl" before "meta" all separated by periods
|
|
||||||
let command;
|
|
||||||
try {
|
|
||||||
command = this._getPref(aGesture.concat(subCombo).join("."));
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
if (!command)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let node = document.getElementById(command);
|
|
||||||
if (node) {
|
|
||||||
if (node.getAttribute("disabled") != "true") {
|
|
||||||
let cmdEvent = document.createEvent("xulcommandevent");
|
|
||||||
cmdEvent.initCommandEvent("command", true, true, window, 0,
|
|
||||||
aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey,
|
|
||||||
aEvent.metaKey, aEvent);
|
|
||||||
node.dispatchEvent(cmdEvent);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goDoCommand(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert continual motion events into an action if it exceeds a threshold
|
|
||||||
* in a given direction. This function will be set by _setupGesture to
|
|
||||||
* capture state that needs to be shared across multiple gesture updates.
|
|
||||||
*
|
|
||||||
* @param aEvent
|
|
||||||
* The continual motion update event to handle
|
|
||||||
*/
|
|
||||||
_doUpdate: function(aEvent) {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the swipe gesture into a browser action based on the direction
|
|
||||||
*
|
|
||||||
* @param aEvent
|
|
||||||
* The swipe event to handle
|
|
||||||
*/
|
|
||||||
onSwipe: function GS_onSwipe(aEvent) {
|
|
||||||
// Figure out which one (and only one) direction was triggered
|
|
||||||
for (let dir of ["UP", "RIGHT", "DOWN", "LEFT"]) {
|
|
||||||
if (aEvent.direction == aEvent["DIRECTION_" + dir]) {
|
|
||||||
this._doAction(aEvent, ["swipe", dir.toLowerCase()]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a gesture preference or use a default if it doesn't exist
|
|
||||||
*
|
|
||||||
* @param aPref
|
|
||||||
* Name of the preference to load under the gesture branch
|
|
||||||
* @param aDef
|
|
||||||
* Default value if the preference doesn't exist
|
|
||||||
*/
|
|
||||||
_getPref: function GS__getPref(aPref, aDef) {
|
|
||||||
// Preferences branch under which all gestures preferences are stored
|
|
||||||
const branch = "browser.gesture.";
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Determine what type of data to load based on default value's type
|
|
||||||
let type = typeof aDef;
|
|
||||||
let getFunc = "get" + (type == "boolean" ? "Bool" :
|
|
||||||
type == "number" ? "Int" : "Char") + "Pref";
|
|
||||||
return gPrefService[getFunc](branch + aPref);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return aDef;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform rotation for ImageDocuments
|
|
||||||
*
|
|
||||||
* @param aEvent
|
|
||||||
* The MozRotateGestureUpdate event triggering this call
|
|
||||||
*/
|
|
||||||
rotate: function(aEvent) {
|
|
||||||
if (!(content.document instanceof ImageDocument))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let contentElement = content.document.body.firstElementChild;
|
|
||||||
if (!contentElement)
|
|
||||||
return;
|
|
||||||
// If we're currently snapping, cancel that snap
|
|
||||||
if (contentElement.classList.contains("completeRotation"))
|
|
||||||
this._clearCompleteRotation();
|
|
||||||
|
|
||||||
this.rotation = Math.round(this.rotation + aEvent.delta);
|
|
||||||
contentElement.style.transform = "rotate(" + this.rotation + "deg)";
|
|
||||||
this._lastRotateDelta = aEvent.delta;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a rotation end for ImageDocuments
|
|
||||||
*/
|
|
||||||
rotateEnd: function() {
|
|
||||||
if (!(content.document instanceof ImageDocument))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let contentElement = content.document.body.firstElementChild;
|
|
||||||
if (!contentElement)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let transitionRotation = 0;
|
|
||||||
|
|
||||||
// The reason that 360 is allowed here is because when rotating between
|
|
||||||
// 315 and 360, setting rotate(0deg) will cause it to rotate the wrong
|
|
||||||
// direction around--spinning wildly.
|
|
||||||
if (this.rotation <= 45)
|
|
||||||
transitionRotation = 0;
|
|
||||||
else if (this.rotation > 45 && this.rotation <= 135)
|
|
||||||
transitionRotation = 90;
|
|
||||||
else if (this.rotation > 135 && this.rotation <= 225)
|
|
||||||
transitionRotation = 180;
|
|
||||||
else if (this.rotation > 225 && this.rotation <= 315)
|
|
||||||
transitionRotation = 270;
|
|
||||||
else
|
|
||||||
transitionRotation = 360;
|
|
||||||
|
|
||||||
// If we're going fast enough, and we didn't already snap ahead of rotation,
|
|
||||||
// then snap ahead of rotation to simulate momentum
|
|
||||||
if (this._lastRotateDelta > this._rotateMomentumThreshold &&
|
|
||||||
this.rotation > transitionRotation)
|
|
||||||
transitionRotation += 90;
|
|
||||||
else if (this._lastRotateDelta < -1 * this._rotateMomentumThreshold &&
|
|
||||||
this.rotation < transitionRotation)
|
|
||||||
transitionRotation -= 90;
|
|
||||||
|
|
||||||
// Only add the completeRotation class if it is is necessary
|
|
||||||
if (transitionRotation != this.rotation) {
|
|
||||||
contentElement.classList.add("completeRotation");
|
|
||||||
contentElement.addEventListener("transitionend", this._clearCompleteRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
contentElement.style.transform = "rotate(" + transitionRotation + "deg)";
|
|
||||||
this.rotation = transitionRotation;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current rotation for the ImageDocument
|
|
||||||
*/
|
|
||||||
get rotation() {
|
|
||||||
return this._currentRotation;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current rotation for the ImageDocument
|
|
||||||
*
|
|
||||||
* @param aVal
|
|
||||||
* The new value to take. Can be any value, but it will be bounded to
|
|
||||||
* 0 inclusive to 360 exclusive.
|
|
||||||
*/
|
|
||||||
set rotation(aVal) {
|
|
||||||
this._currentRotation = aVal % 360;
|
|
||||||
if (this._currentRotation < 0)
|
|
||||||
this._currentRotation += 360;
|
|
||||||
return this._currentRotation;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When the location/tab changes, need to reload the current rotation for the
|
|
||||||
* image
|
|
||||||
*/
|
|
||||||
restoreRotationState: function() {
|
|
||||||
if (!(content.document instanceof ImageDocument))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let contentElement = content.document.body.firstElementChild;
|
|
||||||
let transformValue = content.window.getComputedStyle(contentElement, null)
|
|
||||||
.transform;
|
|
||||||
|
|
||||||
if (transformValue == "none") {
|
|
||||||
this.rotation = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// transformValue is a rotation matrix--split it and do mathemagic to
|
|
||||||
// obtain the real rotation value
|
|
||||||
transformValue = transformValue.split("(")[1]
|
|
||||||
.split(")")[0]
|
|
||||||
.split(",");
|
|
||||||
this.rotation = Math.round(Math.atan2(transformValue[1], transformValue[0]) *
|
|
||||||
(180 / Math.PI));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the transition rule by removing the completeRotation class
|
|
||||||
*/
|
|
||||||
_clearCompleteRotation: function() {
|
|
||||||
let contentElement = content.document &&
|
|
||||||
content.document instanceof ImageDocument &&
|
|
||||||
content.document.body &&
|
|
||||||
content.document.body.firstElementChild;
|
|
||||||
if (!contentElement)
|
|
||||||
return;
|
|
||||||
contentElement.classList.remove("completeRotation");
|
|
||||||
contentElement.removeEventListener("transitionend", this._clearCompleteRotation);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var gBrowserInit = {
|
var gBrowserInit = {
|
||||||
onLoad: function() {
|
onLoad: function() {
|
||||||
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
|
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
|
||||||
|
@ -1212,6 +823,9 @@ var gBrowserInit = {
|
||||||
// setup simple gestures support
|
// setup simple gestures support
|
||||||
gGestureSupport.init(true);
|
gGestureSupport.init(true);
|
||||||
|
|
||||||
|
// setup history swipe animation
|
||||||
|
gHistorySwipeAnimation.init();
|
||||||
|
|
||||||
if (window.opener && !window.opener.closed) {
|
if (window.opener && !window.opener.closed) {
|
||||||
let openerSidebarBox = window.opener.document.getElementById("sidebar-box");
|
let openerSidebarBox = window.opener.document.getElementById("sidebar-box");
|
||||||
// If the opener had a sidebar, open the same sidebar in our window.
|
// If the opener had a sidebar, open the same sidebar in our window.
|
||||||
|
@ -1571,19 +1185,27 @@ var gBrowserInit = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable Chrome Debugger?
|
// Enable Chrome Debugger?
|
||||||
let enabled = gPrefService.getBoolPref("devtools.chrome.enabled") &&
|
let chromeEnabled = gPrefService.getBoolPref("devtools.chrome.enabled");
|
||||||
gPrefService.getBoolPref("devtools.debugger.chrome-enabled") &&
|
let remoteEnabled = chromeEnabled &&
|
||||||
gPrefService.getBoolPref("devtools.debugger.remote-enabled");
|
gPrefService.getBoolPref("devtools.debugger.chrome-enabled") &&
|
||||||
if (enabled) {
|
gPrefService.getBoolPref("devtools.debugger.remote-enabled");
|
||||||
|
if (remoteEnabled) {
|
||||||
let cmd = document.getElementById("Tools:ChromeDebugger");
|
let cmd = document.getElementById("Tools:ChromeDebugger");
|
||||||
cmd.removeAttribute("disabled");
|
cmd.removeAttribute("disabled");
|
||||||
cmd.removeAttribute("hidden");
|
cmd.removeAttribute("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable the Browser Console?
|
||||||
|
if (chromeEnabled) {
|
||||||
|
let cmd = document.getElementById("Tools:BrowserConsole");
|
||||||
|
cmd.removeAttribute("disabled");
|
||||||
|
cmd.removeAttribute("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
// Enable Error Console?
|
// Enable Error Console?
|
||||||
// Temporarily enabled. See bug 798925.
|
// Temporarily enabled. See bug 798925.
|
||||||
let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled") ||
|
let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled") ||
|
||||||
gPrefService.getBoolPref("devtools.chrome.enabled");
|
chromeEnabled;
|
||||||
if (consoleEnabled) {
|
if (consoleEnabled) {
|
||||||
let cmd = document.getElementById("Tools:ErrorConsole");
|
let cmd = document.getElementById("Tools:ErrorConsole");
|
||||||
cmd.removeAttribute("disabled");
|
cmd.removeAttribute("disabled");
|
||||||
|
@ -1681,6 +1303,8 @@ var gBrowserInit = {
|
||||||
|
|
||||||
gGestureSupport.init(false);
|
gGestureSupport.init(false);
|
||||||
|
|
||||||
|
gHistorySwipeAnimation.uninit();
|
||||||
|
|
||||||
FullScreen.cleanup();
|
FullScreen.cleanup();
|
||||||
|
|
||||||
Services.obs.removeObserver(gPluginHandler.pluginCrashed, "plugin-crashed");
|
Services.obs.removeObserver(gPluginHandler.pluginCrashed, "plugin-crashed");
|
||||||
|
@ -1807,6 +1431,10 @@ var gBrowserInit = {
|
||||||
|
|
||||||
SocialUI.nonBrowserWindowInit();
|
SocialUI.nonBrowserWindowInit();
|
||||||
|
|
||||||
|
if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||||
|
document.getElementById("macDockMenuNewWindow").hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
this._delayedStartupTimeoutId = setTimeout(this.nonBrowserWindowDelayedStartup.bind(this), 0);
|
this._delayedStartupTimeoutId = setTimeout(this.nonBrowserWindowDelayedStartup.bind(this), 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1896,7 +1524,6 @@ var nonBrowserWindowDelayedStartup = gBrowserInit.nonBrowserWindowDelayedStartup
|
||||||
var nonBrowserWindowShutdown = gBrowserInit.nonBrowserWindowShutdown.bind(gBrowserInit);
|
var nonBrowserWindowShutdown = gBrowserInit.nonBrowserWindowShutdown.bind(gBrowserInit);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
function HandleAppCommandEvent(evt) {
|
function HandleAppCommandEvent(evt) {
|
||||||
switch (evt.command) {
|
switch (evt.command) {
|
||||||
case "Back":
|
case "Back":
|
||||||
|
|
|
@ -191,8 +191,8 @@
|
||||||
<hbox pack="start" align="center" class="popup-notification-button-container">
|
<hbox pack="start" align="center" class="popup-notification-button-container">
|
||||||
<label id="social-undoactivation-button"
|
<label id="social-undoactivation-button"
|
||||||
class="text-link"
|
class="text-link"
|
||||||
value="&social.activated.undobutton.label;"
|
value="&social.activated.undo.label;"
|
||||||
accesskey="&social.activated.undobutton.accesskey;"
|
accesskey="&social.activated.undo.accesskey;"
|
||||||
onclick="SocialUI.undoActivation(this);"/>
|
onclick="SocialUI.undoActivation(this);"/>
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
<button id="social-activation-button"
|
<button id="social-activation-button"
|
||||||
|
|
|
@ -55,7 +55,8 @@
|
||||||
<menupopup id="menu_mac_dockmenu">
|
<menupopup id="menu_mac_dockmenu">
|
||||||
<!-- The command cannot be cmd_newNavigator because we need to activate
|
<!-- The command cannot be cmd_newNavigator because we need to activate
|
||||||
the application. -->
|
the application. -->
|
||||||
<menuitem label="&newNavigatorCmd.label;" oncommand="OpenBrowserWindowFromDockMenu();" />
|
<menuitem label="&newNavigatorCmd.label;" oncommand="OpenBrowserWindowFromDockMenu();"
|
||||||
|
id="macDockMenuNewWindow" />
|
||||||
<menuitem label="&newPrivateWindow.label;" oncommand="OpenBrowserWindowFromDockMenu({private: true});" />
|
<menuitem label="&newPrivateWindow.label;" oncommand="OpenBrowserWindowFromDockMenu({private: true});" />
|
||||||
</menupopup>
|
</menupopup>
|
||||||
</popupset>
|
</popupset>
|
||||||
|
|
|
@ -310,10 +310,8 @@ function onLoadPageInfo()
|
||||||
gStrings.mediaEmbed = gBundle.getString("mediaEmbed");
|
gStrings.mediaEmbed = gBundle.getString("mediaEmbed");
|
||||||
gStrings.mediaLink = gBundle.getString("mediaLink");
|
gStrings.mediaLink = gBundle.getString("mediaLink");
|
||||||
gStrings.mediaInput = gBundle.getString("mediaInput");
|
gStrings.mediaInput = gBundle.getString("mediaInput");
|
||||||
#ifdef MOZ_MEDIA
|
|
||||||
gStrings.mediaVideo = gBundle.getString("mediaVideo");
|
gStrings.mediaVideo = gBundle.getString("mediaVideo");
|
||||||
gStrings.mediaAudio = gBundle.getString("mediaAudio");
|
gStrings.mediaAudio = gBundle.getString("mediaAudio");
|
||||||
#endif
|
|
||||||
|
|
||||||
var args = "arguments" in window &&
|
var args = "arguments" in window &&
|
||||||
window.arguments.length >= 1 &&
|
window.arguments.length >= 1 &&
|
||||||
|
@ -677,14 +675,12 @@ function grabAll(elem)
|
||||||
addImage(href, gStrings.mediaImg, "", elem, false);
|
addImage(href, gStrings.mediaImg, "", elem, false);
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
#ifdef MOZ_MEDIA
|
|
||||||
else if (elem instanceof HTMLVideoElement) {
|
else if (elem instanceof HTMLVideoElement) {
|
||||||
addImage(elem.currentSrc, gStrings.mediaVideo, "", elem, false);
|
addImage(elem.currentSrc, gStrings.mediaVideo, "", elem, false);
|
||||||
}
|
}
|
||||||
else if (elem instanceof HTMLAudioElement) {
|
else if (elem instanceof HTMLAudioElement) {
|
||||||
addImage(elem.currentSrc, gStrings.mediaAudio, "", elem, false);
|
addImage(elem.currentSrc, gStrings.mediaAudio, "", elem, false);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else if (elem instanceof HTMLLinkElement) {
|
else if (elem instanceof HTMLLinkElement) {
|
||||||
if (elem.rel && /\bicon\b/i.test(elem.rel))
|
if (elem.rel && /\bicon\b/i.test(elem.rel))
|
||||||
addImage(elem.href, gStrings.mediaLink, "", elem, false);
|
addImage(elem.href, gStrings.mediaLink, "", elem, false);
|
||||||
|
@ -1015,7 +1011,6 @@ function makePreview(row)
|
||||||
document.getElementById("theimagecontainer").collapsed = false
|
document.getElementById("theimagecontainer").collapsed = false
|
||||||
document.getElementById("brokenimagecontainer").collapsed = true;
|
document.getElementById("brokenimagecontainer").collapsed = true;
|
||||||
}
|
}
|
||||||
#ifdef MOZ_MEDIA
|
|
||||||
else if (item instanceof HTMLVideoElement && isProtocolAllowed) {
|
else if (item instanceof HTMLVideoElement && isProtocolAllowed) {
|
||||||
newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
|
newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
|
||||||
newImage.id = "thepreviewimage";
|
newImage.id = "thepreviewimage";
|
||||||
|
@ -1037,7 +1032,6 @@ function makePreview(row)
|
||||||
document.getElementById("theimagecontainer").collapsed = false;
|
document.getElementById("theimagecontainer").collapsed = false;
|
||||||
document.getElementById("brokenimagecontainer").collapsed = true;
|
document.getElementById("brokenimagecontainer").collapsed = true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else {
|
else {
|
||||||
// fallback image for protocols not allowed (e.g., javascript:)
|
// fallback image for protocols not allowed (e.g., javascript:)
|
||||||
// or elements not [yet] handled (e.g., object, embed).
|
// or elements not [yet] handled (e.g., object, embed).
|
||||||
|
|
|
@ -145,6 +145,9 @@ _BROWSER_FILES = \
|
||||||
browser_bug647886.js \
|
browser_bug647886.js \
|
||||||
browser_bug655584.js \
|
browser_bug655584.js \
|
||||||
browser_bug664672.js \
|
browser_bug664672.js \
|
||||||
|
browser_bug678392.js \
|
||||||
|
browser_bug678392-1.html \
|
||||||
|
browser_bug678392-2.html \
|
||||||
browser_bug710878.js \
|
browser_bug710878.js \
|
||||||
browser_bug719271.js \
|
browser_bug719271.js \
|
||||||
browser_bug724239.js \
|
browser_bug724239.js \
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||||
|
<meta content="utf-8" http-equiv="encoding">
|
||||||
|
<title>bug678392 - 1</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
bug 678392 test page 1
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||||
|
<meta content="utf-8" http-equiv="encoding">
|
||||||
|
<title>bug678392 - 2</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
bug 678392 test page 2
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,192 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
let HTTPROOT = "http://example.com/browser/browser/base/content/test/";
|
||||||
|
|
||||||
|
function maxSnapshotOverride() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
BrowserOpenTab();
|
||||||
|
let tab = gBrowser.selectedTab;
|
||||||
|
registerCleanupFunction(function () { gBrowser.removeTab(tab); });
|
||||||
|
|
||||||
|
ok(gHistorySwipeAnimation, "gHistorySwipeAnimation exists.");
|
||||||
|
|
||||||
|
if (!gHistorySwipeAnimation._isSupported()) {
|
||||||
|
is(gHistorySwipeAnimation.active, false, "History swipe animation is not " +
|
||||||
|
"active when not supported by the platform.");
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gHistorySwipeAnimation._getMaxSnapshots = maxSnapshotOverride;
|
||||||
|
gHistorySwipeAnimation.init();
|
||||||
|
|
||||||
|
is(gHistorySwipeAnimation.active, true, "History swipe animation support " +
|
||||||
|
"was successfully initialized when supported.");
|
||||||
|
|
||||||
|
cleanupArray();
|
||||||
|
load(gBrowser.selectedTab, HTTPROOT + "browser_bug678392-2.html", test0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function load(aTab, aUrl, aCallback) {
|
||||||
|
aTab.linkedBrowser.addEventListener("pageshow", function onpageshow(aEvent) {
|
||||||
|
aEvent.currentTarget.removeEventListener("pageshow", onpageshow, false);
|
||||||
|
waitForFocus(aCallback, content);
|
||||||
|
}, false);
|
||||||
|
aTab.linkedBrowser.loadURI(aUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanupArray() {
|
||||||
|
let arr = gHistorySwipeAnimation._trackedSnapshots;
|
||||||
|
while (arr.length > 0) {
|
||||||
|
delete arr[0].browser.snapshots[arr[0].index]; // delete actual snapshot
|
||||||
|
arr.splice(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testArrayCleanup() {
|
||||||
|
// Test cleanup of array of tracked snapshots.
|
||||||
|
let arr = gHistorySwipeAnimation._trackedSnapshots;
|
||||||
|
is(arr.length, 0, "Snapshots were removed correctly from the array of " +
|
||||||
|
"tracked snapshots.");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test0() {
|
||||||
|
// Test growing of array of tracked snapshots.
|
||||||
|
let tab = gBrowser.selectedTab;
|
||||||
|
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-1.html", function() {
|
||||||
|
ok(gHistorySwipeAnimation._trackedSnapshots, "Array for snapshot " +
|
||||||
|
"tracking is initialized.");
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 1, "Snapshot array " +
|
||||||
|
"has correct length of 1 after loading one page.");
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-2.html", function() {
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 2, "Snapshot array " +
|
||||||
|
" has correct length of 2 after loading two pages.");
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-1.html", function() {
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 3, "Snapshot " +
|
||||||
|
"array has correct length of 3 after loading three pages.");
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-2.html", function() {
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 4, "Snapshot " +
|
||||||
|
"array has correct length of 4 after loading four pages.");
|
||||||
|
cleanupArray();
|
||||||
|
testArrayCleanup();
|
||||||
|
test1();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyRefRemoved(aIndex, aBrowser) {
|
||||||
|
let wasFound = false;
|
||||||
|
let arr = gHistorySwipeAnimation._trackedSnapshots;
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i].index == aIndex && arr[i].browser == aBrowser)
|
||||||
|
wasFound = true;
|
||||||
|
}
|
||||||
|
is(wasFound, false, "The reference that was previously removed was " +
|
||||||
|
"still found in the array of tracked snapshots.");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test1() {
|
||||||
|
// Test presence of snpashots in per-tab array of snapshots and removal of
|
||||||
|
// individual snapshots (and corresponding references in the array of
|
||||||
|
// tracked snapshots).
|
||||||
|
let tab = gBrowser.selectedTab;
|
||||||
|
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-1.html", function() {
|
||||||
|
var historyIndex = gBrowser.webNavigation.sessionHistory.index - 1;
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-2.html", function() {
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-1.html", function() {
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-2.html", function() {
|
||||||
|
let browser = gBrowser.selectedBrowser;
|
||||||
|
ok(browser.snapshots, "Array of snapshots exists in browser.");
|
||||||
|
ok(browser.snapshots[historyIndex], "First page exists in snapshot " +
|
||||||
|
"array.");
|
||||||
|
ok(browser.snapshots[historyIndex + 1], "Second page exists in " +
|
||||||
|
"snapshot array.");
|
||||||
|
ok(browser.snapshots[historyIndex + 2], "Third page exists in " +
|
||||||
|
"snapshot array.");
|
||||||
|
ok(browser.snapshots[historyIndex + 3], "Fourth page exists in " +
|
||||||
|
"snapshot array.");
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 4, "Length of " +
|
||||||
|
"array of tracked snapshots is equal to 4 after loading four " +
|
||||||
|
"pages.");
|
||||||
|
|
||||||
|
// Test removal of reference in the middle of the array.
|
||||||
|
gHistorySwipeAnimation._removeTrackedSnapshot(historyIndex + 1,
|
||||||
|
browser);
|
||||||
|
verifyRefRemoved(historyIndex + 1, browser);
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 3, "Length of " +
|
||||||
|
"array of tracked snapshots is equal to 3 after removing one" +
|
||||||
|
"reference from the array with length 4.");
|
||||||
|
|
||||||
|
// Test removal of reference at end of array.
|
||||||
|
gHistorySwipeAnimation._removeTrackedSnapshot(historyIndex + 3,
|
||||||
|
browser);
|
||||||
|
verifyRefRemoved(historyIndex + 3, browser);
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 2, "Length of " +
|
||||||
|
"array of tracked snapshots is equal to 2 after removing two" +
|
||||||
|
"references from the array with length 4.");
|
||||||
|
|
||||||
|
// Test removal of reference at head of array.
|
||||||
|
gHistorySwipeAnimation._removeTrackedSnapshot(historyIndex,
|
||||||
|
browser);
|
||||||
|
verifyRefRemoved(historyIndex, browser);
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 1, "Length of " +
|
||||||
|
"array of tracked snapshots is equal to 1 after removing three" +
|
||||||
|
"references from the array with length 4.");
|
||||||
|
|
||||||
|
cleanupArray();
|
||||||
|
test2();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test2() {
|
||||||
|
// Test growing of snapshot array across tabs.
|
||||||
|
let tab = gBrowser.selectedTab;
|
||||||
|
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-1.html", function() {
|
||||||
|
var historyIndex = gBrowser.webNavigation.sessionHistory.index - 1;
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-2.html", function() {
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 2, "Length of " +
|
||||||
|
"snapshot array is equal to 2 after loading two pages");
|
||||||
|
let prevTab = tab;
|
||||||
|
tab = gBrowser.addTab("about:newtab");
|
||||||
|
gBrowser.selectedTab = tab;
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-2.html" /* initial page */,
|
||||||
|
function() {
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-1.html", function() {
|
||||||
|
load(tab, HTTPROOT + "browser_bug678392-2.html", function() {
|
||||||
|
is(gHistorySwipeAnimation._trackedSnapshots.length, 4, "Length " +
|
||||||
|
"of snapshot array is equal to 4 after loading two pages in " +
|
||||||
|
"two tabs each.");
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
gBrowser.selectedTab = prevTab;
|
||||||
|
cleanupArray();
|
||||||
|
test3();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test3() {
|
||||||
|
// Test uninit of gHistorySwipeAnimation.
|
||||||
|
// This test MUST be the last one to execute.
|
||||||
|
gHistorySwipeAnimation.uninit();
|
||||||
|
is(gHistorySwipeAnimation.active, false, "History swipe animation support " +
|
||||||
|
"was successfully uninitialized");
|
||||||
|
finish();
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ var pairs = [
|
||||||
["1.1.1.1", "http://1.1.1.1/"],
|
["1.1.1.1", "http://1.1.1.1/"],
|
||||||
["ftp://example", "ftp://example/"],
|
["ftp://example", "ftp://example/"],
|
||||||
["ftp.example.bar", "ftp://ftp.example.bar/"],
|
["ftp.example.bar", "ftp://ftp.example.bar/"],
|
||||||
["ex ample", Services.search.originalDefaultEngine.getSubmission("ex ample", null, "keyword").uri.spec],
|
["ex ample", Services.search.defaultEngine.getSubmission("ex ample", null, "keyword").uri.spec],
|
||||||
];
|
];
|
||||||
|
|
||||||
function testNext() {
|
function testNext() {
|
||||||
|
|
|
@ -122,6 +122,14 @@ function test_TestEventListeners()
|
||||||
{
|
{
|
||||||
let e = test_helper1; // easier to type this name
|
let e = test_helper1; // easier to type this name
|
||||||
|
|
||||||
|
// Swipe gesture animation events
|
||||||
|
e("MozSwipeGestureStart", 0, -0.7, 0);
|
||||||
|
e("MozSwipeGestureUpdate", 0, -0.4, 0);
|
||||||
|
e("MozSwipeGestureEnd", 0, 0, 0);
|
||||||
|
e("MozSwipeGestureStart", 0, 0.6, 0);
|
||||||
|
e("MozSwipeGestureUpdate", 0, 0.3, 0);
|
||||||
|
e("MozSwipeGestureEnd", 0, 1, 0);
|
||||||
|
|
||||||
// Swipe gesture event
|
// Swipe gesture event
|
||||||
e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0);
|
e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0);
|
||||||
e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0);
|
e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0);
|
||||||
|
@ -199,7 +207,7 @@ function test_helper2(type, direction, delta, altKey, ctrlKey, shiftKey, metaKey
|
||||||
10, 10, 10, 10,
|
10, 10, 10, 10,
|
||||||
ctrlKey, altKey, shiftKey, metaKey,
|
ctrlKey, altKey, shiftKey, metaKey,
|
||||||
1, window,
|
1, window,
|
||||||
direction, delta, 0);
|
0, direction, delta, 0);
|
||||||
successful = true;
|
successful = true;
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
|
|
|
@ -7,30 +7,12 @@ var gTests = [
|
||||||
{
|
{
|
||||||
name: "normal search (search service)",
|
name: "normal search (search service)",
|
||||||
testText: "test search",
|
testText: "test search",
|
||||||
searchURL: Services.search.originalDefaultEngine.getSubmission("test search", null, "keyword").uri.spec
|
searchURL: Services.search.defaultEngine.getSubmission("test search", null, "keyword").uri.spec
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "?-prefixed search (search service)",
|
name: "?-prefixed search (search service)",
|
||||||
testText: "? foo ",
|
testText: "? foo ",
|
||||||
searchURL: Services.search.originalDefaultEngine.getSubmission("foo", null, "keyword").uri.spec
|
searchURL: Services.search.defaultEngine.getSubmission("foo", null, "keyword").uri.spec
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "normal search (keyword.url)",
|
|
||||||
testText: "test search",
|
|
||||||
keywordURLPref: "http://example.com/?q=",
|
|
||||||
searchURL: "http://example.com/?q=test+search"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "?-prefixed search (keyword.url)",
|
|
||||||
testText: "? foo ",
|
|
||||||
keywordURLPref: "http://example.com/?q=",
|
|
||||||
searchURL: "http://example.com/?q=foo"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "encoding test (keyword.url)",
|
|
||||||
testText: "test encoded+%/",
|
|
||||||
keywordURLPref: "http://example.com/?q=",
|
|
||||||
searchURL: "http://example.com/?q=test+encoded%2B%25%2F"
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
@ -17,11 +19,11 @@ pref("app.update.promptWaitTime", 86400);
|
||||||
pref("app.update.url.manual", "http://www.mozilla.com/firefox/channel/");
|
pref("app.update.url.manual", "http://www.mozilla.com/firefox/channel/");
|
||||||
// A default value for the "More information about this update" link
|
// A default value for the "More information about this update" link
|
||||||
// supplied in the "An update is available" page of the update wizard.
|
// supplied in the "An update is available" page of the update wizard.
|
||||||
pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
|
pref("app.update.url.details", "http://www.mozilla.org/projects/firefox/");
|
||||||
|
|
||||||
// Release notes and vendor URLs
|
// Release notes and vendor URLs
|
||||||
pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
|
pref("app.releaseNotesURL", "http://www.mozilla.org/projects/firefox/%VERSION%/releasenotes/");
|
||||||
pref("app.vendorURL", "http://www.mozilla.org/projects/%APP%/");
|
pref("app.vendorURL", "http://www.mozilla.org/projects/firefox/");
|
||||||
|
|
||||||
// Search codes belong only in builds with official branding
|
// Search codes belong only in builds with official branding
|
||||||
pref("browser.search.param.yahoo-fr", "");
|
pref("browser.search.param.yahoo-fr", "");
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
|
pref("startup.homepage_override_url","http://www.mozilla.org/projects/firefox/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
|
||||||
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
|
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/firefox/%VERSION%/firstrun/");
|
||||||
// The time interval between checks for a new version (in seconds)
|
// The time interval between checks for a new version (in seconds)
|
||||||
pref("app.update.interval", 7200); // 2 hours
|
pref("app.update.interval", 7200); // 2 hours
|
||||||
// The time interval between the downloading of mar file chunks in the
|
// The time interval between the downloading of mar file chunks in the
|
||||||
|
@ -16,11 +16,11 @@ pref("app.update.promptWaitTime", 43200);
|
||||||
pref("app.update.url.manual", "http://nightly.mozilla.org/");
|
pref("app.update.url.manual", "http://nightly.mozilla.org/");
|
||||||
// A default value for the "More information about this update" link
|
// A default value for the "More information about this update" link
|
||||||
// supplied in the "An update is available" page of the update wizard.
|
// supplied in the "An update is available" page of the update wizard.
|
||||||
pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
|
pref("app.update.url.details", "http://www.mozilla.org/projects/firefox/");
|
||||||
|
|
||||||
// Release notes and vendor URLs
|
// Release notes and vendor URLs
|
||||||
pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
|
pref("app.releaseNotesURL", "http://www.mozilla.org/projects/firefox/%VERSION%/releasenotes/");
|
||||||
pref("app.vendorURL", "http://www.mozilla.org/projects/%APP%/");
|
pref("app.vendorURL", "http://www.mozilla.org/projects/firefox/");
|
||||||
|
|
||||||
// Search codes belong only in builds with official branding
|
// Search codes belong only in builds with official branding
|
||||||
pref("browser.search.param.yahoo-fr", "");
|
pref("browser.search.param.yahoo-fr", "");
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
pref("startup.homepage_override_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
|
pref("startup.homepage_override_url","http://www.mozilla.com/%LOCALE%/firefox/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
|
||||||
pref("startup.homepage_welcome_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/firstrun/");
|
pref("startup.homepage_welcome_url","http://www.mozilla.com/%LOCALE%/firefox/%VERSION%/firstrun/");
|
||||||
// Interval: Time between checks for a new version (in seconds)
|
// Interval: Time between checks for a new version (in seconds)
|
||||||
pref("app.update.interval", 43200); // 12 hours
|
pref("app.update.interval", 43200); // 12 hours
|
||||||
// The time interval between the downloading of mar file chunks in the
|
// The time interval between the downloading of mar file chunks in the
|
||||||
|
@ -16,11 +16,11 @@ pref("app.update.promptWaitTime", 86400);
|
||||||
pref("app.update.url.manual", "http://www.firefox.com");
|
pref("app.update.url.manual", "http://www.firefox.com");
|
||||||
// A default value for the "More information about this update" link
|
// A default value for the "More information about this update" link
|
||||||
// supplied in the "An update is available" page of the update wizard.
|
// supplied in the "An update is available" page of the update wizard.
|
||||||
pref("app.update.url.details", "http://www.mozilla.com/%LOCALE%/%APP%/releases/");
|
pref("app.update.url.details", "http://www.mozilla.com/%LOCALE%/firefox/releases/");
|
||||||
|
|
||||||
// Release notes and vendor URLs
|
// Release notes and vendor URLs
|
||||||
pref("app.releaseNotesURL", "http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/releasenotes/");
|
pref("app.releaseNotesURL", "http://www.mozilla.com/%LOCALE%/firefox/%VERSION%/releasenotes/");
|
||||||
pref("app.vendorURL", "http://www.mozilla.com/%LOCALE%/%APP%/");
|
pref("app.vendorURL", "http://www.mozilla.com/%LOCALE%/firefox/");
|
||||||
|
|
||||||
pref("browser.search.param.ms-pc", "MOZI");
|
pref("browser.search.param.ms-pc", "MOZI");
|
||||||
pref("browser.search.param.yahoo-fr", "moz35");
|
pref("browser.search.param.yahoo-fr", "moz35");
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
|
pref("startup.homepage_override_url","http://www.mozilla.org/projects/firefox/%VERSION%/whatsnew/");
|
||||||
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
|
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/firefox/%VERSION%/firstrun/");
|
||||||
// The time interval between checks for a new version (in seconds)
|
// The time interval between checks for a new version (in seconds)
|
||||||
pref("app.update.interval", 86400); // 24 hours
|
pref("app.update.interval", 86400); // 24 hours
|
||||||
// The time interval between the downloading of mar file chunks in the
|
// The time interval between the downloading of mar file chunks in the
|
||||||
|
@ -13,14 +13,14 @@ pref("app.update.download.backgroundInterval", 60);
|
||||||
pref("app.update.promptWaitTime", 86400);
|
pref("app.update.promptWaitTime", 86400);
|
||||||
// URL user can browse to manually if for some reason all update installation
|
// URL user can browse to manually if for some reason all update installation
|
||||||
// attempts fail.
|
// attempts fail.
|
||||||
pref("app.update.url.manual", "http://www.mozilla.org/products/%APP%/");
|
pref("app.update.url.manual", "http://www.mozilla.org/products/firefox/");
|
||||||
// A default value for the "More information about this update" link
|
// A default value for the "More information about this update" link
|
||||||
// supplied in the "An update is available" page of the update wizard.
|
// supplied in the "An update is available" page of the update wizard.
|
||||||
pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
|
pref("app.update.url.details", "http://www.mozilla.org/projects/firefox/");
|
||||||
|
|
||||||
// Release notes and vendor URLs
|
// Release notes and vendor URLs
|
||||||
pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
|
pref("app.releaseNotesURL", "http://www.mozilla.org/projects/firefox/%VERSION%/releasenotes/");
|
||||||
pref("app.vendorURL", "http://www.mozilla.org/projects/%APP%/");
|
pref("app.vendorURL", "http://www.mozilla.org/projects/firefox/");
|
||||||
|
|
||||||
// Search codes belong only in builds with official branding
|
// Search codes belong only in builds with official branding
|
||||||
pref("browser.search.param.yahoo-fr", "");
|
pref("browser.search.param.yahoo-fr", "");
|
||||||
|
|
|
@ -77,9 +77,10 @@ FirefoxProfileMigrator.prototype.getResources = function() {
|
||||||
let formData = getFileResource(types.FORMDATA, ["formhistory.sqlite"]);
|
let formData = getFileResource(types.FORMDATA, ["formhistory.sqlite"]);
|
||||||
let bookmarksBackups = getFileResource(types.OTHERDATA,
|
let bookmarksBackups = getFileResource(types.OTHERDATA,
|
||||||
[PlacesUtils.backups.profileRelativeFolderPath]);
|
[PlacesUtils.backups.profileRelativeFolderPath]);
|
||||||
|
let dictionary = getFileResource(types.OTHERDATA, ["persdict.dat"]);
|
||||||
|
|
||||||
return [r for each (r in [places, cookies, passwords, formData,
|
return [r for each (r in [places, cookies, passwords, formData,
|
||||||
bookmarksBackups]) if (r)];
|
dictionary, bookmarksBackups]) if (r)];
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(FirefoxProfileMigrator.prototype, "startupOnlyMigrator", {
|
Object.defineProperty(FirefoxProfileMigrator.prototype, "startupOnlyMigrator", {
|
||||||
|
|
|
@ -405,7 +405,8 @@ this.MigrationUtils = Object.freeze({
|
||||||
*/
|
*/
|
||||||
getLocalizedString: function MU_getLocalizedString(aKey, aReplacements) {
|
getLocalizedString: function MU_getLocalizedString(aKey, aReplacements) {
|
||||||
const OVERRIDES = {
|
const OVERRIDES = {
|
||||||
"4_firefox": "4_firefox_history_and_bookmarks"
|
"4_firefox": "4_firefox_history_and_bookmarks",
|
||||||
|
"64_firefox": "64_firefox_other"
|
||||||
};
|
};
|
||||||
aKey = OVERRIDES[aKey] || aKey;
|
aKey = OVERRIDES[aKey] || aKey;
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "webrtcUI",
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
|
|
||||||
"resource:///modules/KeywordURLResetPrompter.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
||||||
"resource:///modules/RecentWindow.jsm");
|
"resource:///modules/RecentWindow.jsm");
|
||||||
|
|
||||||
|
@ -264,13 +261,6 @@ BrowserGlue.prototype = {
|
||||||
this._initPlaces(false);
|
this._initPlaces(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "defaultURIFixup-using-keyword-pref":
|
|
||||||
if (KeywordURLResetPrompter.shouldPrompt) {
|
|
||||||
let keywordURI = subject.QueryInterface(Ci.nsIURI);
|
|
||||||
KeywordURLResetPrompter.prompt(this.getMostRecentBrowserWindow(),
|
|
||||||
keywordURI);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "initial-migration-will-import-default-bookmarks":
|
case "initial-migration-will-import-default-bookmarks":
|
||||||
this._migrationImportsDefaultBookmarks = true;
|
this._migrationImportsDefaultBookmarks = true;
|
||||||
break;
|
break;
|
||||||
|
@ -344,7 +334,6 @@ BrowserGlue.prototype = {
|
||||||
os.addObserver(this, "distribution-customization-complete", false);
|
os.addObserver(this, "distribution-customization-complete", false);
|
||||||
os.addObserver(this, "places-shutdown", false);
|
os.addObserver(this, "places-shutdown", false);
|
||||||
this._isPlacesShutdownObserver = true;
|
this._isPlacesShutdownObserver = true;
|
||||||
os.addObserver(this, "defaultURIFixup-using-keyword-pref", false);
|
|
||||||
os.addObserver(this, "handle-xul-text-link", false);
|
os.addObserver(this, "handle-xul-text-link", false);
|
||||||
os.addObserver(this, "profile-before-change", false);
|
os.addObserver(this, "profile-before-change", false);
|
||||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||||
|
@ -378,7 +367,6 @@ BrowserGlue.prototype = {
|
||||||
os.removeObserver(this, "places-database-locked");
|
os.removeObserver(this, "places-database-locked");
|
||||||
if (this._isPlacesShutdownObserver)
|
if (this._isPlacesShutdownObserver)
|
||||||
os.removeObserver(this, "places-shutdown");
|
os.removeObserver(this, "places-shutdown");
|
||||||
os.removeObserver(this, "defaultURIFixup-using-keyword-pref");
|
|
||||||
os.removeObserver(this, "handle-xul-text-link");
|
os.removeObserver(this, "handle-xul-text-link");
|
||||||
os.removeObserver(this, "profile-before-change");
|
os.removeObserver(this, "profile-before-change");
|
||||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||||
|
@ -564,9 +552,6 @@ BrowserGlue.prototype = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL");
|
|
||||||
Services.telemetry.getHistogramById("FX_KEYWORD_URL_USERSET").add(keywordURLUserSet);
|
|
||||||
|
|
||||||
// Perform default browser checking.
|
// Perform default browser checking.
|
||||||
var shell;
|
var shell;
|
||||||
try {
|
try {
|
||||||
|
@ -1223,7 +1208,7 @@ BrowserGlue.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_migrateUI: function BG__migrateUI() {
|
_migrateUI: function BG__migrateUI() {
|
||||||
const UI_VERSION = 9;
|
const UI_VERSION = 11;
|
||||||
const BROWSER_DOCURL = "chrome://browser/content/browser.xul#";
|
const BROWSER_DOCURL = "chrome://browser/content/browser.xul#";
|
||||||
let currentUIVersion = 0;
|
let currentUIVersion = 0;
|
||||||
try {
|
try {
|
||||||
|
@ -1366,6 +1351,29 @@ BrowserGlue.prototype = {
|
||||||
Services.prefs.clearUserPref("browser.library.useNewDownloadsView");
|
Services.prefs.clearUserPref("browser.library.useNewDownloadsView");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
if (currentUIVersion < 10) {
|
||||||
|
// For Windows systems with display set to > 96dpi (i.e. systemDefaultScale
|
||||||
|
// will return a value > 1.0), we want to discard any saved full-zoom settings,
|
||||||
|
// as we'll now be scaling the content according to the system resolution
|
||||||
|
// scale factor (Windows "logical DPI" setting)
|
||||||
|
let sm = Cc["@mozilla.org/gfx/screenmanager;1"].getService(Ci.nsIScreenManager);
|
||||||
|
if (sm.systemDefaultScale > 1.0) {
|
||||||
|
let cps2 = Cc["@mozilla.org/content-pref/service;1"].
|
||||||
|
getService(Ci.nsIContentPrefService2);
|
||||||
|
cps2.removeByName("browser.content.full-zoom", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (currentUIVersion < 11) {
|
||||||
|
Services.prefs.clearUserPref("dom.disable_window_move_resize");
|
||||||
|
Services.prefs.clearUserPref("dom.disable_window_flip");
|
||||||
|
Services.prefs.clearUserPref("dom.event.contextmenu.enabled");
|
||||||
|
Services.prefs.clearUserPref("javascript.enabled");
|
||||||
|
Services.prefs.clearUserPref("permissions.default.image");
|
||||||
|
}
|
||||||
|
|
||||||
if (this._dirty)
|
if (this._dirty)
|
||||||
this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
|
this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
|
||||||
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<!-- -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
|
|
||||||
<!-- 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/. -->
|
|
||||||
|
|
||||||
<!DOCTYPE prefwindow SYSTEM "chrome://browser/locale/preferences/advanced-scripts.dtd">
|
|
||||||
|
|
||||||
<?xml-stylesheet href="chrome://global/skin/"?>
|
|
||||||
|
|
||||||
<prefwindow id="AdvancedJSDialog" type="child"
|
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
||||||
title="&advancedJSDialog.title;"
|
|
||||||
dlgbuttons="accept,cancel,help"
|
|
||||||
ondialoghelp="openPrefsHelp()">
|
|
||||||
|
|
||||||
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
|
|
||||||
|
|
||||||
<prefpane id="AdvancedJSDialogPane"
|
|
||||||
helpTopic="prefs-advanced-javascript">
|
|
||||||
|
|
||||||
<preferences>
|
|
||||||
<preference id="dom.event.contextmenu.enabled" name="dom.event.contextmenu.enabled" type="bool"/>
|
|
||||||
<preference id="dom.disable_window_move_resize" name="dom.disable_window_move_resize" type="bool" inverted="true"/>
|
|
||||||
<preference id="dom.disable_window_flip" name="dom.disable_window_flip" type="bool" inverted="true"/>
|
|
||||||
</preferences>
|
|
||||||
|
|
||||||
<script type="application/javascript" src="chrome://browser/content/preferences/advanced-scripts.js"/>
|
|
||||||
|
|
||||||
<stringbundle id="preferencesBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
|
|
||||||
|
|
||||||
<description value="&allowScripts.label;"/>
|
|
||||||
|
|
||||||
<checkbox id="moveResizePopupWindows" label="&moveResizePopupWindows.label;"
|
|
||||||
accesskey="&moveResizePopupWindows.accesskey;"
|
|
||||||
preference="dom.disable_window_move_resize"/>
|
|
||||||
<checkbox id="raiseLowerWindows" label="&raiseLowerWindows.label;"
|
|
||||||
accesskey="&raiseLowerWindows.accesskey;"
|
|
||||||
preference="dom.disable_window_flip"/>
|
|
||||||
<checkbox id="disableContextMenus" label="&disableContextMenus.label;"
|
|
||||||
accesskey="&disableContextMenus.accesskey;"
|
|
||||||
preference="dom.event.contextmenu.enabled"/>
|
|
||||||
|
|
||||||
</prefpane>
|
|
||||||
</prefwindow>
|
|
|
@ -36,8 +36,7 @@ var gContentPane = {
|
||||||
* The exceptions types which may be passed to this._showExceptions().
|
* The exceptions types which may be passed to this._showExceptions().
|
||||||
*/
|
*/
|
||||||
_exceptionsParams: {
|
_exceptionsParams: {
|
||||||
popup: { blockVisible: false, sessionVisible: false, allowVisible: true, prefilledHost: "", permissionType: "popup" },
|
popup: { blockVisible: false, sessionVisible: false, allowVisible: true, prefilledHost: "", permissionType: "popup" }
|
||||||
image: { blockVisible: true, sessionVisible: false, allowVisible: true, prefilledHost: "", permissionType: "image" }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,15 +61,6 @@ var gContentPane = {
|
||||||
*
|
*
|
||||||
* dom.disable_open_during_load
|
* dom.disable_open_during_load
|
||||||
* - true if popups are blocked by default, false otherwise
|
* - true if popups are blocked by default, false otherwise
|
||||||
* permissions.default.image
|
|
||||||
* - an integer:
|
|
||||||
* 1 all images should be loaded,
|
|
||||||
* 2 no images should be loaded,
|
|
||||||
* 3 load only images from the site on which the current page resides
|
|
||||||
* (i.e., if viewing foo.example.com, foo.example.com/foo.jpg and
|
|
||||||
* bar.foo.example.com/bar.jpg load but example.com/quux.jpg does not)
|
|
||||||
* javascript.enabled
|
|
||||||
* - true if JavaScript is enabled, false otherwise
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// POP-UPS
|
// POP-UPS
|
||||||
|
@ -84,48 +74,6 @@ var gContentPane = {
|
||||||
this._showExceptions("popup");
|
this._showExceptions("popup");
|
||||||
},
|
},
|
||||||
|
|
||||||
// IMAGES
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the value of the permissions.default.image preference into a
|
|
||||||
* Boolean value for use in determining the state of the "load images"
|
|
||||||
* checkbox, returning true if images should be loaded and false otherwise.
|
|
||||||
*/
|
|
||||||
readLoadImages: function ()
|
|
||||||
{
|
|
||||||
var pref = document.getElementById("permissions.default.image");
|
|
||||||
return (pref.value == 1 || pref.value == 3);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the "load images" preference value which maps to the state of the
|
|
||||||
* preferences UI.
|
|
||||||
*/
|
|
||||||
writeLoadImages: function ()
|
|
||||||
{
|
|
||||||
return (document.getElementById("loadImages").checked) ? 1 : 2;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays image exception preferences for which websites can and cannot
|
|
||||||
* load images.
|
|
||||||
*/
|
|
||||||
showImageExceptions: function ()
|
|
||||||
{
|
|
||||||
this._showExceptions("image");
|
|
||||||
},
|
|
||||||
|
|
||||||
// JAVASCRIPT
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the advanced JavaScript preferences for enabling or disabling
|
|
||||||
* various annoying behaviors.
|
|
||||||
*/
|
|
||||||
showAdvancedJS: function ()
|
|
||||||
{
|
|
||||||
document.documentElement.openSubDialog("chrome://browser/content/preferences/advanced-scripts.xul",
|
|
||||||
"", null);
|
|
||||||
},
|
|
||||||
|
|
||||||
// FONTS
|
// FONTS
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,8 @@
|
||||||
<preferences id="contentPreferences">
|
<preferences id="contentPreferences">
|
||||||
<!--XXX buttons prefs -->
|
<!--XXX buttons prefs -->
|
||||||
|
|
||||||
<!-- POPUPS, IMAGES, JAVASCRIPT -->
|
<!-- POPUPS -->
|
||||||
<preference id="dom.disable_open_during_load" name="dom.disable_open_during_load" type="bool"/>
|
<preference id="dom.disable_open_during_load" name="dom.disable_open_during_load" type="bool"/>
|
||||||
<preference id="permissions.default.image" name="permissions.default.image" type="int"/>
|
|
||||||
<preference id="javascript.enabled" name="javascript.enabled" type="bool"/>
|
|
||||||
|
|
||||||
<preference id="pref.advanced.images.disable_button.view_image"
|
|
||||||
name="pref.advanced.images.disable_button.view_image"
|
|
||||||
type="bool"/>
|
|
||||||
<preference id="pref.advanced.javascript.disable_button.advanced"
|
|
||||||
name="pref.advanced.javascript.disable_button.advanced"
|
|
||||||
type="bool"/>
|
|
||||||
|
|
||||||
<!-- FONTS -->
|
<!-- FONTS -->
|
||||||
<preference id="font.language.group"
|
<preference id="font.language.group"
|
||||||
|
@ -65,36 +56,6 @@
|
||||||
oncommand="gContentPane.showPopupExceptions();"
|
oncommand="gContentPane.showPopupExceptions();"
|
||||||
accesskey="&popupExceptions.accesskey;"/>
|
accesskey="&popupExceptions.accesskey;"/>
|
||||||
</row>
|
</row>
|
||||||
<row id="enableImagesRow">
|
|
||||||
<vbox align="start">
|
|
||||||
<checkbox id="loadImages"
|
|
||||||
label="&loadImages.label;"
|
|
||||||
accesskey="&loadImages.accesskey;"
|
|
||||||
preference="permissions.default.image"
|
|
||||||
onsyncfrompreference="return gContentPane.readLoadImages();"
|
|
||||||
onsynctopreference="return gContentPane.writeLoadImages();"/>
|
|
||||||
</vbox>
|
|
||||||
<vbox>
|
|
||||||
<button label="&exceptions.label;"
|
|
||||||
accesskey="&exceptions.accesskey;"
|
|
||||||
oncommand="gContentPane.showImageExceptions();"
|
|
||||||
preference="pref.advanced.images.disable_button.view_image"/>
|
|
||||||
</vbox>
|
|
||||||
</row>
|
|
||||||
<row id="enableJavaScriptRow">
|
|
||||||
<vbox align="start">
|
|
||||||
<checkbox id="enableJavaScript" preference="javascript.enabled"
|
|
||||||
label="&enableJavaScript.label;" accesskey="&enableJavaScript.accesskey;"
|
|
||||||
onsyncfrompreference="return gContentPane.updateButtons('advancedJSButton',
|
|
||||||
'javascript.enabled');"/>
|
|
||||||
</vbox>
|
|
||||||
<vbox>
|
|
||||||
<button id="advancedJSButton" label="&advancedJS.label;"
|
|
||||||
accesskey="&advancedJS.accesskey;"
|
|
||||||
oncommand="gContentPane.showAdvancedJS();"
|
|
||||||
preference="pref.advanced.javascript.disable_button.advanced"/>
|
|
||||||
</vbox>
|
|
||||||
</row>
|
|
||||||
</rows>
|
</rows>
|
||||||
</grid>
|
</grid>
|
||||||
</groupbox>
|
</groupbox>
|
||||||
|
|
|
@ -36,9 +36,7 @@ var gContentPane = {
|
||||||
*/
|
*/
|
||||||
_exceptionsParams: {
|
_exceptionsParams: {
|
||||||
popup: { blockVisible: false, sessionVisible: false, allowVisible: true,
|
popup: { blockVisible: false, sessionVisible: false, allowVisible: true,
|
||||||
prefilledHost: "", permissionType: "popup" },
|
prefilledHost: "", permissionType: "popup" }
|
||||||
image: { blockVisible: true, sessionVisible: false, allowVisible: true,
|
|
||||||
prefilledHost: "", permissionType: "image" }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,15 +61,6 @@ var gContentPane = {
|
||||||
*
|
*
|
||||||
* dom.disable_open_during_load
|
* dom.disable_open_during_load
|
||||||
* - true if popups are blocked by default, false otherwise
|
* - true if popups are blocked by default, false otherwise
|
||||||
* permissions.default.image
|
|
||||||
* - an integer:
|
|
||||||
* 1 all images should be loaded,
|
|
||||||
* 2 no images should be loaded,
|
|
||||||
* 3 load only images from the site on which the current page resides
|
|
||||||
* (i.e., if viewing foo.example.com, foo.example.com/foo.jpg and
|
|
||||||
* bar.foo.example.com/bar.jpg load but example.com/quux.jpg does not)
|
|
||||||
* javascript.enabled
|
|
||||||
* - true if JavaScript is enabled, false otherwise
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// POP-UPS
|
// POP-UPS
|
||||||
|
@ -85,49 +74,6 @@ var gContentPane = {
|
||||||
this._showExceptions("popup");
|
this._showExceptions("popup");
|
||||||
},
|
},
|
||||||
|
|
||||||
// IMAGES
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the value of the permissions.default.image preference into a
|
|
||||||
* Boolean value for use in determining the state of the "load images"
|
|
||||||
* checkbox, returning true if images should be loaded and false otherwise.
|
|
||||||
*/
|
|
||||||
readLoadImages: function ()
|
|
||||||
{
|
|
||||||
var pref = document.getElementById("permissions.default.image");
|
|
||||||
return (pref.value == 1 || pref.value == 3);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the "load images" preference value which maps to the state of the
|
|
||||||
* preferences UI.
|
|
||||||
*/
|
|
||||||
writeLoadImages: function ()
|
|
||||||
{
|
|
||||||
return (document.getElementById("loadImages").checked) ? 1 : 2;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays image exception preferences for which websites can and cannot
|
|
||||||
* load images.
|
|
||||||
*/
|
|
||||||
showImageExceptions: function ()
|
|
||||||
{
|
|
||||||
this._showExceptions("image");
|
|
||||||
},
|
|
||||||
|
|
||||||
// JAVASCRIPT
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the advanced JavaScript preferences for enabling or disabling
|
|
||||||
* various annoying behaviors.
|
|
||||||
*/
|
|
||||||
showAdvancedJS: function ()
|
|
||||||
{
|
|
||||||
openDialog("chrome://browser/content/preferences/advanced-scripts.xul",
|
|
||||||
"Browser:AdvancedScripts", null);
|
|
||||||
},
|
|
||||||
|
|
||||||
// FONTS
|
// FONTS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,22 +4,10 @@
|
||||||
|
|
||||||
<preferences id="contentPreferences">
|
<preferences id="contentPreferences">
|
||||||
|
|
||||||
<!-- Popups, images, and JavaScript -->
|
<!-- Popups -->
|
||||||
<preference id="dom.disable_open_during_load"
|
<preference id="dom.disable_open_during_load"
|
||||||
name="dom.disable_open_during_load"
|
name="dom.disable_open_during_load"
|
||||||
type="bool"/>
|
type="bool"/>
|
||||||
<preference id="permissions.default.image"
|
|
||||||
name="permissions.default.image"
|
|
||||||
type="int"/>
|
|
||||||
<preference id="javascript.enabled"
|
|
||||||
name="javascript.enabled"
|
|
||||||
type="bool"/>
|
|
||||||
<preference id="pref.advanced.images.disable_button.view_image"
|
|
||||||
name="pref.advanced.images.disable_button.view_image"
|
|
||||||
type="bool"/>
|
|
||||||
<preference id="pref.advanced.javascript.disable_button.advanced"
|
|
||||||
name="pref.advanced.javascript.disable_button.advanced"
|
|
||||||
type="bool"/>
|
|
||||||
|
|
||||||
<!-- Fonts -->
|
<!-- Fonts -->
|
||||||
<preference id="font.language.group"
|
<preference id="font.language.group"
|
||||||
|
@ -56,36 +44,6 @@
|
||||||
oncommand="gContentPane.showPopupExceptions();"
|
oncommand="gContentPane.showPopupExceptions();"
|
||||||
accesskey="&popupExceptions.accesskey;"/>
|
accesskey="&popupExceptions.accesskey;"/>
|
||||||
</row>
|
</row>
|
||||||
<row id="enableImagesRow">
|
|
||||||
<vbox align="start">
|
|
||||||
<checkbox id="loadImages"
|
|
||||||
label="&loadImages.label;"
|
|
||||||
accesskey="&loadImages.accesskey;"
|
|
||||||
preference="permissions.default.image"
|
|
||||||
onsyncfrompreference="return gContentPane.readLoadImages();"
|
|
||||||
onsynctopreference="return gContentPane.writeLoadImages();"/>
|
|
||||||
</vbox>
|
|
||||||
<vbox>
|
|
||||||
<button label="&exceptions.label;"
|
|
||||||
accesskey="&exceptions.accesskey;"
|
|
||||||
oncommand="gContentPane.showImageExceptions();"
|
|
||||||
preference="pref.advanced.images.disable_button.view_image"/>
|
|
||||||
</vbox>
|
|
||||||
</row>
|
|
||||||
<row id="enableJavaScriptRow">
|
|
||||||
<vbox align="start">
|
|
||||||
<checkbox id="enableJavaScript" preference="javascript.enabled"
|
|
||||||
label="&enableJavaScript.label;" accesskey="&enableJavaScript.accesskey;"
|
|
||||||
onsyncfrompreference="return gContentPane.updateButtons('advancedJSButton',
|
|
||||||
'javascript.enabled');"/>
|
|
||||||
</vbox>
|
|
||||||
<vbox>
|
|
||||||
<button id="advancedJSButton" label="&advancedJS.label;"
|
|
||||||
accesskey="&advancedJS.accesskey;"
|
|
||||||
oncommand="gContentPane.showAdvancedJS();"
|
|
||||||
preference="pref.advanced.javascript.disable_button.advanced"/>
|
|
||||||
</vbox>
|
|
||||||
</row>
|
|
||||||
</rows>
|
</rows>
|
||||||
</grid>
|
</grid>
|
||||||
</groupbox>
|
</groupbox>
|
||||||
|
|
|
@ -146,13 +146,14 @@ var gPrivacyPane = {
|
||||||
*/
|
*/
|
||||||
getTrackingPrefs: function PPP_getTrackingPrefs()
|
getTrackingPrefs: function PPP_getTrackingPrefs()
|
||||||
{
|
{
|
||||||
let dntValuePref = document.getElementById("privacy.donottrackheader.value"),
|
// XXX avoid using bindings that might not be attached, see bug 859982
|
||||||
dntEnabledPref = document.getElementById("privacy.donottrackheader.enabled");
|
let dntValue = Services.prefs.getBoolPref("privacy.donottrackheader.value"),
|
||||||
|
dntEnabled = Services.prefs.getBoolPref("privacy.donottrackheader.enabled");
|
||||||
|
|
||||||
// if DNT is enbaled, select the value from the selected radio
|
// if DNT is enbaled, select the value from the selected radio
|
||||||
// button, otherwise choose the "no preference" radio button
|
// button, otherwise choose the "no preference" radio button
|
||||||
if (dntEnabledPref.value)
|
if (dntEnabled)
|
||||||
return dntValuePref.value;
|
return dntValue;
|
||||||
|
|
||||||
return document.getElementById("dntnopref").value;
|
return document.getElementById("dntnopref").value;
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,7 +9,6 @@ browser.jar:
|
||||||
content/browser/preferences/aboutPermissions.xml
|
content/browser/preferences/aboutPermissions.xml
|
||||||
* content/browser/preferences/advanced.xul
|
* content/browser/preferences/advanced.xul
|
||||||
* content/browser/preferences/advanced.js
|
* content/browser/preferences/advanced.js
|
||||||
content/browser/preferences/advanced-scripts.xul
|
|
||||||
content/browser/preferences/applications.xul
|
content/browser/preferences/applications.xul
|
||||||
* content/browser/preferences/applications.js
|
* content/browser/preferences/applications.js
|
||||||
content/browser/preferences/applicationManager.xul
|
content/browser/preferences/applicationManager.xul
|
||||||
|
|
|
@ -45,6 +45,7 @@ var gEngineManagerDialog = {
|
||||||
break;
|
break;
|
||||||
case "engine-removed":
|
case "engine-removed":
|
||||||
case "engine-current":
|
case "engine-current":
|
||||||
|
case "engine-default":
|
||||||
// Not relevant
|
// Not relevant
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,8 +121,12 @@
|
||||||
<field name="searchButton">document.getAnonymousElementByAttribute(this,
|
<field name="searchButton">document.getAnonymousElementByAttribute(this,
|
||||||
"anonid", "searchbar-engine-button");</field>
|
"anonid", "searchbar-engine-button");</field>
|
||||||
|
|
||||||
<property name="currentEngine"
|
<property name="currentEngine">
|
||||||
onset="this.searchService.currentEngine = val; return val;">
|
<setter><![CDATA[
|
||||||
|
let ss = this.searchService;
|
||||||
|
ss.defaultEngine = ss.currentEngine = val;
|
||||||
|
return val;
|
||||||
|
]]></setter>
|
||||||
<getter><![CDATA[
|
<getter><![CDATA[
|
||||||
var currentEngine = this.searchService.currentEngine;
|
var currentEngine = this.searchService.currentEngine;
|
||||||
// Return a dummy engine if there is no currentEngine
|
// Return a dummy engine if there is no currentEngine
|
||||||
|
@ -422,8 +426,9 @@
|
||||||
var newIndex = this.engines.indexOf(this.currentEngine);
|
var newIndex = this.engines.indexOf(this.currentEngine);
|
||||||
newIndex += isNextEngine ? 1 : -1;
|
newIndex += isNextEngine ? 1 : -1;
|
||||||
|
|
||||||
if (newIndex >= 0 && newIndex < this.engines.length)
|
if (newIndex >= 0 && newIndex < this.engines.length) {
|
||||||
this.currentEngine = this.engines[newIndex];
|
this.currentEngine = this.engines[newIndex];
|
||||||
|
}
|
||||||
|
|
||||||
aEvent.preventDefault();
|
aEvent.preventDefault();
|
||||||
aEvent.stopPropagation();
|
aEvent.stopPropagation();
|
||||||
|
|
|
@ -57,7 +57,7 @@ function test() {
|
||||||
let engine = Services.search.getEngineByName("Google");
|
let engine = Services.search.getEngineByName("Google");
|
||||||
ok(engine, "Google");
|
ok(engine, "Google");
|
||||||
|
|
||||||
is(Services.search.originalDefaultEngine, engine, "Check that Google is the default search engine");
|
is(Services.search.defaultEngine, engine, "Check that Google is the default search engine");
|
||||||
|
|
||||||
let distributionID;
|
let distributionID;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -23,62 +23,6 @@ function nsSidebar()
|
||||||
|
|
||||||
nsSidebar.prototype.classID = SIDEBAR_CID;
|
nsSidebar.prototype.classID = SIDEBAR_CID;
|
||||||
|
|
||||||
nsSidebar.prototype.nc = "http://home.netscape.com/NC-rdf#";
|
|
||||||
|
|
||||||
function sidebarURLSecurityCheck(url)
|
|
||||||
{
|
|
||||||
if (!/^(https?:|ftp:)/i.test(url)) {
|
|
||||||
Components.utils.reportError("Invalid argument passed to window.sidebar.addPanel: Unsupported panel URL." );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decorate prototype to provide ``class'' methods and property accessors */
|
|
||||||
nsSidebar.prototype.addPanel =
|
|
||||||
function (aTitle, aContentURL, aCustomizeURL)
|
|
||||||
{
|
|
||||||
debug("addPanel(" + aTitle + ", " + aContentURL + ", " +
|
|
||||||
aCustomizeURL + ")");
|
|
||||||
|
|
||||||
return this.addPanelInternal(aTitle, aContentURL, aCustomizeURL, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsSidebar.prototype.addPersistentPanel =
|
|
||||||
function(aTitle, aContentURL, aCustomizeURL)
|
|
||||||
{
|
|
||||||
debug("addPersistentPanel(" + aTitle + ", " + aContentURL + ", " +
|
|
||||||
aCustomizeURL + ")\n");
|
|
||||||
|
|
||||||
return this.addPanelInternal(aTitle, aContentURL, aCustomizeURL, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsSidebar.prototype.addPanelInternal =
|
|
||||||
function (aTitle, aContentURL, aCustomizeURL, aPersist)
|
|
||||||
{
|
|
||||||
// XXX Bug 620418: We shouldn't do this anymore. Instead, we should find the
|
|
||||||
// global object for our caller and use it.
|
|
||||||
var win = Services.wm.getMostRecentWindow("navigator:browser");
|
|
||||||
if (!sidebarURLSecurityCheck(aContentURL))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var uri = null;
|
|
||||||
try {
|
|
||||||
uri = Services.io.newURI(aContentURL, null, null);
|
|
||||||
}
|
|
||||||
catch(ex) { return; }
|
|
||||||
|
|
||||||
win.PlacesUIUtils.showBookmarkDialog({ action: "add"
|
|
||||||
, type: "bookmark"
|
|
||||||
, hiddenRows: [ "description"
|
|
||||||
, "keyword"
|
|
||||||
, "location" ]
|
|
||||||
, uri: uri
|
|
||||||
, title: aTitle
|
|
||||||
, loadBookmarkInSidebar: true
|
|
||||||
}, win);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsSidebar.prototype.validateSearchEngine =
|
nsSidebar.prototype.validateSearchEngine =
|
||||||
function (engineURL, iconURL)
|
function (engineURL, iconURL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -161,10 +161,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||||
|
|
||||||
// Create the promise that will be resolved when the add-on listing has
|
// Create the promise that will be resolved when the add-on listing has
|
||||||
// been finished.
|
// been finished.
|
||||||
let promise = context.createPromise();
|
let deferred = context.defer();
|
||||||
let types = aArgs.type == "all" ? null : [aArgs.type];
|
let types = aArgs.type == "all" ? null : [aArgs.type];
|
||||||
AddonManager.getAddonsByTypes(types, list.bind(promise, aArgs.type));
|
AddonManager.getAddonsByTypes(types, list.bind(deferred, aArgs.type));
|
||||||
return promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -259,10 +259,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||||
this.resolve(message);
|
this.resolve(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
let promise = context.createPromise();
|
let deferred = context.defer();
|
||||||
// List the installed add-ons, enable one when done listing.
|
// List the installed add-ons, enable one when done listing.
|
||||||
AddonManager.getAllAddons(enable.bind(promise, aArgs.name));
|
AddonManager.getAllAddons(enable.bind(deferred, aArgs.name));
|
||||||
return promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -301,10 +301,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||||
this.resolve(message);
|
this.resolve(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
let promise = context.createPromise();
|
let deferred = context.defer();
|
||||||
// List the installed add-ons, disable one when done listing.
|
// List the installed add-ons, disable one when done listing.
|
||||||
AddonManager.getAllAddons(disable.bind(promise, aArgs.name));
|
AddonManager.getAllAddons(disable.bind(deferred, aArgs.name));
|
||||||
return promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
module.CmdAddonFlags.addonsLoaded = true;
|
module.CmdAddonFlags.addonsLoaded = true;
|
||||||
|
@ -1235,7 +1235,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||||
return gcli.lookup('jsbInvalidURL');
|
return gcli.lookup('jsbInvalidURL');
|
||||||
}
|
}
|
||||||
|
|
||||||
let promise = context.createPromise();
|
let deferred = context.defer();
|
||||||
|
|
||||||
xhr.onreadystatechange = function(aEvt) {
|
xhr.onreadystatechange = function(aEvt) {
|
||||||
if (xhr.readyState == 4) {
|
if (xhr.readyState == 4) {
|
||||||
|
@ -1247,15 +1247,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||||
|
|
||||||
browserWindow.Scratchpad.ScratchpadManager.openScratchpad({text: result});
|
browserWindow.Scratchpad.ScratchpadManager.openScratchpad({text: result});
|
||||||
|
|
||||||
promise.resolve();
|
deferred.resolve();
|
||||||
} else {
|
} else {
|
||||||
promise.resolve("Unable to load page to beautify: " + args.url + " " +
|
deferred.resolve("Unable to load page to beautify: " + args.url + " " +
|
||||||
xhr.status + " " + xhr.statusText);
|
xhr.status + " " + xhr.statusText);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
xhr.send(null);
|
xhr.send(null);
|
||||||
return promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}(this));
|
}(this));
|
||||||
|
@ -1642,13 +1642,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||||
var document = args.chrome? context.environment.chromeDocument
|
var document = args.chrome? context.environment.chromeDocument
|
||||||
: context.environment.contentDocument;
|
: context.environment.contentDocument;
|
||||||
if (args.delay > 0) {
|
if (args.delay > 0) {
|
||||||
var promise = context.createPromise();
|
var deferred = context.defer();
|
||||||
document.defaultView.setTimeout(function Command_screenshotDelay() {
|
document.defaultView.setTimeout(function Command_screenshotDelay() {
|
||||||
let reply = this.grabScreen(document, args.filename, args.clipboard,
|
let reply = this.grabScreen(document, args.filename, args.clipboard,
|
||||||
args.fullpage);
|
args.fullpage);
|
||||||
promise.resolve(reply);
|
deferred.resolve(reply);
|
||||||
}.bind(this), args.delay * 1000);
|
}.bind(this), args.delay * 1000);
|
||||||
return promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return this.grabScreen(document, args.filename, args.clipboard,
|
return this.grabScreen(document, args.filename, args.clipboard,
|
||||||
|
|
|
@ -30,32 +30,93 @@ gcli.addCommand({
|
||||||
gcli.addCommand({
|
gcli.addCommand({
|
||||||
name: "break list",
|
name: "break list",
|
||||||
description: gcli.lookup("breaklistDesc"),
|
description: gcli.lookup("breaklistDesc"),
|
||||||
returnType: "html",
|
returnType: "breakpoints",
|
||||||
exec: function(args, context) {
|
exec: function(args, context) {
|
||||||
let dbg = getPanel(context, "jsdebugger");
|
let panel = getPanel(context, "jsdebugger", {ensure_opened: true});
|
||||||
if (!dbg) {
|
return panel.then(function(dbg) {
|
||||||
return gcli.lookup("debuggerStopped");
|
let breakpoints = [];
|
||||||
}
|
for (let source in dbg.panelWin.DebuggerView.Sources) {
|
||||||
|
for (let { attachment: breakpoint } in source) {
|
||||||
let breakpoints = dbg.getAllBreakpoints();
|
breakpoints.push({
|
||||||
|
url: source.value,
|
||||||
if (Object.keys(breakpoints).length === 0) {
|
label: source.label,
|
||||||
return gcli.lookup("breaklistNone");
|
lineNumber: breakpoint.lineNumber,
|
||||||
}
|
lineText: breakpoint.lineText
|
||||||
|
});
|
||||||
let reply = gcli.lookup("breaklistIntro");
|
}
|
||||||
reply += "<ol>";
|
}
|
||||||
for each (let breakpoint in breakpoints) {
|
return breakpoints;
|
||||||
let text = gcli.lookupFormat("breaklistLineEntry",
|
});
|
||||||
[breakpoint.location.url,
|
|
||||||
breakpoint.location.line]);
|
|
||||||
reply += "<li>" + text + "</li>";
|
|
||||||
};
|
|
||||||
reply += "</ol>";
|
|
||||||
return reply;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gcli.addConverter({
|
||||||
|
from: "breakpoints",
|
||||||
|
to: "view",
|
||||||
|
exec: function(breakpoints, context) {
|
||||||
|
let dbg = getPanel(context, "jsdebugger");
|
||||||
|
if (dbg && breakpoints.length) {
|
||||||
|
let SourceUtils = dbg.panelWin.SourceUtils;
|
||||||
|
let index = 0;
|
||||||
|
return context.createView({
|
||||||
|
html: breakListHtml,
|
||||||
|
data: {
|
||||||
|
breakpoints: breakpoints.map(function(breakpoint) {
|
||||||
|
return {
|
||||||
|
index: index++,
|
||||||
|
url: breakpoint.url,
|
||||||
|
label: SourceUtils.trimUrlLength(
|
||||||
|
breakpoint.label + ":" + breakpoint.lineNumber,
|
||||||
|
MAX_LABEL_LENGTH,
|
||||||
|
"start"),
|
||||||
|
lineText: breakpoint.lineText,
|
||||||
|
truncatedLineText: SourceUtils.trimUrlLength(
|
||||||
|
breakpoint.lineText,
|
||||||
|
MAX_LINE_TEXT_LENGTH,
|
||||||
|
"end")
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
onclick: createUpdateHandler(context),
|
||||||
|
ondblclick: createExecuteHandler(context)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return context.createView({
|
||||||
|
html: "<p>${message}</p>",
|
||||||
|
data: { message: gcli.lookup("breaklistNone") }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var breakListHtml = "" +
|
||||||
|
"<table>" +
|
||||||
|
" <thead>" +
|
||||||
|
" <th>Source</th>" +
|
||||||
|
" <th>Line</th>" +
|
||||||
|
" <th>Actions</th>" +
|
||||||
|
" </thead>" +
|
||||||
|
" <tbody>" +
|
||||||
|
" <tr foreach='breakpoint in ${breakpoints}'>" +
|
||||||
|
" <td class='gcli-breakpoint-label'>${breakpoint.label}</td>" +
|
||||||
|
" <td class='gcli-breakpoint-lineText'>" +
|
||||||
|
" ${breakpoint.truncatedLineText}" +
|
||||||
|
" </td>" +
|
||||||
|
" <td>" +
|
||||||
|
" <span class='gcli-out-shortcut'" +
|
||||||
|
" data-command='break del ${breakpoint.index}'" +
|
||||||
|
" onclick='${onclick}'" +
|
||||||
|
" ondblclick='${ondblclick}'" +
|
||||||
|
" >" + gcli.lookup("breaklistOutRemove") + "</span>" +
|
||||||
|
" </td>" +
|
||||||
|
" </tr>" +
|
||||||
|
" </tbody>" +
|
||||||
|
"</table>" +
|
||||||
|
"";
|
||||||
|
|
||||||
|
var MAX_LINE_TEXT_LENGTH = 30;
|
||||||
|
var MAX_LABEL_LENGTH = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'break add' command
|
* 'break add' command
|
||||||
*/
|
*/
|
||||||
|
@ -348,14 +409,71 @@ function createXHTMLElement(document, tagname) {
|
||||||
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
|
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to find the 'data-command' attribute and call some action on it.
|
||||||
|
* @see |updateCommand()| and |executeCommand()|
|
||||||
|
*/
|
||||||
|
function withCommand(element, action) {
|
||||||
|
var command = element.getAttribute("data-command");
|
||||||
|
if (!command) {
|
||||||
|
command = element.querySelector("*[data-command]")
|
||||||
|
.getAttribute("data-command");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command) {
|
||||||
|
action(command);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn("Missing data-command for " + util.findCssSelector(element));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a handler to update the requisition to contain the text held in the
|
||||||
|
* first matching data-command attribute under the currentTarget of the event.
|
||||||
|
* @param context Either a Requisition or an ExecutionContext or another object
|
||||||
|
* that contains an |update()| function that follows a similar contract.
|
||||||
|
*/
|
||||||
|
function createUpdateHandler(context) {
|
||||||
|
return function(ev) {
|
||||||
|
withCommand(ev.currentTarget, function(command) {
|
||||||
|
context.update(command);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a handler to execute the text held in the data-command attribute
|
||||||
|
* under the currentTarget of the event.
|
||||||
|
* @param context Either a Requisition or an ExecutionContext or another object
|
||||||
|
* that contains an |update()| function that follows a similar contract.
|
||||||
|
*/
|
||||||
|
function createExecuteHandler(context) {
|
||||||
|
return function(ev) {
|
||||||
|
withCommand(ev.currentTarget, function(command) {
|
||||||
|
context.exec({
|
||||||
|
visible: true,
|
||||||
|
typed: command
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper to go from a command context to a debugger panel
|
* A helper to go from a command context to a debugger panel
|
||||||
*/
|
*/
|
||||||
function getPanel(context, id) {
|
function getPanel(context, id, opts) {
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
let target = context.environment.target;
|
||||||
return toolbox == null ? undefined : toolbox.getPanel(id);
|
if (opts && opts.ensure_opened) {
|
||||||
|
return gDevTools.showToolbox(target, id).then(function(toolbox) {
|
||||||
|
return toolbox.getPanel(id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let toolbox = gDevTools.getToolbox(target);
|
||||||
|
return toolbox && toolbox.getPanel(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,10 +86,4 @@ DebuggerPanel.prototype = {
|
||||||
getAllBreakpoints: function() {
|
getAllBreakpoints: function() {
|
||||||
return this._bkp.store;
|
return this._bkp.store;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Private
|
|
||||||
|
|
||||||
_ensureOnlyOneRunningDebugger: function() {
|
|
||||||
// FIXME
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,6 @@ const Cu = Components.utils;
|
||||||
const DBG_XUL = "chrome://browser/content/debugger.xul";
|
const DBG_XUL = "chrome://browser/content/debugger.xul";
|
||||||
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
|
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
|
||||||
const CHROME_DEBUGGER_PROFILE_NAME = "-chrome-debugger";
|
const CHROME_DEBUGGER_PROFILE_NAME = "-chrome-debugger";
|
||||||
const TAB_SWITCH_NOTIFICATION = "debugger-tab-switch";
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
@ -83,10 +82,6 @@ DebuggerUI.prototype = {
|
||||||
let selectedTab = this.chromeWindow.gBrowser.selectedTab;
|
let selectedTab = this.chromeWindow.gBrowser.selectedTab;
|
||||||
|
|
||||||
if (scriptDebugger) {
|
if (scriptDebugger) {
|
||||||
if (scriptDebugger.ownerTab !== selectedTab) {
|
|
||||||
this.showTabSwitchNotification();
|
|
||||||
return scriptDebugger;
|
|
||||||
}
|
|
||||||
scriptDebugger.close();
|
scriptDebugger.close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -171,63 +166,6 @@ DebuggerUI.prototype = {
|
||||||
*/
|
*/
|
||||||
getChromeDebugger: function DUI_getChromeDebugger() {
|
getChromeDebugger: function DUI_getChromeDebugger() {
|
||||||
return '_chromeDebugger' in this ? this._chromeDebugger : null;
|
return '_chromeDebugger' in this ? this._chromeDebugger : null;
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currently, there can only be one debugger per tab.
|
|
||||||
* Show an asynchronous notification which asks the user to switch the
|
|
||||||
* script debugger to the current tab if it's already open in another one.
|
|
||||||
*/
|
|
||||||
showTabSwitchNotification: function DUI_showTabSwitchNotification() {
|
|
||||||
let gBrowser = this.chromeWindow.gBrowser;
|
|
||||||
let selectedBrowser = gBrowser.selectedBrowser;
|
|
||||||
|
|
||||||
let nbox = gBrowser.getNotificationBox(selectedBrowser);
|
|
||||||
let notification = nbox.getNotificationWithValue(TAB_SWITCH_NOTIFICATION);
|
|
||||||
if (notification) {
|
|
||||||
nbox.removeNotification(notification);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let self = this;
|
|
||||||
|
|
||||||
let buttons = [{
|
|
||||||
id: "debugger.confirmTabSwitch.buttonSwitch",
|
|
||||||
label: L10N.getStr("confirmTabSwitch.buttonSwitch"),
|
|
||||||
accessKey: L10N.getStr("confirmTabSwitch.buttonSwitch.accessKey"),
|
|
||||||
callback: function DUI_notificationButtonSwitch() {
|
|
||||||
let scriptDebugger = self.findDebugger();
|
|
||||||
let targetWindow = scriptDebugger.globalUI.chromeWindow;
|
|
||||||
targetWindow.gBrowser.selectedTab = scriptDebugger.ownerTab;
|
|
||||||
targetWindow.focus();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
id: "debugger.confirmTabSwitch.buttonOpen",
|
|
||||||
label: L10N.getStr("confirmTabSwitch.buttonOpen"),
|
|
||||||
accessKey: L10N.getStr("confirmTabSwitch.buttonOpen.accessKey"),
|
|
||||||
callback: function DUI_notificationButtonOpen() {
|
|
||||||
let scriptDebugger = self.findDebugger();
|
|
||||||
let targetWindow = scriptDebugger.globalUI.chromeWindow;
|
|
||||||
scriptDebugger.close();
|
|
||||||
|
|
||||||
targetWindow.addEventListener("Debugger:Shutdown", function onShutdown() {
|
|
||||||
targetWindow.removeEventListener("Debugger:Shutdown", onShutdown, false);
|
|
||||||
Services.tm.currentThread.dispatch({ run: function() {
|
|
||||||
self.toggleDebugger();
|
|
||||||
}}, 0);
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
let message = L10N.getStr("confirmTabSwitch.message");
|
|
||||||
let imageURL = "chrome://browser/skin/Info.png";
|
|
||||||
|
|
||||||
notification = nbox.appendNotification(
|
|
||||||
message, TAB_SWITCH_NOTIFICATION,
|
|
||||||
imageURL, nbox.PRIORITY_WARNING_HIGH, buttons, null);
|
|
||||||
|
|
||||||
// Make sure this is not a transient notification, to avoid the automatic
|
|
||||||
// transient notification removal.
|
|
||||||
notification.persistence = -1;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,17 +15,6 @@ const NEW_SOURCE_DISPLAY_DELAY = 200; // ms
|
||||||
const FETCH_SOURCE_RESPONSE_DELAY = 50; // ms
|
const FETCH_SOURCE_RESPONSE_DELAY = 50; // ms
|
||||||
const FRAME_STEP_CLEAR_DELAY = 100; // ms
|
const FRAME_STEP_CLEAR_DELAY = 100; // ms
|
||||||
const CALL_STACK_PAGE_SIZE = 25; // frames
|
const CALL_STACK_PAGE_SIZE = 25; // frames
|
||||||
const VARIABLES_VIEW_NON_SORTABLE = [
|
|
||||||
"Array",
|
|
||||||
"Int8Array",
|
|
||||||
"Uint8Array",
|
|
||||||
"Int16Array",
|
|
||||||
"Uint16Array",
|
|
||||||
"Int32Array",
|
|
||||||
"Uint32Array",
|
|
||||||
"Float32Array",
|
|
||||||
"Float64Array"
|
|
||||||
];
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
@ -267,7 +256,7 @@ let DebuggerController = {
|
||||||
this.ThreadState.connect();
|
this.ThreadState.connect();
|
||||||
this.StackFrames.connect();
|
this.StackFrames.connect();
|
||||||
this.SourceScripts.connect();
|
this.SourceScripts.connect();
|
||||||
aThreadClient.resume();
|
aThreadClient.resume(this._ensureResumptionOrder);
|
||||||
|
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
aCallback();
|
aCallback();
|
||||||
|
@ -276,6 +265,15 @@ let DebuggerController = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warn if resuming execution produced a wrongOrder error.
|
||||||
|
*/
|
||||||
|
_ensureResumptionOrder: function DC__ensureResumptionOrder(aResponse) {
|
||||||
|
if (aResponse.error == "wrongOrder") {
|
||||||
|
DebuggerView.Toolbar.showResumeWarning(aResponse.lastPausedUrl);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up a chrome debugging session.
|
* Sets up a chrome debugging session.
|
||||||
*
|
*
|
||||||
|
@ -303,7 +301,7 @@ let DebuggerController = {
|
||||||
this.ThreadState.connect();
|
this.ThreadState.connect();
|
||||||
this.StackFrames.connect();
|
this.StackFrames.connect();
|
||||||
this.SourceScripts.connect();
|
this.SourceScripts.connect();
|
||||||
aThreadClient.resume();
|
aThreadClient.resume(this._ensureResumptionOrder);
|
||||||
|
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
aCallback();
|
aCallback();
|
||||||
|
@ -528,7 +526,7 @@ StackFrames.prototype = {
|
||||||
// If the breakpoint's conditional expression evaluation is falsy,
|
// If the breakpoint's conditional expression evaluation is falsy,
|
||||||
// automatically resume execution.
|
// automatically resume execution.
|
||||||
if (VariablesView.isFalsy({ value: this.currentEvaluation.return })) {
|
if (VariablesView.isFalsy({ value: this.currentEvaluation.return })) {
|
||||||
this.activeThread.resume();
|
this.activeThread.resume(DebuggerController._ensureResumptionOrder);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -893,7 +891,7 @@ StackFrames.prototype = {
|
||||||
|
|
||||||
this.activeThread.pauseGrip(grip).getPrototypeAndProperties(function(aResponse) {
|
this.activeThread.pauseGrip(grip).getPrototypeAndProperties(function(aResponse) {
|
||||||
let { ownProperties, prototype } = aResponse;
|
let { ownProperties, prototype } = aResponse;
|
||||||
let sortable = VARIABLES_VIEW_NON_SORTABLE.indexOf(grip.class) == -1;
|
let sortable = VariablesView.NON_SORTABLE_CLASSES.indexOf(grip.class) == -1;
|
||||||
|
|
||||||
// Add all the variable properties.
|
// Add all the variable properties.
|
||||||
if (ownProperties) {
|
if (ownProperties) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ ToolbarView.prototype = {
|
||||||
dumpn("Initializing the ToolbarView");
|
dumpn("Initializing the ToolbarView");
|
||||||
|
|
||||||
this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
|
this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
|
||||||
|
this._resumeOrderPanel = document.getElementById("resumption-order-panel");
|
||||||
this._resumeButton = document.getElementById("resume");
|
this._resumeButton = document.getElementById("resume");
|
||||||
this._stepOverButton = document.getElementById("step-over");
|
this._stepOverButton = document.getElementById("step-over");
|
||||||
this._stepInButton = document.getElementById("step-in");
|
this._stepInButton = document.getElementById("step-in");
|
||||||
|
@ -89,6 +90,19 @@ ToolbarView.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a warning when trying to resume a debuggee while another is paused.
|
||||||
|
* Debuggees must be unpaused in a Last-In-First-Out order.
|
||||||
|
*
|
||||||
|
* @param string aPausedUrl
|
||||||
|
* The URL of the last paused debuggee.
|
||||||
|
*/
|
||||||
|
showResumeWarning: function DVT_showResumeWarning(aPausedUrl) {
|
||||||
|
let label = L10N.getFormatStr("resumptionOrderPanelTitle", [aPausedUrl]);
|
||||||
|
document.getElementById("resumption-panel-desc").textContent = label;
|
||||||
|
this._resumeOrderPanel.openPopup(this._resumeButton);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the chrome globals container hidden or visible. It's hidden by default.
|
* Sets the chrome globals container hidden or visible. It's hidden by default.
|
||||||
*
|
*
|
||||||
|
@ -115,7 +129,8 @@ ToolbarView.prototype = {
|
||||||
*/
|
*/
|
||||||
_onResumePressed: function DVT__onResumePressed() {
|
_onResumePressed: function DVT__onResumePressed() {
|
||||||
if (DebuggerController.activeThread.paused) {
|
if (DebuggerController.activeThread.paused) {
|
||||||
DebuggerController.activeThread.resume();
|
let warn = DebuggerController._ensureResumptionOrder;
|
||||||
|
DebuggerController.activeThread.resume(warn);
|
||||||
} else {
|
} else {
|
||||||
DebuggerController.activeThread.interrupt();
|
DebuggerController.activeThread.interrupt();
|
||||||
}
|
}
|
||||||
|
@ -149,6 +164,7 @@ ToolbarView.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_instrumentsPaneToggleButton: null,
|
_instrumentsPaneToggleButton: null,
|
||||||
|
_resumeOrderPanel: null,
|
||||||
_resumeButton: null,
|
_resumeButton: null,
|
||||||
_stepOverButton: null,
|
_stepOverButton: null,
|
||||||
_stepInButton: null,
|
_stepInButton: null,
|
||||||
|
|
|
@ -340,4 +340,14 @@
|
||||||
</vbox>
|
</vbox>
|
||||||
</panel>
|
</panel>
|
||||||
|
|
||||||
|
<panel id="resumption-order-panel"
|
||||||
|
type="arrow"
|
||||||
|
noautofocus="true"
|
||||||
|
position="before_start">
|
||||||
|
<hbox align="start">
|
||||||
|
<image class="alert-icon"/>
|
||||||
|
<label id="resumption-panel-desc" class="description"/>
|
||||||
|
</hbox>
|
||||||
|
</panel>
|
||||||
|
|
||||||
</window>
|
</window>
|
||||||
|
|
|
@ -17,8 +17,6 @@ MOCHITEST_BROWSER_TESTS = \
|
||||||
$(browser_dbg_cmd_break.js disabled until bug 722727 is fixed) \
|
$(browser_dbg_cmd_break.js disabled until bug 722727 is fixed) \
|
||||||
browser_dbg_createChrome.js \
|
browser_dbg_createChrome.js \
|
||||||
$(browser_dbg_createRemote.js disabled for intermittent failures, bug 753225) \
|
$(browser_dbg_createRemote.js disabled for intermittent failures, bug 753225) \
|
||||||
$(browser_dbg_debugger-tab-switch.js disabled until issues 106, 40 are fixed) \
|
|
||||||
$(browser_dbg_debugger-tab-switch-window.js disabled until issues 106, 40 are fixed) \
|
|
||||||
browser_dbg_debuggerstatement.js \
|
browser_dbg_debuggerstatement.js \
|
||||||
browser_dbg_listtabs.js \
|
browser_dbg_listtabs.js \
|
||||||
browser_dbg_tabactor-01.js \
|
browser_dbg_tabactor-01.js \
|
||||||
|
|
|
@ -1,244 +0,0 @@
|
||||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
|
||||||
/*
|
|
||||||
* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
||||||
*/
|
|
||||||
|
|
||||||
let gInitialTab, gTab1, gTab2, gTab3, gTab4;
|
|
||||||
let gInitialWindow, gSecondWindow;
|
|
||||||
let gPane1, gPane2;
|
|
||||||
let gNbox;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that a debugger instance can't be opened in multiple windows at once,
|
|
||||||
* and that on such an attempt a notification is shown, which can either switch
|
|
||||||
* to the old debugger instance, or close the old instance to open a new one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
gInitialWindow = window;
|
|
||||||
gInitialTab = window.gBrowser.selectedTab;
|
|
||||||
gNbox = gInitialWindow.gBrowser.getNotificationBox(gInitialWindow.gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
testTab1_initialWindow(function() {
|
|
||||||
testTab2_secondWindow(function() {
|
|
||||||
testTab3_secondWindow(function() {
|
|
||||||
testTab4_secondWindow(function() {
|
|
||||||
lastTest(function() {
|
|
||||||
cleanup(function() {
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab1_initialWindow(callback) {
|
|
||||||
gTab1 = addTab(TAB1_URL, function() {
|
|
||||||
gInitialWindow.gBrowser.selectedTab = gTab1;
|
|
||||||
gNbox = gInitialWindow.gBrowser.getNotificationBox(gInitialWindow.gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
ok(!gInitialWindow.DebuggerUI.getDebugger(),
|
|
||||||
"Shouldn't have a debugger pane for this tab yet.");
|
|
||||||
|
|
||||||
info("Toggling a debugger (1).");
|
|
||||||
|
|
||||||
gPane1 = gInitialWindow.DebuggerUI.toggleDebugger();
|
|
||||||
ok(gPane1, "toggleDebugger() should return a pane.");
|
|
||||||
is(gPane1.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(gInitialWindow.DebuggerUI.getDebugger(), gPane1,
|
|
||||||
"getDebugger() should return the same pane as toggleDebugger().");
|
|
||||||
|
|
||||||
wait_for_connect_and_resume(function dbgLoaded() {
|
|
||||||
info("First debugger has finished loading correctly.");
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, gInitialWindow);
|
|
||||||
}, gInitialWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab2_secondWindow(callback) {
|
|
||||||
gSecondWindow = addWindow();
|
|
||||||
|
|
||||||
gTab2 = addTab(TAB1_URL, function() {
|
|
||||||
gSecondWindow.gBrowser.selectedTab = gTab2;
|
|
||||||
gNbox = gSecondWindow.gBrowser.getNotificationBox(gSecondWindow.gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification yet.");
|
|
||||||
ok(gSecondWindow.DebuggerUI.findDebugger(),
|
|
||||||
"Should already have a debugger pane for another tab.");
|
|
||||||
|
|
||||||
gNbox.addEventListener("AlertActive", function active() {
|
|
||||||
gNbox.removeEventListener("AlertActive", active, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
|
||||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(gSecondWindow.DebuggerUI.findDebugger(), gPane1,
|
|
||||||
"findDebugger() should return the same pane as the first call to toggleDebugger().");
|
|
||||||
is(gSecondWindow.DebuggerUI.findDebugger(), gPane2,
|
|
||||||
"findDebugger() should return the same pane as the second call to toggleDebugger().");
|
|
||||||
|
|
||||||
info("Second debugger has not loaded.");
|
|
||||||
|
|
||||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
|
||||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
|
||||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
|
||||||
|
|
||||||
info("Notification will be simply closed.");
|
|
||||||
notification.close();
|
|
||||||
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
info("Toggling a debugger (2).");
|
|
||||||
|
|
||||||
gPane2 = gSecondWindow.DebuggerUI.toggleDebugger();
|
|
||||||
}, gSecondWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab3_secondWindow(callback) {
|
|
||||||
gTab3 = addTab(TAB1_URL, function() {
|
|
||||||
gSecondWindow.gBrowser.selectedTab = gTab3;
|
|
||||||
gNbox = gSecondWindow.gBrowser.getNotificationBox(gSecondWindow.gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
ok(gSecondWindow.DebuggerUI.findDebugger(),
|
|
||||||
"Should already have a debugger pane for another tab.");
|
|
||||||
|
|
||||||
gNbox.addEventListener("AlertActive", function active() {
|
|
||||||
gNbox.removeEventListener("AlertActive", active, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
|
||||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(gSecondWindow.DebuggerUI.findDebugger(), gPane1,
|
|
||||||
"findDebugger() should return the same pane as the first call to toggleDebugger().");
|
|
||||||
is(gSecondWindow.DebuggerUI.findDebugger(), gPane2,
|
|
||||||
"findDebugger() should return the same pane as the second call to toggleDebugger().");
|
|
||||||
|
|
||||||
info("Second debugger has not loaded.");
|
|
||||||
|
|
||||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
|
||||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
|
||||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
|
||||||
|
|
||||||
gInitialWindow.gBrowser.selectedTab = gInitialTab;
|
|
||||||
gInitialWindow.gBrowser.tabContainer.addEventListener("TabSelect", function tabSelect() {
|
|
||||||
gInitialWindow.gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
let buttonSwitch = notification.querySelectorAll("button")[0];
|
|
||||||
buttonSwitch.focus();
|
|
||||||
EventUtils.sendKey("SPACE", gSecondWindow);
|
|
||||||
info("The switch button on the notification was pressed.");
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
info("Toggling a debugger (3).");
|
|
||||||
|
|
||||||
gPane2 = gSecondWindow.DebuggerUI.toggleDebugger();
|
|
||||||
}, gSecondWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab4_secondWindow(callback) {
|
|
||||||
is(gInitialWindow.gBrowser.selectedTab, gTab1,
|
|
||||||
"Should've switched to the first debugged tab.");
|
|
||||||
|
|
||||||
gTab4 = addTab(TAB1_URL, function() {
|
|
||||||
gSecondWindow.gBrowser.selectedTab = gTab4;
|
|
||||||
gNbox = gSecondWindow.gBrowser.getNotificationBox(gSecondWindow.gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
ok(gSecondWindow.DebuggerUI.findDebugger(),
|
|
||||||
"Should already have a debugger pane for another tab.");
|
|
||||||
|
|
||||||
gNbox.addEventListener("AlertActive", function active() {
|
|
||||||
gNbox.removeEventListener("AlertActive", active, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
|
||||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(gSecondWindow.DebuggerUI.findDebugger(), gPane1,
|
|
||||||
"findDebugger() should return the same pane as the first call to toggleDebugger().");
|
|
||||||
is(gSecondWindow.DebuggerUI.findDebugger(), gPane2,
|
|
||||||
"findDebugger() should return the same pane as the second call to toggleDebugger().");
|
|
||||||
|
|
||||||
info("Second debugger has not loaded.");
|
|
||||||
|
|
||||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
|
||||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
|
||||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
|
||||||
|
|
||||||
let buttonOpen = notification.querySelectorAll("button")[1];
|
|
||||||
buttonOpen.focus();
|
|
||||||
EventUtils.sendKey("SPACE", gSecondWindow);
|
|
||||||
info("The open button on the notification was pressed.");
|
|
||||||
|
|
||||||
wait_for_connect_and_resume(function() {
|
|
||||||
callback();
|
|
||||||
}, gSecondWindow);
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
info("Toggling a debugger (4).");
|
|
||||||
|
|
||||||
gPane2 = gSecondWindow.DebuggerUI.toggleDebugger();
|
|
||||||
}, gSecondWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function lastTest(callback) {
|
|
||||||
is(gInitialWindow.gBrowser.selectedTab, gTab1,
|
|
||||||
"The initial window should continue having selected the first debugged tab.");
|
|
||||||
is(gSecondWindow.gBrowser.selectedTab, gTab4,
|
|
||||||
"Should currently be in the fourth tab.");
|
|
||||||
is(gSecondWindow.DebuggerUI.findDebugger().ownerTab, gTab4,
|
|
||||||
"The debugger should be open for the fourth tab.");
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
|
|
||||||
info("Second debugger has loaded.");
|
|
||||||
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanup(callback)
|
|
||||||
{
|
|
||||||
gPane1 = null;
|
|
||||||
gPane2 = null;
|
|
||||||
gNbox = null;
|
|
||||||
|
|
||||||
closeDebuggerAndFinish(false, function() {
|
|
||||||
removeTab(gTab1, gInitialWindow);
|
|
||||||
removeTab(gTab2, gSecondWindow);
|
|
||||||
removeTab(gTab3, gSecondWindow);
|
|
||||||
removeTab(gTab4, gSecondWindow);
|
|
||||||
gSecondWindow.close();
|
|
||||||
gTab1 = null;
|
|
||||||
gTab2 = null;
|
|
||||||
gTab3 = null;
|
|
||||||
gTab4 = null;
|
|
||||||
gInitialWindow = null;
|
|
||||||
gSecondWindow = null;
|
|
||||||
|
|
||||||
callback();
|
|
||||||
}, gSecondWindow);
|
|
||||||
}
|
|
|
@ -1,235 +0,0 @@
|
||||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
|
||||||
/*
|
|
||||||
* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
||||||
*/
|
|
||||||
|
|
||||||
let gTab1, gTab2, gTab3, gTab4;
|
|
||||||
let gPane1, gPane2;
|
|
||||||
let gNbox;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that a debugger instance can't be opened in multiple tabs at once,
|
|
||||||
* and that on such an attempt a notification is shown, which can either switch
|
|
||||||
* to the old debugger instance, or close the old instance to open a new one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
testTab1(function() {
|
|
||||||
testTab2(function() {
|
|
||||||
testTab3(function() {
|
|
||||||
testTab4(function() {
|
|
||||||
lastTest(function() {
|
|
||||||
cleanup(function() {
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab1(callback) {
|
|
||||||
gTab1 = addTab(TAB1_URL, function() {
|
|
||||||
gBrowser.selectedTab = gTab1;
|
|
||||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
ok(!DebuggerUI.getDebugger(),
|
|
||||||
"Shouldn't have a debugger pane for this tab yet.");
|
|
||||||
|
|
||||||
info("Toggling a debugger (1).");
|
|
||||||
|
|
||||||
gPane1 = DebuggerUI.toggleDebugger();
|
|
||||||
ok(gPane1, "toggleDebugger() should return a pane.");
|
|
||||||
is(gPane1.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(DebuggerUI.getDebugger(), gPane1,
|
|
||||||
"getDebugger() should return the same pane as toggleDebugger().");
|
|
||||||
|
|
||||||
wait_for_connect_and_resume(function dbgLoaded() {
|
|
||||||
info("First debugger has finished loading correctly.");
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab2(callback) {
|
|
||||||
gTab2 = addTab(TAB1_URL, function() {
|
|
||||||
gBrowser.selectedTab = gTab2;
|
|
||||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification yet.");
|
|
||||||
ok(DebuggerUI.getDebugger(),
|
|
||||||
"Should already have a debugger pane for another tab.");
|
|
||||||
|
|
||||||
gNbox.addEventListener("AlertActive", function active() {
|
|
||||||
gNbox.removeEventListener("AlertActive", active, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
|
||||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(DebuggerUI.getDebugger(), gPane1,
|
|
||||||
"getDebugger() should return the same pane as the first call to toggleDebugger().");
|
|
||||||
is(DebuggerUI.getDebugger(), gPane2,
|
|
||||||
"getDebugger() should return the same pane as the second call to toggleDebugger().");
|
|
||||||
|
|
||||||
info("Second debugger has not loaded.");
|
|
||||||
|
|
||||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
|
||||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
|
||||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
|
||||||
|
|
||||||
info("Notification will be simply closed.");
|
|
||||||
notification.close();
|
|
||||||
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
info("Toggling a debugger (2).");
|
|
||||||
|
|
||||||
gPane2 = DebuggerUI.toggleDebugger();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab3(callback) {
|
|
||||||
gTab3 = addTab(TAB1_URL, function() {
|
|
||||||
gBrowser.selectedTab = gTab3;
|
|
||||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
ok(DebuggerUI.getDebugger(),
|
|
||||||
"Should already have a debugger pane for another tab.");
|
|
||||||
|
|
||||||
gNbox.addEventListener("AlertActive", function active() {
|
|
||||||
gNbox.removeEventListener("AlertActive", active, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
|
||||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(DebuggerUI.getDebugger(), gPane1,
|
|
||||||
"getDebugger() should return the same pane as the first call to toggleDebugger().");
|
|
||||||
is(DebuggerUI.getDebugger(), gPane2,
|
|
||||||
"getDebugger() should return the same pane as the second call to toggleDebugger().");
|
|
||||||
|
|
||||||
info("Second debugger has not loaded.");
|
|
||||||
|
|
||||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
|
||||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
|
||||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
|
||||||
|
|
||||||
gBrowser.tabContainer.addEventListener("TabSelect", function tabSelect() {
|
|
||||||
gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
let buttonSwitch = notification.querySelectorAll("button")[0];
|
|
||||||
buttonSwitch.focus();
|
|
||||||
EventUtils.sendKey("SPACE");
|
|
||||||
info("The switch button on the notification was pressed.");
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
info("Toggling a debugger (3).");
|
|
||||||
|
|
||||||
gPane2 = DebuggerUI.toggleDebugger();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testTab4(callback) {
|
|
||||||
is(gBrowser.selectedTab, gTab1,
|
|
||||||
"Should've switched to the first debugged tab.");
|
|
||||||
|
|
||||||
gTab4 = addTab(TAB1_URL, function() {
|
|
||||||
gBrowser.selectedTab = gTab4;
|
|
||||||
gNbox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
ok(DebuggerUI.getDebugger(),
|
|
||||||
"Should already have a debugger pane for another tab.");
|
|
||||||
|
|
||||||
gNbox.addEventListener("AlertActive", function active() {
|
|
||||||
gNbox.removeEventListener("AlertActive", active, true);
|
|
||||||
executeSoon(function() {
|
|
||||||
ok(gPane2, "toggleDebugger() should always return a pane.");
|
|
||||||
is(gPane2.ownerTab, gTab1, "Incorrect tab owner.");
|
|
||||||
|
|
||||||
is(DebuggerUI.getDebugger(), gPane1,
|
|
||||||
"getDebugger() should return the same pane as the first call to toggleDebugger().");
|
|
||||||
is(DebuggerUI.getDebugger(), gPane2,
|
|
||||||
"getDebugger() should return the same pane as the second call to toggleDebugger().");
|
|
||||||
|
|
||||||
info("Second debugger has not loaded.");
|
|
||||||
|
|
||||||
let notification = gNbox.getNotificationWithValue("debugger-tab-switch");
|
|
||||||
ok(gNbox.currentNotification, "Should have a tab switch notification.");
|
|
||||||
is(gNbox.currentNotification, notification, "Incorrect current notification.");
|
|
||||||
|
|
||||||
let buttonOpen = notification.querySelectorAll("button")[1];
|
|
||||||
buttonOpen.focus();
|
|
||||||
EventUtils.sendKey("SPACE");
|
|
||||||
info("The open button on the notification was pressed.");
|
|
||||||
|
|
||||||
wait_for_connect_and_resume(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
info("Toggling a debugger (4).");
|
|
||||||
|
|
||||||
gPane2 = DebuggerUI.toggleDebugger();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function lastTest(callback) {
|
|
||||||
isnot(gBrowser.selectedTab, gTab1,
|
|
||||||
"Shouldn't have switched to the first debugged tab.");
|
|
||||||
is(gBrowser.selectedTab, gTab4,
|
|
||||||
"Should currently be in the fourth tab.");
|
|
||||||
is(DebuggerUI.getDebugger().ownerTab, gTab4,
|
|
||||||
"The debugger should be open for the fourth tab.");
|
|
||||||
|
|
||||||
is(gNbox.getNotificationWithValue("debugger-tab-switch"), null,
|
|
||||||
"Shouldn't have a tab switch notification.");
|
|
||||||
|
|
||||||
info("Second debugger has loaded.");
|
|
||||||
|
|
||||||
executeSoon(function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanup(callback)
|
|
||||||
{
|
|
||||||
gPane1 = null;
|
|
||||||
gPane2 = null;
|
|
||||||
gNbox = null;
|
|
||||||
|
|
||||||
closeDebuggerAndFinish(false, function() {
|
|
||||||
removeTab(gTab1);
|
|
||||||
removeTab(gTab2);
|
|
||||||
removeTab(gTab3);
|
|
||||||
removeTab(gTab4);
|
|
||||||
gTab1 = null;
|
|
||||||
gTab2 = null;
|
|
||||||
gTab3 = null;
|
|
||||||
gTab4 = null;
|
|
||||||
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -61,14 +61,14 @@ ToolSidebar.prototype = {
|
||||||
|
|
||||||
let onIFrameLoaded = function() {
|
let onIFrameLoaded = function() {
|
||||||
tab.setAttribute("label", iframe.contentDocument.title);
|
tab.setAttribute("label", iframe.contentDocument.title);
|
||||||
iframe.removeEventListener("DOMContentLoaded", onIFrameLoaded, true);
|
iframe.removeEventListener("load", onIFrameLoaded, true);
|
||||||
if ("setPanel" in iframe.contentWindow) {
|
if ("setPanel" in iframe.contentWindow) {
|
||||||
iframe.contentWindow.setPanel(this._toolPanel, iframe);
|
iframe.contentWindow.setPanel(this._toolPanel, iframe);
|
||||||
}
|
}
|
||||||
this.emit(id + "-ready");
|
this.emit(id + "-ready");
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
iframe.addEventListener("DOMContentLoaded", onIFrameLoaded, true);
|
iframe.addEventListener("load", onIFrameLoaded, true);
|
||||||
|
|
||||||
let tabpanel = this._panelDoc.createElementNS(XULNS, "tabpanel");
|
let tabpanel = this._panelDoc.createElementNS(XULNS, "tabpanel");
|
||||||
tabpanel.setAttribute("id", "sidebar-panel-" + id);
|
tabpanel.setAttribute("id", "sidebar-panel-" + id);
|
||||||
|
@ -91,7 +91,7 @@ ToolSidebar.prototype = {
|
||||||
// the "selected" attribute set to true.
|
// the "selected" attribute set to true.
|
||||||
this._panelDoc.defaultView.setTimeout(function() {
|
this._panelDoc.defaultView.setTimeout(function() {
|
||||||
this.select(id);
|
this.select(id);
|
||||||
}.bind(this), 0);
|
}.bind(this), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit("new-tab-registered", id);
|
this.emit("new-tab-registered", id);
|
||||||
|
|
|
@ -22,7 +22,7 @@ function test() {
|
||||||
const tab3URL = "data:text/html;charset=utf8,<title>3</title><p>3</p>";
|
const tab3URL = "data:text/html;charset=utf8,<title>3</title><p>3</p>";
|
||||||
|
|
||||||
let panelDoc;
|
let panelDoc;
|
||||||
|
let tab1Selected = false;
|
||||||
let registeredTabs = {};
|
let registeredTabs = {};
|
||||||
let readyTabs = {};
|
let readyTabs = {};
|
||||||
|
|
||||||
|
@ -63,24 +63,27 @@ function test() {
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.sidebar.once("tab1-ready", function(event) {
|
panel.sidebar.once("tab1-ready", function(event) {
|
||||||
|
info(event);
|
||||||
readyTabs.tab1 = true;
|
readyTabs.tab1 = true;
|
||||||
if (readyTabs.tab1 && readyTabs.tab2 && readyTabs.tab3) {
|
allTabsReady(panel);
|
||||||
allTabsReady(panel);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.sidebar.once("tab2-ready", function(event) {
|
panel.sidebar.once("tab2-ready", function(event) {
|
||||||
|
info(event);
|
||||||
readyTabs.tab2 = true;
|
readyTabs.tab2 = true;
|
||||||
if (readyTabs.tab1 && readyTabs.tab2 && readyTabs.tab3) {
|
allTabsReady(panel);
|
||||||
allTabsReady(panel);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.sidebar.once("tab3-ready", function(event) {
|
panel.sidebar.once("tab3-ready", function(event) {
|
||||||
|
info(event);
|
||||||
readyTabs.tab3 = true;
|
readyTabs.tab3 = true;
|
||||||
if (readyTabs.tab1 && readyTabs.tab2 && readyTabs.tab3) {
|
allTabsReady(panel);
|
||||||
allTabsReady(panel);
|
});
|
||||||
}
|
|
||||||
|
panel.sidebar.once("tab1-selected", function(event) {
|
||||||
|
info(event);
|
||||||
|
tab1Selected = true;
|
||||||
|
allTabsReady(panel);
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.sidebar.addTab("tab1", tab1URL, true);
|
panel.sidebar.addTab("tab1", tab1URL, true);
|
||||||
|
@ -92,6 +95,10 @@ function test() {
|
||||||
});
|
});
|
||||||
|
|
||||||
function allTabsReady(panel) {
|
function allTabsReady(panel) {
|
||||||
|
if (!tab1Selected || !readyTabs.tab1 || !readyTabs.tab2 || !readyTabs.tab3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ok(registeredTabs.tab1, "tab1 registered");
|
ok(registeredTabs.tab1, "tab1 registered");
|
||||||
ok(registeredTabs.tab2, "tab2 registered");
|
ok(registeredTabs.tab2, "tab2 registered");
|
||||||
ok(registeredTabs.tab3, "tab3 registered");
|
ok(registeredTabs.tab3, "tab3 registered");
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
browser.jar:
|
browser.jar:
|
||||||
content/browser/devtools/widgets.css (shared/widgets/widgets.css)
|
content/browser/devtools/widgets.css (shared/widgets/widgets.css)
|
||||||
|
content/browser/devtools/widgets/VariablesView.xul (shared/widgets/VariablesView.xul)
|
||||||
content/browser/devtools/markup-view.xhtml (markupview/markup-view.xhtml)
|
content/browser/devtools/markup-view.xhtml (markupview/markup-view.xhtml)
|
||||||
content/browser/devtools/markup-view.css (markupview/markup-view.css)
|
content/browser/devtools/markup-view.css (markupview/markup-view.css)
|
||||||
content/browser/devtools/netmonitor.xul (netmonitor/netmonitor.xul)
|
content/browser/devtools/netmonitor.xul (netmonitor/netmonitor.xul)
|
||||||
|
|
|
@ -259,7 +259,7 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
|
||||||
initialize: function NVRM_initialize() {
|
initialize: function NVRM_initialize() {
|
||||||
dumpn("Initializing the RequestsMenuView");
|
dumpn("Initializing the RequestsMenuView");
|
||||||
|
|
||||||
this.node = new SideMenuWidget($("#requests-menu-contents"));
|
this.node = new SideMenuWidget($("#requests-menu-contents"), false);
|
||||||
|
|
||||||
this.node.addEventListener("mousedown", this._onMouseDown, false);
|
this.node.addEventListener("mousedown", this._onMouseDown, false);
|
||||||
this.node.addEventListener("select", this._onSelect, false);
|
this.node.addEventListener("select", this._onSelect, false);
|
||||||
|
@ -403,6 +403,9 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
|
||||||
break;
|
break;
|
||||||
case "statusText":
|
case "statusText":
|
||||||
requestItem.attachment.statusText = value;
|
requestItem.attachment.statusText = value;
|
||||||
|
this._updateMenuView(requestItem, key,
|
||||||
|
requestItem.attachment.status + " " +
|
||||||
|
requestItem.attachment.statusText);
|
||||||
break;
|
break;
|
||||||
case "headersSize":
|
case "headersSize":
|
||||||
requestItem.attachment.headersSize = value;
|
requestItem.attachment.headersSize = value;
|
||||||
|
@ -458,18 +461,24 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
|
||||||
let hostPort = NetworkHelper.convertToUnicode(unescape(uri.hostPort));
|
let hostPort = NetworkHelper.convertToUnicode(unescape(uri.hostPort));
|
||||||
|
|
||||||
let template = $("#requests-menu-item-template");
|
let template = $("#requests-menu-item-template");
|
||||||
let requestsMenuItem = template.firstChild.cloneNode(true);
|
let fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
$(".requests-menu-method", requestsMenuItem)
|
$(".requests-menu-method", template).setAttribute("value", aMethod);
|
||||||
.setAttribute("value", aMethod);
|
|
||||||
|
|
||||||
$(".requests-menu-file", requestsMenuItem)
|
let file = $(".requests-menu-file", template);
|
||||||
.setAttribute("value", name + (query ? "?" + query : ""));
|
file.setAttribute("value", name + (query ? "?" + query : ""));
|
||||||
|
file.setAttribute("tooltiptext", name + (query ? "?" + query : ""));
|
||||||
|
|
||||||
$(".requests-menu-domain", requestsMenuItem)
|
let domain = $(".requests-menu-domain", template);
|
||||||
.setAttribute("value", hostPort);
|
domain.setAttribute("value", hostPort);
|
||||||
|
domain.setAttribute("tooltiptext", hostPort);
|
||||||
|
|
||||||
return requestsMenuItem;
|
// Flatten the DOM by removing one redundant box (the template container).
|
||||||
|
for (let node of template.childNodes) {
|
||||||
|
fragment.appendChild(node.cloneNode(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fragment;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -489,21 +498,32 @@ create({ constructor: RequestsMenuView, proto: MenuContainer.prototype }, {
|
||||||
node.setAttribute("code", aValue);
|
node.setAttribute("code", aValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "statusText": {
|
||||||
|
let node = $(".requests-menu-status-and-method", aItem.target);
|
||||||
|
node.setAttribute("tooltiptext", aValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "contentSize": {
|
case "contentSize": {
|
||||||
let size = (aValue / 1024).toFixed(CONTENT_SIZE_DECIMALS);
|
let size = (aValue / 1024).toFixed(CONTENT_SIZE_DECIMALS);
|
||||||
let node = $(".requests-menu-size", aItem.target);
|
let node = $(".requests-menu-size", aItem.target);
|
||||||
node.setAttribute("value", L10N.getFormatStr("networkMenu.size", size));
|
let text = L10N.getFormatStr("networkMenu.sizeKB", size);
|
||||||
|
node.setAttribute("value", text);
|
||||||
|
node.setAttribute("tooltiptext", text);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "mimeType": {
|
case "mimeType": {
|
||||||
let type = aValue.split(";")[0].split("/")[1] || "?";
|
let type = aValue.split(";")[0].split("/")[1] || "?";
|
||||||
let node = $(".requests-menu-type", aItem.target);
|
let node = $(".requests-menu-type", aItem.target);
|
||||||
node.setAttribute("value", CONTENT_MIME_TYPE_ABBREVIATIONS[type] || type);
|
let text = CONTENT_MIME_TYPE_ABBREVIATIONS[type] || type;
|
||||||
|
node.setAttribute("value", text);
|
||||||
|
node.setAttribute("tooltiptext", aValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "totalTime": {
|
case "totalTime": {
|
||||||
let node = $(".requests-menu-timings-total", aItem.target);
|
let node = $(".requests-menu-timings-total", aItem.target);
|
||||||
node.setAttribute("value", L10N.getFormatStr("networkMenu.total", aValue));
|
let text = L10N.getFormatStr("networkMenu.totalMS", aValue);
|
||||||
|
node.setAttribute("value", text);
|
||||||
|
node.setAttribute("tooltiptext", text);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -795,6 +815,7 @@ create({ constructor: NetworkDetailsView, proto: MenuContainer.prototype }, {
|
||||||
if (aData.url) {
|
if (aData.url) {
|
||||||
let unicodeUrl = NetworkHelper.convertToUnicode(unescape(aData.url));
|
let unicodeUrl = NetworkHelper.convertToUnicode(unescape(aData.url));
|
||||||
$("#headers-summary-url-value").setAttribute("value", unicodeUrl);
|
$("#headers-summary-url-value").setAttribute("value", unicodeUrl);
|
||||||
|
$("#headers-summary-url-value").setAttribute("tooltiptext", unicodeUrl);
|
||||||
$("#headers-summary-url").removeAttribute("hidden");
|
$("#headers-summary-url").removeAttribute("hidden");
|
||||||
} else {
|
} else {
|
||||||
$("#headers-summary-url").setAttribute("hidden", "true");
|
$("#headers-summary-url").setAttribute("hidden", "true");
|
||||||
|
@ -858,7 +879,7 @@ create({ constructor: NetworkDetailsView, proto: MenuContainer.prototype }, {
|
||||||
*/
|
*/
|
||||||
_addHeaders: function NVND__addHeaders(aName, aResponse) {
|
_addHeaders: function NVND__addHeaders(aName, aResponse) {
|
||||||
let kb = (aResponse.headersSize / 1024).toFixed(HEADERS_SIZE_DECIMALS);
|
let kb = (aResponse.headersSize / 1024).toFixed(HEADERS_SIZE_DECIMALS);
|
||||||
let size = L10N.getFormatStr("networkMenu.size", kb);
|
let size = L10N.getFormatStr("networkMenu.sizeKB", kb);
|
||||||
let headersScope = this._headers.addScope(aName + " (" + size + ")");
|
let headersScope = this._headers.addScope(aName + " (" + size + ")");
|
||||||
headersScope.expanded = true;
|
headersScope.expanded = true;
|
||||||
|
|
||||||
|
@ -1083,32 +1104,32 @@ create({ constructor: NetworkDetailsView, proto: MenuContainer.prototype }, {
|
||||||
$("#timings-summary-blocked .requests-menu-timings-box")
|
$("#timings-summary-blocked .requests-menu-timings-box")
|
||||||
.setAttribute("width", blocked * scale);
|
.setAttribute("width", blocked * scale);
|
||||||
$("#timings-summary-blocked .requests-menu-timings-total")
|
$("#timings-summary-blocked .requests-menu-timings-total")
|
||||||
.setAttribute("value", L10N.getFormatStr("networkMenu.total", blocked));
|
.setAttribute("value", L10N.getFormatStr("networkMenu.totalMS", blocked));
|
||||||
|
|
||||||
$("#timings-summary-dns .requests-menu-timings-box")
|
$("#timings-summary-dns .requests-menu-timings-box")
|
||||||
.setAttribute("width", dns * scale);
|
.setAttribute("width", dns * scale);
|
||||||
$("#timings-summary-dns .requests-menu-timings-total")
|
$("#timings-summary-dns .requests-menu-timings-total")
|
||||||
.setAttribute("value", L10N.getFormatStr("networkMenu.total", dns));
|
.setAttribute("value", L10N.getFormatStr("networkMenu.totalMS", dns));
|
||||||
|
|
||||||
$("#timings-summary-connect .requests-menu-timings-box")
|
$("#timings-summary-connect .requests-menu-timings-box")
|
||||||
.setAttribute("width", connect * scale);
|
.setAttribute("width", connect * scale);
|
||||||
$("#timings-summary-connect .requests-menu-timings-total")
|
$("#timings-summary-connect .requests-menu-timings-total")
|
||||||
.setAttribute("value", L10N.getFormatStr("networkMenu.total", connect));
|
.setAttribute("value", L10N.getFormatStr("networkMenu.totalMS", connect));
|
||||||
|
|
||||||
$("#timings-summary-send .requests-menu-timings-box")
|
$("#timings-summary-send .requests-menu-timings-box")
|
||||||
.setAttribute("width", send * scale);
|
.setAttribute("width", send * scale);
|
||||||
$("#timings-summary-send .requests-menu-timings-total")
|
$("#timings-summary-send .requests-menu-timings-total")
|
||||||
.setAttribute("value", L10N.getFormatStr("networkMenu.total", send));
|
.setAttribute("value", L10N.getFormatStr("networkMenu.totalMS", send));
|
||||||
|
|
||||||
$("#timings-summary-wait .requests-menu-timings-box")
|
$("#timings-summary-wait .requests-menu-timings-box")
|
||||||
.setAttribute("width", wait * scale);
|
.setAttribute("width", wait * scale);
|
||||||
$("#timings-summary-wait .requests-menu-timings-total")
|
$("#timings-summary-wait .requests-menu-timings-total")
|
||||||
.setAttribute("value", L10N.getFormatStr("networkMenu.total", wait));
|
.setAttribute("value", L10N.getFormatStr("networkMenu.totalMS", wait));
|
||||||
|
|
||||||
$("#timings-summary-receive .requests-menu-timings-box")
|
$("#timings-summary-receive .requests-menu-timings-box")
|
||||||
.setAttribute("width", receive * scale);
|
.setAttribute("width", receive * scale);
|
||||||
$("#timings-summary-receive .requests-menu-timings-total")
|
$("#timings-summary-receive .requests-menu-timings-total")
|
||||||
.setAttribute("value", L10N.getFormatStr("networkMenu.total", receive));
|
.setAttribute("value", L10N.getFormatStr("networkMenu.totalMS", receive));
|
||||||
|
|
||||||
$("#timings-summary-dns .requests-menu-timings-box")
|
$("#timings-summary-dns .requests-menu-timings-box")
|
||||||
.style.transform = "translateX(" + (scale * blocked) + "px)";
|
.style.transform = "translateX(" + (scale * blocked) + "px)";
|
||||||
|
|
|
@ -55,35 +55,33 @@
|
||||||
<label class="plain requests-menu-empty-notice"
|
<label class="plain requests-menu-empty-notice"
|
||||||
value="&netmonitorUI.emptyNotice;"/>
|
value="&netmonitorUI.emptyNotice;"/>
|
||||||
<vbox id="requests-menu-contents" flex="1">
|
<vbox id="requests-menu-contents" flex="1">
|
||||||
<template id="requests-menu-item-template">
|
<hbox id="requests-menu-item-template" hidden="true">
|
||||||
<hbox class="requests-menu-item">
|
<hbox class="requests-menu-subitem requests-menu-status-and-method"
|
||||||
<hbox class="requests-menu-subitem requests-menu-status-and-method"
|
align="center">
|
||||||
|
<hbox class="requests-menu-status"/>
|
||||||
|
<label class="plain requests-menu-method"
|
||||||
|
crop="end"
|
||||||
|
flex="1"/>
|
||||||
|
</hbox>
|
||||||
|
<label class="plain requests-menu-subitem requests-menu-file"
|
||||||
|
crop="end"/>
|
||||||
|
<label class="plain requests-menu-subitem requests-menu-domain"
|
||||||
|
crop="end"/>
|
||||||
|
<label class="plain requests-menu-subitem requests-menu-type"
|
||||||
|
crop="end"/>
|
||||||
|
<label class="plain requests-menu-subitem requests-menu-size"
|
||||||
|
crop="end"/>
|
||||||
|
<hbox class="requests-menu-subitem requests-menu-waterfall"
|
||||||
|
align="center"
|
||||||
|
flex="1">
|
||||||
|
<hbox class="requests-menu-timings"
|
||||||
align="center">
|
align="center">
|
||||||
<hbox class="requests-menu-status"/>
|
<hbox class="start requests-menu-timings-cap" hidden="true"/>
|
||||||
<label class="plain requests-menu-method"
|
<hbox class="end requests-menu-timings-cap" hidden="true"/>
|
||||||
crop="end"
|
<label class="plain requests-menu-timings-total"/>
|
||||||
flex="1"/>
|
|
||||||
</hbox>
|
|
||||||
<label class="plain requests-menu-subitem requests-menu-file"
|
|
||||||
crop="end"/>
|
|
||||||
<label class="plain requests-menu-subitem requests-menu-domain"
|
|
||||||
crop="end"/>
|
|
||||||
<label class="plain requests-menu-subitem requests-menu-type"
|
|
||||||
crop="end"/>
|
|
||||||
<label class="plain requests-menu-subitem requests-menu-size"
|
|
||||||
crop="end"/>
|
|
||||||
<hbox class="requests-menu-subitem requests-menu-waterfall"
|
|
||||||
align="center"
|
|
||||||
flex="1">
|
|
||||||
<hbox class="requests-menu-timings"
|
|
||||||
align="center">
|
|
||||||
<hbox class="start requests-menu-timings-cap" hidden="true"/>
|
|
||||||
<hbox class="end requests-menu-timings-cap" hidden="true"/>
|
|
||||||
<label class="plain requests-menu-timings-total"/>
|
|
||||||
</hbox>
|
|
||||||
</hbox>
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
</template>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ function test() {
|
||||||
initNetMonitor(CONTENT_TYPE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
initNetMonitor(CONTENT_TYPE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||||
info("Starting test... ");
|
info("Starting test... ");
|
||||||
|
|
||||||
let { document, SourceEditor, NetMonitorView } = aMonitor.panelWin;
|
let { document, L10N, SourceEditor, NetMonitorView } = aMonitor.panelWin;
|
||||||
let { RequestsMenu } = NetMonitorView;
|
let { RequestsMenu } = NetMonitorView;
|
||||||
|
|
||||||
RequestsMenu.lazyUpdate = false;
|
RequestsMenu.lazyUpdate = false;
|
||||||
|
@ -18,43 +18,55 @@ function test() {
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
|
||||||
"GET", CONTENT_TYPE_SJS + "?fmt=xml", {
|
"GET", CONTENT_TYPE_SJS + "?fmt=xml", {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
type: "xml",
|
type: "xml",
|
||||||
size: "0.04kb",
|
fullMimeType: "text/xml; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.04),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
|
||||||
"GET", CONTENT_TYPE_SJS + "?fmt=css", {
|
"GET", CONTENT_TYPE_SJS + "?fmt=css", {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
type: "css",
|
type: "css",
|
||||||
size: "0.03kb",
|
fullMimeType: "text/css; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.03),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(2),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(2),
|
||||||
"GET", CONTENT_TYPE_SJS + "?fmt=js", {
|
"GET", CONTENT_TYPE_SJS + "?fmt=js", {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
type: "js",
|
type: "js",
|
||||||
size: "0.03kb",
|
fullMimeType: "application/javascript; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.03),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3),
|
||||||
"GET", CONTENT_TYPE_SJS + "?fmt=json", {
|
"GET", CONTENT_TYPE_SJS + "?fmt=json", {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
type: "json",
|
type: "json",
|
||||||
size: "0.03kb",
|
fullMimeType: "application/json; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.03),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
|
||||||
"GET", CONTENT_TYPE_SJS + "?fmt=bogus", {
|
"GET", CONTENT_TYPE_SJS + "?fmt=bogus", {
|
||||||
status: 404,
|
status: 404,
|
||||||
|
statusText: "Not Found",
|
||||||
type: "html",
|
type: "html",
|
||||||
size: "0.02kb",
|
fullMimeType: "text/html; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.02),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5),
|
||||||
"GET", TEST_IMAGE, {
|
"GET", TEST_IMAGE, {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
statusText: "OK",
|
||||||
type: "png",
|
type: "png",
|
||||||
size: "0.76kb",
|
fullMimeType: "image/png",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.76),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,15 +19,19 @@ function test() {
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(0),
|
||||||
"POST", SIMPLE_SJS + "?foo=bar&baz=42&type=urlencoded", {
|
"POST", SIMPLE_SJS + "?foo=bar&baz=42&type=urlencoded", {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
statusText: "Och Aye",
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.01kb",
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.01),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(1),
|
||||||
"POST", SIMPLE_SJS + "?foo=bar&baz=42&type=multipart", {
|
"POST", SIMPLE_SJS + "?foo=bar&baz=42&type=multipart", {
|
||||||
status: 200,
|
status: 200,
|
||||||
|
statusText: "Och Aye",
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.01kb",
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.01),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ function test() {
|
||||||
stringBundle.GetStringFromName("netmonitor.label"),
|
stringBundle.GetStringFromName("netmonitor.label"),
|
||||||
"The getStr() method didn't return the expected string.");
|
"The getStr() method didn't return the expected string.");
|
||||||
|
|
||||||
is(L10N.getFormatStr("networkMenu.total", "foo"),
|
is(L10N.getFormatStr("networkMenu.totalMS", "foo"),
|
||||||
stringBundle.formatStringFromName("networkMenu.total", ["foo"], 1),
|
stringBundle.formatStringFromName("networkMenu.totalMS", ["foo"], 1),
|
||||||
"The getFormatStr() method didn't return the expected string.");
|
"The getFormatStr() method didn't return the expected string.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ function test() {
|
||||||
initNetMonitor(SIMPLE_SJS).then(([aTab, aDebuggee, aMonitor]) => {
|
initNetMonitor(SIMPLE_SJS).then(([aTab, aDebuggee, aMonitor]) => {
|
||||||
info("Starting test... ");
|
info("Starting test... ");
|
||||||
|
|
||||||
let { NetMonitorView } = aMonitor.panelWin;
|
let { L10N, NetMonitorView } = aMonitor.panelWin;
|
||||||
let { RequestsMenu } = NetMonitorView;
|
let { RequestsMenu } = NetMonitorView;
|
||||||
|
|
||||||
RequestsMenu.lazyUpdate = false;
|
RequestsMenu.lazyUpdate = false;
|
||||||
|
@ -148,7 +148,8 @@ function test() {
|
||||||
"The headersSize attachment has an incorrect value.");
|
"The headersSize attachment has an incorrect value.");
|
||||||
|
|
||||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||||
status: "200"
|
status: "200",
|
||||||
|
statusText: "Och Aye"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -162,7 +163,8 @@ function test() {
|
||||||
|
|
||||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.01kb"
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.01),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -180,7 +182,8 @@ function test() {
|
||||||
|
|
||||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.01kb"
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.01),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,8 @@ function test() {
|
||||||
|
|
||||||
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"),
|
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("value"),
|
||||||
SIMPLE_SJS, "The url summary value is incorrect.");
|
SIMPLE_SJS, "The url summary value is incorrect.");
|
||||||
|
is(tabpanel.querySelector("#headers-summary-url-value").getAttribute("tooltiptext"),
|
||||||
|
SIMPLE_SJS, "The url summary tooltiptext is incorrect.");
|
||||||
is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"),
|
is(tabpanel.querySelector("#headers-summary-method-value").getAttribute("value"),
|
||||||
"GET", "The method summary value is incorrect.");
|
"GET", "The method summary value is incorrect.");
|
||||||
is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("code"),
|
is(tabpanel.querySelector("#headers-summary-status-circle").getAttribute("code"),
|
||||||
|
@ -71,7 +73,7 @@ function test() {
|
||||||
|
|
||||||
is(responseScope.querySelector(".name").getAttribute("value"),
|
is(responseScope.querySelector(".name").getAttribute("value"),
|
||||||
L10N.getStr("responseHeaders") + " (" +
|
L10N.getStr("responseHeaders") + " (" +
|
||||||
L10N.getFormatStr("networkMenu.size", "0.169") + ")",
|
L10N.getFormatStr("networkMenu.sizeKB", "0.169") + ")",
|
||||||
"The response headers scope doesn't have the correct title.");
|
"The response headers scope doesn't have the correct title.");
|
||||||
|
|
||||||
ok(requestScope.querySelector(".name").getAttribute("value").contains(
|
ok(requestScope.querySelector(".name").getAttribute("value").contains(
|
||||||
|
@ -196,27 +198,27 @@ function test() {
|
||||||
"The timings tab in the network details pane should be selected.");
|
"The timings tab in the network details pane should be selected.");
|
||||||
|
|
||||||
ok(tabpanel.querySelector("#timings-summary-blocked .requests-menu-timings-total")
|
ok(tabpanel.querySelector("#timings-summary-blocked .requests-menu-timings-total")
|
||||||
.getAttribute("value").match(/[0-9]+ms$/),
|
.getAttribute("value").match(/[0-9]+/),
|
||||||
"The blocked timing info does not appear to be correct.");
|
"The blocked timing info does not appear to be correct.");
|
||||||
|
|
||||||
ok(tabpanel.querySelector("#timings-summary-dns .requests-menu-timings-total")
|
ok(tabpanel.querySelector("#timings-summary-dns .requests-menu-timings-total")
|
||||||
.getAttribute("value").match(/[0-9]+ms$/),
|
.getAttribute("value").match(/[0-9]+/),
|
||||||
"The dns timing info does not appear to be correct.");
|
"The dns timing info does not appear to be correct.");
|
||||||
|
|
||||||
ok(tabpanel.querySelector("#timings-summary-connect .requests-menu-timings-total")
|
ok(tabpanel.querySelector("#timings-summary-connect .requests-menu-timings-total")
|
||||||
.getAttribute("value").match(/[0-9]+ms$/),
|
.getAttribute("value").match(/[0-9]+/),
|
||||||
"The connect timing info does not appear to be correct.");
|
"The connect timing info does not appear to be correct.");
|
||||||
|
|
||||||
ok(tabpanel.querySelector("#timings-summary-send .requests-menu-timings-total")
|
ok(tabpanel.querySelector("#timings-summary-send .requests-menu-timings-total")
|
||||||
.getAttribute("value").match(/[0-9]+ms$/),
|
.getAttribute("value").match(/[0-9]+/),
|
||||||
"The send timing info does not appear to be correct.");
|
"The send timing info does not appear to be correct.");
|
||||||
|
|
||||||
ok(tabpanel.querySelector("#timings-summary-wait .requests-menu-timings-total")
|
ok(tabpanel.querySelector("#timings-summary-wait .requests-menu-timings-total")
|
||||||
.getAttribute("value").match(/[0-9]+ms$/),
|
.getAttribute("value").match(/[0-9]+/),
|
||||||
"The wait timing info does not appear to be correct.");
|
"The wait timing info does not appear to be correct.");
|
||||||
|
|
||||||
ok(tabpanel.querySelector("#timings-summary-receive .requests-menu-timings-total")
|
ok(tabpanel.querySelector("#timings-summary-receive .requests-menu-timings-total")
|
||||||
.getAttribute("value").match(/[0-9]+ms$/),
|
.getAttribute("value").match(/[0-9]+/),
|
||||||
"The receive timing info does not appear to be correct.");
|
"The receive timing info does not appear to be correct.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,36 +21,46 @@ function test() {
|
||||||
verifyRequestItemTarget(requestItems[0] = RequestsMenu.getItemAtIndex(0),
|
verifyRequestItemTarget(requestItems[0] = RequestsMenu.getItemAtIndex(0),
|
||||||
"GET", STATUS_CODES_SJS + "?sts=100", {
|
"GET", STATUS_CODES_SJS + "?sts=100", {
|
||||||
status: 101,
|
status: 101,
|
||||||
|
statusText: "Switching Protocols",
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.00kb",
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", "0.00"),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(requestItems[1] = RequestsMenu.getItemAtIndex(1),
|
verifyRequestItemTarget(requestItems[1] = RequestsMenu.getItemAtIndex(1),
|
||||||
"GET", STATUS_CODES_SJS + "?sts=200", {
|
"GET", STATUS_CODES_SJS + "?sts=200", {
|
||||||
status: 202,
|
status: 202,
|
||||||
|
statusText: "Created",
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.02kb",
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.02),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(requestItems[2] = RequestsMenu.getItemAtIndex(2),
|
verifyRequestItemTarget(requestItems[2] = RequestsMenu.getItemAtIndex(2),
|
||||||
"GET", STATUS_CODES_SJS + "?sts=300", {
|
"GET", STATUS_CODES_SJS + "?sts=300", {
|
||||||
status: 303,
|
status: 303,
|
||||||
|
statusText: "See Other",
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.00kb",
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", "0.00"),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(requestItems[3] = RequestsMenu.getItemAtIndex(3),
|
verifyRequestItemTarget(requestItems[3] = RequestsMenu.getItemAtIndex(3),
|
||||||
"GET", STATUS_CODES_SJS + "?sts=400", {
|
"GET", STATUS_CODES_SJS + "?sts=400", {
|
||||||
status: 404,
|
status: 404,
|
||||||
|
statusText: "Not Found",
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.02kb",
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.02),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(requestItems[4] = RequestsMenu.getItemAtIndex(4),
|
verifyRequestItemTarget(requestItems[4] = RequestsMenu.getItemAtIndex(4),
|
||||||
"GET", STATUS_CODES_SJS + "?sts=500", {
|
"GET", STATUS_CODES_SJS + "?sts=500", {
|
||||||
status: 501,
|
status: 501,
|
||||||
|
statusText: "Not Implemented",
|
||||||
type: "plain",
|
type: "plain",
|
||||||
size: "0.02kb",
|
fullMimeType: "text/plain; charset=utf-8",
|
||||||
|
size: L10N.getFormatStr("networkMenu.sizeKB", 0.02),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
||||||
info("> Verifying: " + aMethod + " " + aUrl + " " + aData.toSource());
|
info("> Verifying: " + aMethod + " " + aUrl + " " + aData.toSource());
|
||||||
info("> Request: " + aRequestItem.attachment.toSource());
|
info("> Request: " + aRequestItem.attachment.toSource());
|
||||||
|
|
||||||
let { status, type, size, time } = aData;
|
let { status, statusText, type, fullMimeType, size, time } = aData;
|
||||||
let { attachment, target } = aRequestItem
|
let { attachment, target } = aRequestItem
|
||||||
|
|
||||||
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
||||||
|
@ -197,28 +197,44 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) {
|
||||||
|
|
||||||
is(target.querySelector(".requests-menu-file").getAttribute("value"),
|
is(target.querySelector(".requests-menu-file").getAttribute("value"),
|
||||||
name + (query ? "?" + query : ""), "The displayed file is incorrect.");
|
name + (query ? "?" + query : ""), "The displayed file is incorrect.");
|
||||||
|
is(target.querySelector(".requests-menu-file").getAttribute("tooltiptext"),
|
||||||
|
name + (query ? "?" + query : ""), "The tooltip file is incorrect.");
|
||||||
|
|
||||||
is(target.querySelector(".requests-menu-domain").getAttribute("value"),
|
is(target.querySelector(".requests-menu-domain").getAttribute("value"),
|
||||||
hostPort, "The displayed domain is incorrect.");
|
hostPort, "The displayed domain is incorrect.");
|
||||||
|
is(target.querySelector(".requests-menu-domain").getAttribute("tooltiptext"),
|
||||||
|
hostPort, "The tooltip domain is incorrect.");
|
||||||
|
|
||||||
if (status !== undefined) {
|
if (status !== undefined) {
|
||||||
let value = target.querySelector(".requests-menu-status").getAttribute("code");
|
let value = target.querySelector(".requests-menu-status").getAttribute("code");
|
||||||
|
let tooltip = target.querySelector(".requests-menu-status-and-method").getAttribute("tooltiptext");
|
||||||
info("Displayed status: " + value);
|
info("Displayed status: " + value);
|
||||||
|
info("Tooltip status: " + tooltip);
|
||||||
is(value, status, "The displayed status is incorrect.");
|
is(value, status, "The displayed status is incorrect.");
|
||||||
|
is(tooltip, status + " " + statusText, "The tooltip status is incorrect.");
|
||||||
}
|
}
|
||||||
if (type !== undefined) {
|
if (type !== undefined) {
|
||||||
let value = target.querySelector(".requests-menu-type").getAttribute("value");
|
let value = target.querySelector(".requests-menu-type").getAttribute("value");
|
||||||
|
let tooltip = target.querySelector(".requests-menu-type").getAttribute("tooltiptext");
|
||||||
info("Displayed type: " + value);
|
info("Displayed type: " + value);
|
||||||
|
info("Tooltip type: " + tooltip);
|
||||||
is(value, type, "The displayed type is incorrect.");
|
is(value, type, "The displayed type is incorrect.");
|
||||||
|
is(tooltip, fullMimeType, "The tooltip type is incorrect.");
|
||||||
}
|
}
|
||||||
if (size !== undefined) {
|
if (size !== undefined) {
|
||||||
let value = target.querySelector(".requests-menu-size").getAttribute("value");
|
let value = target.querySelector(".requests-menu-size").getAttribute("value");
|
||||||
|
let tooltip = target.querySelector(".requests-menu-size").getAttribute("tooltiptext");
|
||||||
info("Displayed size: " + value);
|
info("Displayed size: " + value);
|
||||||
|
info("Tooltip size: " + tooltip);
|
||||||
is(value, size, "The displayed size is incorrect.");
|
is(value, size, "The displayed size is incorrect.");
|
||||||
|
is(tooltip, size, "The tooltip size is incorrect.");
|
||||||
}
|
}
|
||||||
if (time !== undefined) {
|
if (time !== undefined) {
|
||||||
let value = target.querySelector(".requests-menu-timings-total").getAttribute("value");
|
let value = target.querySelector(".requests-menu-timings-total").getAttribute("value");
|
||||||
|
let tooltip = target.querySelector(".requests-menu-timings-total").getAttribute("tooltiptext");
|
||||||
info("Displayed time: " + value);
|
info("Displayed time: " + value);
|
||||||
|
info("Tooltip time: " + tooltip);
|
||||||
ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is incorrect.");
|
ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is incorrect.");
|
||||||
|
ok(~~(tooltip.match(/[0-9]+/)) >= 0, "The tooltip time is incorrect.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,16 @@ XPCOMUtils.defineLazyGetter(this, "DebuggerServer", function () {
|
||||||
return DebuggerServer;
|
return DebuggerServer;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data structure that contains information that has
|
||||||
|
* to be shared between separate ProfilerController
|
||||||
|
* instances.
|
||||||
|
*/
|
||||||
|
const sharedData = {
|
||||||
|
startTime: 0,
|
||||||
|
data: new WeakMap(),
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a structure representing an individual profile.
|
* Makes a structure representing an individual profile.
|
||||||
*/
|
*/
|
||||||
|
@ -29,163 +39,51 @@ function makeProfile(name) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Three functions below all operate with sharedData
|
||||||
* Object acting as a mediator between the ProfilerController and
|
// structure defined above. They should be self-explanatory.
|
||||||
* DebuggerServer.
|
|
||||||
*/
|
function addTarget(target) {
|
||||||
function ProfilerConnection(client) {
|
sharedData.data.set(target, new Map());
|
||||||
this.client = client;
|
|
||||||
this.startTime = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfilerConnection.prototype = {
|
function getProfiles(target) {
|
||||||
actor: null,
|
return sharedData.data.get(target);
|
||||||
startTime: null,
|
}
|
||||||
|
|
||||||
/**
|
function getCurrentTime() {
|
||||||
* Returns how many milliseconds have passed since the connection
|
return (new Date()).getTime() - sharedData.startTime;
|
||||||
* was started (start time is specificed by the startTime property).
|
}
|
||||||
*
|
|
||||||
* @return number
|
|
||||||
*/
|
|
||||||
get currentTime() {
|
|
||||||
return (new Date()).getTime() - this.startTime;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects to a debugee and executes a callback when ready.
|
* Object to control the JavaScript Profiler over the remote
|
||||||
*
|
* debugging protocol.
|
||||||
* @param function aCallback
|
*
|
||||||
* Function to be called once we're connected to the client.
|
* @param Target target
|
||||||
*/
|
* A target object as defined in Target.jsm
|
||||||
connect: function PCn_connect(aCallback) {
|
*/
|
||||||
this.client.listTabs(function (aResponse) {
|
function ProfilerController(target) {
|
||||||
this.actor = aResponse.profilerActor;
|
this.target = target;
|
||||||
aCallback();
|
this.client = target.client;
|
||||||
}.bind(this));
|
this.isConnected = false;
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
addTarget(target);
|
||||||
* Sends a message to check if the profiler is currently active.
|
|
||||||
*
|
|
||||||
* @param function aCallback
|
|
||||||
* Function to be called once we have a response from
|
|
||||||
* the client. It will be called with a single argument
|
|
||||||
* containing a response object.
|
|
||||||
*/
|
|
||||||
isActive: function PCn_isActive(aCallback) {
|
|
||||||
var message = { to: this.actor, type: "isActive" };
|
|
||||||
this.client.request(message, aCallback);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
// Chrome debugging targets have already obtained a reference
|
||||||
* Sends a message to start a profiler.
|
// to the profiler actor.
|
||||||
*
|
if (target.chrome) {
|
||||||
* @param function aCallback
|
this.isConnected = true;
|
||||||
* Function to be called once the profiler is running.
|
this.actor = target.form.profilerActor;
|
||||||
* It will be called with a single argument containing
|
|
||||||
* a response object.
|
|
||||||
*/
|
|
||||||
startProfiler: function PCn_startProfiler(aCallback) {
|
|
||||||
var message = {
|
|
||||||
to: this.actor,
|
|
||||||
type: "startProfiler",
|
|
||||||
entries: 1000000,
|
|
||||||
interval: 1,
|
|
||||||
features: ["js"],
|
|
||||||
};
|
|
||||||
|
|
||||||
this.client.request(message, function () {
|
|
||||||
// Record the current time so we could split profiler data
|
|
||||||
// in chunks later.
|
|
||||||
this.startTime = (new Date()).getTime();
|
|
||||||
aCallback.apply(null, Array.slice(arguments));
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a message to stop a profiler.
|
|
||||||
*
|
|
||||||
* @param function aCallback
|
|
||||||
* Function to be called once the profiler is idle.
|
|
||||||
* It will be called with a single argument containing
|
|
||||||
* a response object.
|
|
||||||
*/
|
|
||||||
stopProfiler: function PCn_stopProfiler(aCallback) {
|
|
||||||
var message = { to: this.actor, type: "stopProfiler" };
|
|
||||||
this.client.request(message, aCallback);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a message to get the generated profile data.
|
|
||||||
*
|
|
||||||
* @param function aCallback
|
|
||||||
* Function to be called once we have the data.
|
|
||||||
* It will be called with a single argument containing
|
|
||||||
* a response object.
|
|
||||||
*/
|
|
||||||
getProfileData: function PCn_getProfileData(aCallback) {
|
|
||||||
var message = { to: this.actor, type: "getProfile" };
|
|
||||||
this.client.request(message, aCallback);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleanup.
|
|
||||||
*/
|
|
||||||
destroy: function PCn_destroy() {
|
|
||||||
this.client = null;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Object defining the profiler controller components.
|
|
||||||
*/
|
|
||||||
function ProfilerController(target) {
|
|
||||||
this.profiler = new ProfilerConnection(target.client);
|
|
||||||
this.profiles = new Map();
|
|
||||||
|
|
||||||
// Chrome debugging targets have already obtained a reference to the
|
|
||||||
// profiler actor.
|
|
||||||
this._connected = !!target.chrome;
|
|
||||||
|
|
||||||
if (target.chrome) {
|
|
||||||
this.profiler.actor = target.form.profilerActor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfilerController.prototype = {
|
ProfilerController.prototype = {
|
||||||
/**
|
/**
|
||||||
* Connects to the client unless we're already connected.
|
* Return a map of profile results for the current target.
|
||||||
*
|
*
|
||||||
* @param function aCallback
|
* @return Map
|
||||||
* Function to be called once we're connected. If
|
|
||||||
* the controller is already connected, this function
|
|
||||||
* will be called immediately (synchronously).
|
|
||||||
*/
|
*/
|
||||||
connect: function (aCallback) {
|
get profiles() {
|
||||||
if (this._connected) {
|
return getProfiles(this.target);
|
||||||
return void aCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.profiler.connect(function onConnect() {
|
|
||||||
this._connected = true;
|
|
||||||
aCallback();
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the profiler is active.
|
|
||||||
*
|
|
||||||
* @param function aCallback
|
|
||||||
* Function to be called with a response from the
|
|
||||||
* client. It will be called with two arguments:
|
|
||||||
* an error object (may be null) and a boolean
|
|
||||||
* value indicating if the profiler is active or not.
|
|
||||||
*/
|
|
||||||
isActive: function PC_isActive(aCallback) {
|
|
||||||
this.profiler.isActive(function onActive(aResponse) {
|
|
||||||
aCallback(aResponse.error, aResponse.isActive);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,6 +97,56 @@ ProfilerController.prototype = {
|
||||||
return profile.timeStarted !== null && profile.timeEnded === null;
|
return profile.timeStarted !== null && profile.timeEnded === null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to the client unless we're already connected.
|
||||||
|
*
|
||||||
|
* @param function cb
|
||||||
|
* Function to be called once we're connected. If
|
||||||
|
* the controller is already connected, this function
|
||||||
|
* will be called immediately (synchronously).
|
||||||
|
*/
|
||||||
|
connect: function (cb) {
|
||||||
|
if (this.isConnected) {
|
||||||
|
return void cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client.listTabs((resp) => {
|
||||||
|
this.actor = resp.profilerActor;
|
||||||
|
this.isConnected = true;
|
||||||
|
cb();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds actor and type information to data and sends the request over
|
||||||
|
* the remote debugging protocol.
|
||||||
|
*
|
||||||
|
* @param string type
|
||||||
|
* Method to call on the other side
|
||||||
|
* @param object data
|
||||||
|
* Data to send with the request
|
||||||
|
* @param function cb
|
||||||
|
* A callback function
|
||||||
|
*/
|
||||||
|
request: function (type, data, cb) {
|
||||||
|
data.to = this.actor;
|
||||||
|
data.type = type;
|
||||||
|
this.client.request(data, cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the profiler is active.
|
||||||
|
*
|
||||||
|
* @param function cb
|
||||||
|
* Function to be called with a response from the
|
||||||
|
* client. It will be called with two arguments:
|
||||||
|
* an error object (may be null) and a boolean
|
||||||
|
* value indicating if the profiler is active or not.
|
||||||
|
*/
|
||||||
|
isActive: function (cb) {
|
||||||
|
this.request("isActive", {}, (resp) => cb(resp.error, resp.isActive));
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new profile and starts the profiler, if needed.
|
* Creates a new profile and starts the profiler, if needed.
|
||||||
*
|
*
|
||||||
|
@ -214,35 +162,42 @@ ProfilerController.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let profiler = this.profiler;
|
|
||||||
let profile = makeProfile(name);
|
let profile = makeProfile(name);
|
||||||
this.profiles.set(name, profile);
|
this.profiles.set(name, profile);
|
||||||
|
|
||||||
|
|
||||||
// If profile is already running, no need to do anything.
|
// If profile is already running, no need to do anything.
|
||||||
if (this.isProfileRecording(profile)) {
|
if (this.isProfileRecording(profile)) {
|
||||||
return void cb();
|
return void cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isActive(function (err, isActive) {
|
this.isActive((err, isActive) => {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
profile.timeStarted = profiler.currentTime;
|
profile.timeStarted = getCurrentTime();
|
||||||
return void cb();
|
return void cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
profiler.startProfiler(function onStart(aResponse) {
|
let params = {
|
||||||
if (aResponse.error) {
|
entries: 1000000,
|
||||||
return void cb(aResponse.error);
|
interval: 1,
|
||||||
|
features: ["js"],
|
||||||
|
};
|
||||||
|
|
||||||
|
this.request("startProfiler", params, (resp) => {
|
||||||
|
if (resp.error) {
|
||||||
|
return void cb(resp.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.timeStarted = profiler.currentTime;
|
sharedData.startTime = (new Date()).getTime();
|
||||||
|
profile.timeStarted = getCurrentTime();
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the profiler.
|
* Stops the profiler. NOTE, that we don't stop the actual
|
||||||
|
* SPS Profiler here. It will be stopped as soon as all
|
||||||
|
* clients disconnect from the profiler actor.
|
||||||
*
|
*
|
||||||
* @param string name
|
* @param string name
|
||||||
* Name of the profile that needs to be stopped.
|
* Name of the profile that needs to be stopped.
|
||||||
|
@ -252,50 +207,36 @@ ProfilerController.prototype = {
|
||||||
* argument: an error object (may be null).
|
* argument: an error object (may be null).
|
||||||
*/
|
*/
|
||||||
stop: function PC_stop(name, cb) {
|
stop: function PC_stop(name, cb) {
|
||||||
let profiler = this.profiler;
|
if (!this.profiles.has(name)) {
|
||||||
let profile = this.profiles.get(name);
|
|
||||||
|
|
||||||
if (!profile || !this.isProfileRecording(profile)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isRecording = function () {
|
let profile = this.profiles.get(name);
|
||||||
for (let [ name, profile ] of this.profiles) {
|
if (!this.isProfileRecording(profile)) {
|
||||||
if (this.isProfileRecording(profile)) {
|
return;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
this.request("getProfile", {}, (resp) => {
|
||||||
|
if (resp.error) {
|
||||||
|
Cu.reportError("Failed to fetch profile data.");
|
||||||
|
return void cb(resp.error, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
let data = resp.profile;
|
||||||
}.bind(this);
|
profile.timeEnded = getCurrentTime();
|
||||||
|
|
||||||
let onStop = function (data) {
|
// Filter out all samples that fall out of current
|
||||||
if (isRecording()) {
|
// profile's range.
|
||||||
return void cb(null, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
profiler.stopProfiler(function onStopProfiler(response) {
|
data.threads = data.threads.map((thread) => {
|
||||||
cb(response.error, data);
|
let samples = thread.samples.filter((sample) => {
|
||||||
});
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
profiler.getProfileData(function onData(aResponse) {
|
|
||||||
if (aResponse.error) {
|
|
||||||
Cu.reportError("Failed to fetch profile data before stopping the profiler.");
|
|
||||||
return void cb(aResponse.error, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = aResponse.profile;
|
|
||||||
profile.timeEnded = profiler.currentTime;
|
|
||||||
|
|
||||||
data.threads = data.threads.map(function (thread) {
|
|
||||||
let samples = thread.samples.filter(function (sample) {
|
|
||||||
return sample.time >= profile.timeStarted;
|
return sample.time >= profile.timeStarted;
|
||||||
});
|
});
|
||||||
|
|
||||||
return { samples: samples };
|
return { samples: samples };
|
||||||
});
|
});
|
||||||
|
|
||||||
onStop(data);
|
cb(null, data);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -303,7 +244,8 @@ ProfilerController.prototype = {
|
||||||
* Cleanup.
|
* Cleanup.
|
||||||
*/
|
*/
|
||||||
destroy: function PC_destroy() {
|
destroy: function PC_destroy() {
|
||||||
this.profiler.destroy();
|
this.client = null;
|
||||||
this.profiler = null;
|
this.target = null;
|
||||||
|
this.actor = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@ MOCHITEST_BROWSER_TESTS = \
|
||||||
browser_profiler_run.js \
|
browser_profiler_run.js \
|
||||||
browser_profiler_controller.js \
|
browser_profiler_controller.js \
|
||||||
browser_profiler_bug_830664_multiple_profiles.js \
|
browser_profiler_bug_830664_multiple_profiles.js \
|
||||||
|
browser_profiler_bug_855244_multiple_tabs.js \
|
||||||
head.js \
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
const URL = "data:text/html;charset=utf8,<p>JavaScript Profiler test</p>";
|
||||||
|
|
||||||
|
let gTab1, gPanel1;
|
||||||
|
let gTab2, gPanel2;
|
||||||
|
|
||||||
|
// Tests that you can run the profiler in multiple tabs at the same
|
||||||
|
// time and that closing the debugger panel in one tab doesn't lock
|
||||||
|
// profilers in other tabs.
|
||||||
|
|
||||||
|
registerCleanupFunction(function () {
|
||||||
|
gTab1 = gTab2 = gPanel1 = gPanel2 = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
openTwoTabs()
|
||||||
|
.then(startTwoProfiles)
|
||||||
|
.then(stopFirstProfile)
|
||||||
|
.then(stopSecondProfile)
|
||||||
|
.then(closeTabs)
|
||||||
|
.then(openTwoTabs)
|
||||||
|
.then(startTwoProfiles)
|
||||||
|
.then(closeFirstPanel)
|
||||||
|
.then(stopSecondProfile)
|
||||||
|
.then(closeTabs)
|
||||||
|
.then(finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openTwoTabs() {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
setUp(URL, (tab, browser, panel) => {
|
||||||
|
gTab1 = tab;
|
||||||
|
gPanel1 = panel;
|
||||||
|
|
||||||
|
loadTab(URL, (tab, browser) => {
|
||||||
|
gTab2 = tab;
|
||||||
|
openProfiler(tab, () => {
|
||||||
|
let target = TargetFactory.forTab(tab);
|
||||||
|
gPanel2 = gDevTools.getToolbox(target).getPanel("jsprofiler");
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTwoProfiles() {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
gPanel1.controller.start("Profile 1", (err) => {
|
||||||
|
ok(!err, "Profile in tab 1 started without errors");
|
||||||
|
gPanel2.controller.start("Profile 1", (err) => {
|
||||||
|
ok(!err, "Profile in tab 2 started without errors");
|
||||||
|
gPanel1.controller.isActive((err, isActive) => {
|
||||||
|
ok(isActive, "Profiler is active");
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopFirstProfile() {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
gPanel1.controller.stop("Profile 1", (err, data) => {
|
||||||
|
ok(!err, "Profile in tab 1 stopped without errors");
|
||||||
|
ok(data, "Profile in tab 1 returned some data");
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopSecondProfile() {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
gPanel2.controller.stop("Profile 1", (err, data) => {
|
||||||
|
ok(!err, "Profile in tab 2 stopped without errors");
|
||||||
|
ok(data, "Profile in tab 2 returned some data");
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeTabs() {
|
||||||
|
while (gBrowser.tabs.length > 1) {
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeFirstPanel() {
|
||||||
|
let target = TargetFactory.forTab(gTab1);
|
||||||
|
let toolbox = gDevTools.getToolbox(target);
|
||||||
|
return toolbox.destroy;
|
||||||
|
}
|
|
@ -13,26 +13,12 @@ function test() {
|
||||||
gPanel = panel;
|
gPanel = panel;
|
||||||
|
|
||||||
panel.once("started", onStart);
|
panel.once("started", onStart);
|
||||||
panel.once("stopped", onStop);
|
|
||||||
panel.once("parsed", onParsed);
|
panel.once("parsed", onParsed);
|
||||||
|
|
||||||
testUI();
|
testUI();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function attemptTearDown() {
|
|
||||||
gAttempts += 1;
|
|
||||||
|
|
||||||
if (gAttempts < 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tearDown(gTab, function onTearDown() {
|
|
||||||
gPanel = null;
|
|
||||||
gTab = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function testUI() {
|
function testUI() {
|
||||||
ok(gPanel, "Profiler panel exists");
|
ok(gPanel, "Profiler panel exists");
|
||||||
ok(gPanel.activeProfile, "Active profile exists");
|
ok(gPanel.activeProfile, "Active profile exists");
|
||||||
|
@ -58,13 +44,6 @@ function onStart() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStop() {
|
|
||||||
gPanel.controller.isActive(function (err, isActive) {
|
|
||||||
ok(!isActive, "Profiler is idle");
|
|
||||||
attemptTearDown();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onParsed() {
|
function onParsed() {
|
||||||
function assertSample() {
|
function assertSample() {
|
||||||
let [win,doc] = getProfileInternals();
|
let [win,doc] = getProfileInternals();
|
||||||
|
@ -76,7 +55,11 @@ function onParsed() {
|
||||||
|
|
||||||
ok(sample.length > 0, "We have some items displayed");
|
ok(sample.length > 0, "We have some items displayed");
|
||||||
is(sample[0].innerHTML, "100.0%", "First percentage is 100%");
|
is(sample[0].innerHTML, "100.0%", "First percentage is 100%");
|
||||||
attemptTearDown();
|
|
||||||
|
tearDown(gTab, function onTearDown() {
|
||||||
|
gPanel = null;
|
||||||
|
gTab = null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
assertSample();
|
assertSample();
|
||||||
|
|
|
@ -33,15 +33,19 @@ this.EXPORTED_SYMBOLS = ["SideMenuWidget"];
|
||||||
*
|
*
|
||||||
* @param nsIDOMNode aNode
|
* @param nsIDOMNode aNode
|
||||||
* The element associated with the widget.
|
* The element associated with the widget.
|
||||||
|
* @param boolean aShowArrows
|
||||||
|
* Specifies if items in this container should display horizontal arrows.
|
||||||
*/
|
*/
|
||||||
this.SideMenuWidget = function SideMenuWidget(aNode) {
|
this.SideMenuWidget = function SideMenuWidget(aNode, aShowArrows = true) {
|
||||||
this._parent = aNode;
|
this._parent = aNode;
|
||||||
|
this._showArrows = aShowArrows;
|
||||||
|
|
||||||
// Create an internal scrollbox container.
|
// Create an internal scrollbox container.
|
||||||
this._list = this.document.createElement("scrollbox");
|
this._list = this.document.createElement("scrollbox");
|
||||||
this._list.className = "side-menu-widget-container";
|
this._list.className = "side-menu-widget-container";
|
||||||
this._list.setAttribute("flex", "1");
|
this._list.setAttribute("flex", "1");
|
||||||
this._list.setAttribute("orient", "vertical");
|
this._list.setAttribute("orient", "vertical");
|
||||||
|
this._list.setAttribute("with-arrow", aShowArrows);
|
||||||
this._parent.appendChild(this._list);
|
this._parent.appendChild(this._list);
|
||||||
this._boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
this._boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||||
|
|
||||||
|
@ -83,7 +87,7 @@ SideMenuWidget.prototype = {
|
||||||
this.ensureSelectionIsVisible(true, true); // Don't worry, it's delayed.
|
this.ensureSelectionIsVisible(true, true); // Don't worry, it's delayed.
|
||||||
|
|
||||||
let group = this._getGroupForName(aGroup);
|
let group = this._getGroupForName(aGroup);
|
||||||
return group.insertItemAt(aIndex, aContents, aTooltip);
|
return group.insertItemAt(aIndex, aContents, aTooltip, this._showArrows);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,9 +154,11 @@ SideMenuWidget.prototype = {
|
||||||
}
|
}
|
||||||
for (let node of menuElementsArray) {
|
for (let node of menuElementsArray) {
|
||||||
if (node == aChild) {
|
if (node == aChild) {
|
||||||
|
node.classList.add("selected");
|
||||||
node.parentNode.classList.add("selected");
|
node.parentNode.classList.add("selected");
|
||||||
this._selectedItem = node;
|
this._selectedItem = node;
|
||||||
} else {
|
} else {
|
||||||
|
node.classList.remove("selected");
|
||||||
node.parentNode.classList.remove("selected");
|
node.parentNode.classList.remove("selected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,13 +403,15 @@ SideMenuGroup.prototype = {
|
||||||
* The string or node displayed in the container.
|
* The string or node displayed in the container.
|
||||||
* @param string aTooltip [optional]
|
* @param string aTooltip [optional]
|
||||||
* A tooltip attribute for the displayed item.
|
* A tooltip attribute for the displayed item.
|
||||||
|
* @param boolean aArrowFlag
|
||||||
|
* True if a horizontal arrow should be shown.
|
||||||
* @return nsIDOMNode
|
* @return nsIDOMNode
|
||||||
* The element associated with the displayed item.
|
* The element associated with the displayed item.
|
||||||
*/
|
*/
|
||||||
insertItemAt: function SMG_insertItemAt(aIndex, aContents, aTooltip) {
|
insertItemAt: function SMG_insertItemAt(aIndex, aContents, aTooltip, aArrowFlag) {
|
||||||
let list = this._list;
|
let list = this._list;
|
||||||
let menuArray = this._menuElementsArray;
|
let menuArray = this._menuElementsArray;
|
||||||
let item = new SideMenuItem(this, aContents, aTooltip);
|
let item = new SideMenuItem(this, aContents, aTooltip, aArrowFlag);
|
||||||
|
|
||||||
// Invalidate any notices set on the owner widget.
|
// Invalidate any notices set on the owner widget.
|
||||||
this.ownerView.removeAttribute("notice");
|
this.ownerView.removeAttribute("notice");
|
||||||
|
@ -475,24 +483,39 @@ SideMenuGroup.prototype = {
|
||||||
* A tooltip attribute for the displayed item.
|
* A tooltip attribute for the displayed item.
|
||||||
* @param string | nsIDOMNode aContents
|
* @param string | nsIDOMNode aContents
|
||||||
* The string or node displayed in the container.
|
* The string or node displayed in the container.
|
||||||
|
* @param boolean aArrowFlag
|
||||||
|
* True if a horizontal arrow should be shown.
|
||||||
*/
|
*/
|
||||||
function SideMenuItem(aGroup, aContents, aTooltip = "") {
|
function SideMenuItem(aGroup, aContents, aTooltip, aArrowFlag) {
|
||||||
this.ownerView = aGroup;
|
this.ownerView = aGroup;
|
||||||
|
|
||||||
let document = this.document;
|
let document = this.document;
|
||||||
let target = this._target = document.createElement("vbox");
|
|
||||||
target.className = "side-menu-widget-item-contents";
|
// Show a horizontal arrow towards the content.
|
||||||
target.setAttribute("flex", "1");
|
if (aArrowFlag) {
|
||||||
|
let target = this._target = document.createElement("vbox");
|
||||||
|
target.className = "side-menu-widget-item-contents";
|
||||||
|
|
||||||
|
let arrow = this._arrow = document.createElement("hbox");
|
||||||
|
arrow.className = "side-menu-widget-item-arrow";
|
||||||
|
|
||||||
|
let container = this._container = document.createElement("hbox");
|
||||||
|
container.className = "side-menu-widget-item side-menu-widget-item-or-group";
|
||||||
|
container.setAttribute("tooltiptext", aTooltip);
|
||||||
|
container.appendChild(target);
|
||||||
|
container.appendChild(arrow);
|
||||||
|
}
|
||||||
|
// Skip a few redundant nodes when no horizontal arrow is shown.
|
||||||
|
else {
|
||||||
|
let target = this._target = this._container = document.createElement("hbox");
|
||||||
|
target.className =
|
||||||
|
"side-menu-widget-item " +
|
||||||
|
"side-menu-widget-item-or-group " +
|
||||||
|
"side-menu-widget-item-contents";
|
||||||
|
}
|
||||||
|
|
||||||
|
this._target.setAttribute("flex", "1");
|
||||||
this.contents = aContents;
|
this.contents = aContents;
|
||||||
|
|
||||||
let arrow = this._arrow = document.createElement("hbox");
|
|
||||||
arrow.className = "side-menu-widget-item-arrow";
|
|
||||||
|
|
||||||
let container = this._container = document.createElement("hbox");
|
|
||||||
container.className = "side-menu-widget-item side-menu-widget-item-or-group";
|
|
||||||
container.setAttribute("tooltiptext", aTooltip);
|
|
||||||
container.appendChild(target);
|
|
||||||
container.appendChild(arrow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SideMenuItem.prototype = {
|
SideMenuItem.prototype = {
|
||||||
|
|
|
@ -918,6 +918,18 @@ VariablesView.prototype = {
|
||||||
_emptyTextValue: ""
|
_emptyTextValue: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VariablesView.NON_SORTABLE_CLASSES = [
|
||||||
|
"Array",
|
||||||
|
"Int8Array",
|
||||||
|
"Uint8Array",
|
||||||
|
"Int16Array",
|
||||||
|
"Uint16Array",
|
||||||
|
"Int32Array",
|
||||||
|
"Uint32Array",
|
||||||
|
"Float32Array",
|
||||||
|
"Float64Array"
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the string evaluated when performing simple value changes.
|
* Generates the string evaluated when performing simple value changes.
|
||||||
*
|
*
|
||||||
|
@ -983,7 +995,8 @@ VariablesView.getterOrSetterEvalMacro = function(aItem, aCurrentString) {
|
||||||
// morph it into a plain value.
|
// morph it into a plain value.
|
||||||
if ((type == "set" && propertyObject.getter.type == "undefined") ||
|
if ((type == "set" && propertyObject.getter.type == "undefined") ||
|
||||||
(type == "get" && propertyObject.setter.type == "undefined")) {
|
(type == "get" && propertyObject.setter.type == "undefined")) {
|
||||||
return VariablesView.overrideValueEvalMacro(propertyObject, "undefined");
|
// Make sure the right getter/setter to value override macro is applied to the target object.
|
||||||
|
return propertyObject.evaluationMacro(propertyObject, "undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct and return the getter/setter removal evaluation string.
|
// Construct and return the getter/setter removal evaluation string.
|
||||||
|
@ -1041,7 +1054,10 @@ VariablesView.getterOrSetterEvalMacro = function(aItem, aCurrentString) {
|
||||||
*/
|
*/
|
||||||
VariablesView.getterOrSetterDeleteCallback = function(aItem) {
|
VariablesView.getterOrSetterDeleteCallback = function(aItem) {
|
||||||
aItem._disable();
|
aItem._disable();
|
||||||
aItem.ownerView.eval(VariablesView.getterOrSetterEvalMacro(aItem, ""));
|
|
||||||
|
// Make sure the right getter/setter to value override macro is applied to the target object.
|
||||||
|
aItem.ownerView.eval(aItem.evaluationMacro(aItem, ""));
|
||||||
|
|
||||||
return true; // Don't hide the element.
|
return true; // Don't hide the element.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1416,6 +1432,13 @@ Scope.prototype = {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Focus this scope.
|
||||||
|
*/
|
||||||
|
focus: function S_focus() {
|
||||||
|
this._variablesView._focusItem(this);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener for a certain event on this scope's title.
|
* Adds an event listener for a certain event on this scope's title.
|
||||||
* @param string aName
|
* @param string aName
|
||||||
|
@ -1448,6 +1471,18 @@ Scope.prototype = {
|
||||||
*/
|
*/
|
||||||
get name() this._nameString,
|
get name() this._nameString,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the displayed value for this item.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
get displayValue() this._valueString,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the class names used for the displayed value.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
get displayValueClassName() this._valueClassName,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the element associated with this item.
|
* Gets the element associated with this item.
|
||||||
* @return nsIDOMNode
|
* @return nsIDOMNode
|
||||||
|
@ -1525,7 +1560,7 @@ Scope.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.toggle();
|
this.toggle();
|
||||||
this._variablesView._focusItem(this);
|
this.focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1907,7 +1942,7 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
||||||
* someProp4: { value: { type: "null" } },
|
* someProp4: { value: { type: "null" } },
|
||||||
* someProp5: { value: { type: "object", class: "Object" } },
|
* someProp5: { value: { type: "object", class: "Object" } },
|
||||||
* someProp6: { get: { type: "object", class: "Function" },
|
* someProp6: { get: { type: "object", class: "Function" },
|
||||||
* set: { type: "undefined" } }
|
* set: { type: "undefined" } } }
|
||||||
* @param object aOptions [optional]
|
* @param object aOptions [optional]
|
||||||
* Additional options for adding the properties. Supported options:
|
* Additional options for adding the properties. Supported options:
|
||||||
* - sorted: true to sort all the properties before adding them
|
* - sorted: true to sort all the properties before adding them
|
||||||
|
@ -2190,6 +2225,7 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
||||||
// evaluation method is provided.
|
// evaluation method is provided.
|
||||||
else {
|
else {
|
||||||
this.delete = null;
|
this.delete = null;
|
||||||
|
this.evaluationMacro = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let getter = this.addProperty("get", { value: descriptor.get });
|
let getter = this.addProperty("get", { value: descriptor.get });
|
||||||
|
@ -2528,11 +2564,11 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
||||||
case e.DOM_VK_RETURN:
|
case e.DOM_VK_RETURN:
|
||||||
case e.DOM_VK_ENTER:
|
case e.DOM_VK_ENTER:
|
||||||
this._saveNameInput(e);
|
this._saveNameInput(e);
|
||||||
this._variablesView._focusItem(this);
|
this.focus();
|
||||||
return;
|
return;
|
||||||
case e.DOM_VK_ESCAPE:
|
case e.DOM_VK_ESCAPE:
|
||||||
this._deactivateNameInput(e);
|
this._deactivateNameInput(e);
|
||||||
this._variablesView._focusItem(this);
|
this.focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2547,11 +2583,11 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, {
|
||||||
case e.DOM_VK_RETURN:
|
case e.DOM_VK_RETURN:
|
||||||
case e.DOM_VK_ENTER:
|
case e.DOM_VK_ENTER:
|
||||||
this._saveValueInput(e);
|
this._saveValueInput(e);
|
||||||
this._variablesView._focusItem(this);
|
this.focus();
|
||||||
return;
|
return;
|
||||||
case e.DOM_VK_ESCAPE:
|
case e.DOM_VK_ESCAPE:
|
||||||
this._deactivateValueInput(e);
|
this._deactivateValueInput(e);
|
||||||
this._variablesView._focusItem(this);
|
this.focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.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/. -->
|
||||||
|
<?xml-stylesheet href="chrome://global/skin/global.css"?>
|
||||||
|
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
|
||||||
|
<!DOCTYPE window [
|
||||||
|
<!ENTITY % viewDTD SYSTEM "chrome://browser/locale/devtools/VariablesView.dtd">
|
||||||
|
%viewDTD;
|
||||||
|
]>
|
||||||
|
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
|
title="&PropertiesViewWindowTitle;">
|
||||||
|
<vbox id="variables" flex="1"/>
|
||||||
|
</window>
|
|
@ -108,6 +108,14 @@ this.ViewHelpers = {
|
||||||
* The element representing the pane to toggle.
|
* The element representing the pane to toggle.
|
||||||
*/
|
*/
|
||||||
togglePane: function VH_togglePane(aFlags, aPane) {
|
togglePane: function VH_togglePane(aFlags, aPane) {
|
||||||
|
// Hiding is always handled via margins, not the hidden attribute.
|
||||||
|
aPane.removeAttribute("hidden");
|
||||||
|
|
||||||
|
// Add a class to the pane to handle min-widths, margins and animations.
|
||||||
|
if (!aPane.classList.contains("generic-toggled-side-pane")) {
|
||||||
|
aPane.classList.add("generic-toggled-side-pane");
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid useless toggles.
|
// Avoid useless toggles.
|
||||||
if (aFlags.visible == !aPane.hasAttribute("pane-collapsed")) {
|
if (aFlags.visible == !aPane.hasAttribute("pane-collapsed")) {
|
||||||
if (aFlags.callback) aFlags.callback();
|
if (aFlags.callback) aFlags.callback();
|
||||||
|
@ -140,14 +148,6 @@ this.ViewHelpers = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a class to the pane to handle min-widths, margins and animations.
|
|
||||||
if (!aPane.classList.contains("generic-toggled-side-pane")) {
|
|
||||||
aPane.classList.add("generic-toggled-side-pane");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hiding is always handled via margins, not the hidden attribute.
|
|
||||||
aPane.removeAttribute("hidden");
|
|
||||||
|
|
||||||
// The "animated" attributes enables animated toggles (slide in-out).
|
// The "animated" attributes enables animated toggles (slide in-out).
|
||||||
if (aFlags.animated) {
|
if (aFlags.animated) {
|
||||||
aPane.setAttribute("animated", "");
|
aPane.setAttribute("animated", "");
|
||||||
|
|
|
@ -74,12 +74,8 @@ function ElementStyle(aElement, aStore)
|
||||||
this.store.userProperties = new UserProperties();
|
this.store.userProperties = new UserProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.store.disabled) {
|
if (!("disabled" in this.store)) {
|
||||||
this.store.disabled = aStore.disabled;
|
this.store.disabled = new WeakMap();
|
||||||
} else {
|
|
||||||
// FIXME: This should be a WeakMap once bug 753517 is fixed.
|
|
||||||
// See Bug 777373 for details.
|
|
||||||
this.store.disabled = new Map();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = aElement.ownerDocument;
|
let doc = aElement.ownerDocument;
|
||||||
|
@ -1666,9 +1662,7 @@ TextPropertyEditor.prototype = {
|
||||||
*/
|
*/
|
||||||
function UserProperties()
|
function UserProperties()
|
||||||
{
|
{
|
||||||
// FIXME: This should be a WeakMap once bug 753517 is fixed.
|
this.weakMap = new WeakMap();
|
||||||
// See Bug 777373 for details.
|
|
||||||
this.map = new Map();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UserProperties.prototype = {
|
UserProperties.prototype = {
|
||||||
|
@ -1688,7 +1682,7 @@ UserProperties.prototype = {
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
getProperty: function UP_getProperty(aStyle, aName, aComputedValue) {
|
getProperty: function UP_getProperty(aStyle, aName, aComputedValue) {
|
||||||
let entry = this.map.get(aStyle, null);
|
let entry = this.weakMap.get(aStyle, null);
|
||||||
|
|
||||||
if (entry && aName in entry) {
|
if (entry && aName in entry) {
|
||||||
let item = entry[aName];
|
let item = entry[aName];
|
||||||
|
@ -1717,13 +1711,13 @@ UserProperties.prototype = {
|
||||||
* The value of the property to set.
|
* The value of the property to set.
|
||||||
*/
|
*/
|
||||||
setProperty: function UP_setProperty(aStyle, aName, aComputedValue, aUserValue) {
|
setProperty: function UP_setProperty(aStyle, aName, aComputedValue, aUserValue) {
|
||||||
let entry = this.map.get(aStyle, null);
|
let entry = this.weakMap.get(aStyle, null);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry[aName] = { computed: aComputedValue, user: aUserValue };
|
entry[aName] = { computed: aComputedValue, user: aUserValue };
|
||||||
} else {
|
} else {
|
||||||
let props = {};
|
let props = {};
|
||||||
props[aName] = { computed: aComputedValue, user: aUserValue };
|
props[aName] = { computed: aComputedValue, user: aUserValue };
|
||||||
this.map.set(aStyle, props);
|
this.weakMap.set(aStyle, props);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1736,7 +1730,7 @@ UserProperties.prototype = {
|
||||||
* The name of the property to check.
|
* The name of the property to check.
|
||||||
*/
|
*/
|
||||||
contains: function UP_contains(aStyle, aName) {
|
contains: function UP_contains(aStyle, aName) {
|
||||||
let entry = this.map.get(aStyle, null);
|
let entry = this.weakMap.get(aStyle, null);
|
||||||
return !!entry && aName in entry;
|
return !!entry && aName in entry;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,9 +19,9 @@ function openRuleView()
|
||||||
// Highlight a node.
|
// Highlight a node.
|
||||||
let node = content.document.getElementsByTagName("h1")[0];
|
let node = content.document.getElementsByTagName("h1")[0];
|
||||||
inspector.selection.once("new-node", testFocus);
|
inspector.selection.once("new-node", testFocus);
|
||||||
executeSoon(function() {
|
|
||||||
inspector.selection.setNode(doc.body);
|
inspector.sidebar.once("ruleview-ready",
|
||||||
});
|
() => inspector.selection.setNode(doc.body));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ const Cu = Components.utils;
|
||||||
|
|
||||||
// Tilt notifications dispatched through the nsIObserverService.
|
// Tilt notifications dispatched through the nsIObserverService.
|
||||||
const TILT_NOTIFICATIONS = {
|
const TILT_NOTIFICATIONS = {
|
||||||
|
// Called early in the startup of a new tilt instance
|
||||||
|
STARTUP: "tilt-startup",
|
||||||
|
|
||||||
// Fires when Tilt starts the initialization.
|
// Fires when Tilt starts the initialization.
|
||||||
INITIALIZING: "tilt-initializing",
|
INITIALIZING: "tilt-initializing",
|
||||||
|
@ -118,12 +120,15 @@ Tilt.prototype = {
|
||||||
// create a visualizer instance for the current tab
|
// create a visualizer instance for the current tab
|
||||||
this.visualizers[id] = new TiltVisualizer({
|
this.visualizers[id] = new TiltVisualizer({
|
||||||
chromeWindow: this.chromeWindow,
|
chromeWindow: this.chromeWindow,
|
||||||
contentWindow: this.chromeWindow.gBrowser.selectedBrowser.contentWindow,
|
contentWindow: contentWindow,
|
||||||
parentNode: this.chromeWindow.gBrowser.selectedBrowser.parentNode,
|
parentNode: this.chromeWindow.gBrowser.selectedBrowser.parentNode,
|
||||||
notifications: this.NOTIFICATIONS,
|
notifications: this.NOTIFICATIONS,
|
||||||
tab: this.chromeWindow.gBrowser.selectedTab
|
tab: this.chromeWindow.gBrowser.selectedTab
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.STARTUP, null);
|
||||||
|
this.visualizers[id].init();
|
||||||
|
|
||||||
// make sure the visualizer object was initialized properly
|
// make sure the visualizer object was initialized properly
|
||||||
if (!this.visualizers[id].isInitialized()) {
|
if (!this.visualizers[id].isInitialized()) {
|
||||||
this.destroy(id);
|
this.destroy(id);
|
||||||
|
@ -131,8 +136,9 @@ Tilt.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.lastInstanceId = id;
|
||||||
this.emit("change", this.chromeWindow.gBrowser.selectedTab);
|
this.emit("change", this.chromeWindow.gBrowser.selectedTab);
|
||||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.INITIALIZING, null);
|
Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.INITIALIZING, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,7 +172,7 @@ Tilt.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, trigger the outro animation and notify necessary observers
|
// otherwise, trigger the outro animation and notify necessary observers
|
||||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYING, null);
|
Services.obs.notifyObservers(content, TILT_NOTIFICATIONS.DESTROYING, null);
|
||||||
|
|
||||||
controller.removeEventListeners();
|
controller.removeEventListeners();
|
||||||
controller.arcball.reset([-pageXOffset, -pageYOffset]);
|
controller.arcball.reset([-pageXOffset, -pageYOffset]);
|
||||||
|
@ -181,6 +187,7 @@ Tilt.prototype = {
|
||||||
*/
|
*/
|
||||||
_finish: function T__finish(aId)
|
_finish: function T__finish(aId)
|
||||||
{
|
{
|
||||||
|
let contentWindow = this.visualizers[aId].presenter.contentWindow;
|
||||||
this.visualizers[aId].removeOverlay();
|
this.visualizers[aId].removeOverlay();
|
||||||
this.visualizers[aId].cleanup();
|
this.visualizers[aId].cleanup();
|
||||||
this.visualizers[aId] = null;
|
this.visualizers[aId] = null;
|
||||||
|
@ -188,7 +195,7 @@ Tilt.prototype = {
|
||||||
this._isDestroying = false;
|
this._isDestroying = false;
|
||||||
this.chromeWindow.gBrowser.selectedBrowser.focus();
|
this.chromeWindow.gBrowser.selectedBrowser.focus();
|
||||||
this.emit("change", this.chromeWindow.gBrowser.selectedTab);
|
this.emit("change", this.chromeWindow.gBrowser.selectedTab);
|
||||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
|
Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.DESTROYED, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,11 +203,17 @@ Tilt.prototype = {
|
||||||
*/
|
*/
|
||||||
_onTabSelect: function T__onTabSelect()
|
_onTabSelect: function T__onTabSelect()
|
||||||
{
|
{
|
||||||
if (this.currentInstance) {
|
if (this.visualizers[this.lastInstanceId]) {
|
||||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.SHOWN, null);
|
let contentWindow = this.visualizers[this.lastInstanceId].presenter.contentWindow;
|
||||||
} else {
|
Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.HIDDEN, null);
|
||||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.HIDDEN, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.currentInstance) {
|
||||||
|
let contentWindow = this.currentInstance.presenter.contentWindow;
|
||||||
|
Services.obs.notifyObservers(contentWindow, TILT_NOTIFICATIONS.SHOWN, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastInstanceId = this.currentWindowId;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -427,6 +427,9 @@ TiltUtils.DOM = {
|
||||||
* the window content holding the document
|
* the window content holding the document
|
||||||
* @param {Object} aProperties
|
* @param {Object} aProperties
|
||||||
* optional, an object containing the following properties:
|
* optional, an object containing the following properties:
|
||||||
|
* {Function} nodeCallback
|
||||||
|
* a function to call instead of TiltUtils.DOM.getNodePosition
|
||||||
|
* to get the position and depth to display nodes
|
||||||
* {Object} invisibleElements
|
* {Object} invisibleElements
|
||||||
* elements which should be ignored
|
* elements which should be ignored
|
||||||
* {Number} minSize
|
* {Number} minSize
|
||||||
|
@ -448,6 +451,8 @@ TiltUtils.DOM = {
|
||||||
let aMaxX = aProperties.maxX || Number.MAX_VALUE;
|
let aMaxX = aProperties.maxX || Number.MAX_VALUE;
|
||||||
let aMaxY = aProperties.maxY || Number.MAX_VALUE;
|
let aMaxY = aProperties.maxY || Number.MAX_VALUE;
|
||||||
|
|
||||||
|
let nodeCallback = aProperties.nodeCallback || this.getNodePosition.bind(this);
|
||||||
|
|
||||||
let nodes = aContentWindow.document.childNodes;
|
let nodes = aContentWindow.document.childNodes;
|
||||||
let store = { info: [], nodes: [] };
|
let store = { info: [], nodes: [] };
|
||||||
let depth = 0;
|
let depth = 0;
|
||||||
|
@ -466,7 +471,7 @@ TiltUtils.DOM = {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let coord = this.getNodePosition(aContentWindow, node, parentPosition);
|
let coord = nodeCallback(aContentWindow, node, parentPosition);
|
||||||
if (!coord) {
|
if (!coord) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,14 @@ this.TiltVisualizer = function TiltVisualizer(aProperties)
|
||||||
|
|
||||||
TiltVisualizer.prototype = {
|
TiltVisualizer.prototype = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the visualizer
|
||||||
|
*/
|
||||||
|
init: function TV_init()
|
||||||
|
{
|
||||||
|
this.presenter.init();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this object was initialized properly.
|
* Checks if this object was initialized properly.
|
||||||
*
|
*
|
||||||
|
@ -309,6 +317,11 @@ TiltVisualizer.Presenter = function TV_Presenter(
|
||||||
*/
|
*/
|
||||||
this.NOTIFICATIONS = aNotifications;
|
this.NOTIFICATIONS = aNotifications;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the default node callback function
|
||||||
|
*/
|
||||||
|
this.nodeCallback = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the renderer, containing useful functions for easy drawing.
|
* Create the renderer, containing useful functions for easy drawing.
|
||||||
*/
|
*/
|
||||||
|
@ -375,14 +388,19 @@ TiltVisualizer.Presenter = function TV_Presenter(
|
||||||
this._delta = 0;
|
this._delta = 0;
|
||||||
this._prevFrameTime = 0;
|
this._prevFrameTime = 0;
|
||||||
this._currFrameTime = 0;
|
this._currFrameTime = 0;
|
||||||
|
|
||||||
|
|
||||||
this._setup();
|
|
||||||
this._loop();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TiltVisualizer.Presenter.prototype = {
|
TiltVisualizer.Presenter.prototype = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the presenter and starts the animation loop
|
||||||
|
*/
|
||||||
|
init: function TVP_init()
|
||||||
|
{
|
||||||
|
this._setup();
|
||||||
|
this._loop();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The initialization logic.
|
* The initialization logic.
|
||||||
*/
|
*/
|
||||||
|
@ -718,6 +736,7 @@ TiltVisualizer.Presenter.prototype = {
|
||||||
|
|
||||||
// traverse the document and get the depths, coordinates and local names
|
// traverse the document and get the depths, coordinates and local names
|
||||||
this._traverseData = TiltUtils.DOM.traverse(this.contentWindow, {
|
this._traverseData = TiltUtils.DOM.traverse(this.contentWindow, {
|
||||||
|
nodeCallback: this.nodeCallback,
|
||||||
invisibleElements: INVISIBLE_ELEMENTS,
|
invisibleElements: INVISIBLE_ELEMENTS,
|
||||||
minSize: ELEMENT_MIN_SIZE,
|
minSize: ELEMENT_MIN_SIZE,
|
||||||
maxX: this._texture.width,
|
maxX: this._texture.width,
|
||||||
|
@ -851,7 +870,7 @@ TiltVisualizer.Presenter.prototype = {
|
||||||
this._currentSelection = -1;
|
this._currentSelection = -1;
|
||||||
this._highlight.disabled = true;
|
this._highlight.disabled = true;
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, this.NOTIFICATIONS.UNHIGHLIGHTING, null);
|
Services.obs.notifyObservers(this.contentWindow, this.NOTIFICATIONS.UNHIGHLIGHTING, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,7 +907,7 @@ TiltVisualizer.Presenter.prototype = {
|
||||||
vec3.scale(this._highlight.v1, this.transforms.zoom, []), 0.5));
|
vec3.scale(this._highlight.v1, this.transforms.zoom, []), 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, this.NOTIFICATIONS.HIGHLIGHTING, null);
|
Services.obs.notifyObservers(this.contentWindow, this.NOTIFICATIONS.HIGHLIGHTING, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -920,7 +939,7 @@ TiltVisualizer.Presenter.prototype = {
|
||||||
this._highlight.disabled = true;
|
this._highlight.disabled = true;
|
||||||
this._redraw = true;
|
this._redraw = true;
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, this.NOTIFICATIONS.NODE_REMOVED, null);
|
Services.obs.notifyObservers(this.contentWindow, this.NOTIFICATIONS.NODE_REMOVED, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1044,7 +1063,7 @@ TiltVisualizer.Presenter.prototype = {
|
||||||
!this._isExecutingDestruction) {
|
!this._isExecutingDestruction) {
|
||||||
|
|
||||||
this._isInitializationFinished = true;
|
this._isInitializationFinished = true;
|
||||||
Services.obs.notifyObservers(null, this.NOTIFICATIONS.INITIALIZED, null);
|
Services.obs.notifyObservers(this.contentWindow, this.NOTIFICATIONS.INITIALIZED, null);
|
||||||
|
|
||||||
if ("function" === typeof this._onInitializationFinished) {
|
if ("function" === typeof this._onInitializationFinished) {
|
||||||
this._onInitializationFinished();
|
this._onInitializationFinished();
|
||||||
|
@ -1056,7 +1075,7 @@ TiltVisualizer.Presenter.prototype = {
|
||||||
this._isExecutingDestruction) {
|
this._isExecutingDestruction) {
|
||||||
|
|
||||||
this._isDestructionFinished = true;
|
this._isDestructionFinished = true;
|
||||||
Services.obs.notifyObservers(null, this.NOTIFICATIONS.BEFORE_DESTROYED, null);
|
Services.obs.notifyObservers(this.contentWindow, this.NOTIFICATIONS.BEFORE_DESTROYED, null);
|
||||||
|
|
||||||
if ("function" === typeof this._onDestructionFinished) {
|
if ("function" === typeof this._onDestructionFinished) {
|
||||||
this._onDestructionFinished();
|
this._onDestructionFinished();
|
||||||
|
|
|
@ -18,7 +18,7 @@ let rgba = TiltMath.hex2rgba;
|
||||||
this.TiltVisualizerStyle = {
|
this.TiltVisualizerStyle = {
|
||||||
|
|
||||||
canvas: {
|
canvas: {
|
||||||
background: "-moz-linear-gradient(top, #454545 0%, #000 100%)",
|
background: "linear-gradient(#454545 0%, #000 100%)",
|
||||||
},
|
},
|
||||||
|
|
||||||
nodes: {
|
nodes: {
|
||||||
|
|
|
@ -15,6 +15,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||||
browser_tilt_01_lazy_getter.js \
|
browser_tilt_01_lazy_getter.js \
|
||||||
browser_tilt_02_notifications-seq.js \
|
browser_tilt_02_notifications-seq.js \
|
||||||
browser_tilt_02_notifications.js \
|
browser_tilt_02_notifications.js \
|
||||||
|
browser_tilt_02_notifications-tabs.js \
|
||||||
browser_tilt_03_tab_switch.js \
|
browser_tilt_03_tab_switch.js \
|
||||||
browser_tilt_04_initialization.js \
|
browser_tilt_04_initialization.js \
|
||||||
browser_tilt_05_destruction-esc.js \
|
browser_tilt_05_destruction-esc.js \
|
||||||
|
@ -53,6 +54,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||||
browser_tilt_utils05.js \
|
browser_tilt_utils05.js \
|
||||||
browser_tilt_utils06.js \
|
browser_tilt_utils06.js \
|
||||||
browser_tilt_utils07.js \
|
browser_tilt_utils07.js \
|
||||||
|
browser_tilt_utils08.js \
|
||||||
browser_tilt_visualizer.js \
|
browser_tilt_visualizer.js \
|
||||||
browser_tilt_zoom.js \
|
browser_tilt_zoom.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
|
@ -19,6 +19,7 @@ function test() {
|
||||||
|
|
||||||
createTab(function() {
|
createTab(function() {
|
||||||
Services.obs.addObserver(finalize, DESTROYED, false);
|
Services.obs.addObserver(finalize, DESTROYED, false);
|
||||||
|
Services.obs.addObserver(obs_STARTUP, STARTUP, false);
|
||||||
Services.obs.addObserver(obs_INITIALIZING, INITIALIZING, false);
|
Services.obs.addObserver(obs_INITIALIZING, INITIALIZING, false);
|
||||||
Services.obs.addObserver(obs_INITIALIZED, INITIALIZED, false);
|
Services.obs.addObserver(obs_INITIALIZED, INITIALIZED, false);
|
||||||
Services.obs.addObserver(obs_DESTROYING, DESTROYING, false);
|
Services.obs.addObserver(obs_DESTROYING, DESTROYING, false);
|
||||||
|
@ -34,39 +35,51 @@ function test() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function obs_INITIALIZING() {
|
function obs_STARTUP(win) {
|
||||||
|
info("Handling the STARTUP notification.");
|
||||||
|
is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
|
||||||
|
tabEvents += "STARTUP;";
|
||||||
|
}
|
||||||
|
|
||||||
|
function obs_INITIALIZING(win) {
|
||||||
info("Handling the INITIALIZING notification.");
|
info("Handling the INITIALIZING notification.");
|
||||||
|
is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "INITIALIZING;";
|
tabEvents += "INITIALIZING;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function obs_INITIALIZED() {
|
function obs_INITIALIZED(win) {
|
||||||
info("Handling the INITIALIZED notification.");
|
info("Handling the INITIALIZED notification.");
|
||||||
|
is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "INITIALIZED;";
|
tabEvents += "INITIALIZED;";
|
||||||
|
|
||||||
Tilt.destroy(Tilt.currentWindowId, true);
|
Tilt.destroy(Tilt.currentWindowId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function obs_DESTROYING() {
|
function obs_DESTROYING(win) {
|
||||||
info("Handling the DESTROYING( notification.");
|
info("Handling the DESTROYING( notification.");
|
||||||
|
is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "DESTROYING;";
|
tabEvents += "DESTROYING;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function obs_BEFORE_DESTROYED() {
|
function obs_BEFORE_DESTROYED(win) {
|
||||||
info("Handling the BEFORE_DESTROYED notification.");
|
info("Handling the BEFORE_DESTROYED notification.");
|
||||||
|
is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "BEFORE_DESTROYED;";
|
tabEvents += "BEFORE_DESTROYED;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function obs_DESTROYED() {
|
function obs_DESTROYED(win) {
|
||||||
info("Handling the DESTROYED notification.");
|
info("Handling the DESTROYED notification.");
|
||||||
|
is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "DESTROYED;";
|
tabEvents += "DESTROYED;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function finalize() {
|
function finalize(win) {
|
||||||
if (!tabEvents) {
|
if (!tabEvents) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
is(tabEvents, "INITIALIZING;INITIALIZED;DESTROYING;BEFORE_DESTROYED;DESTROYED;",
|
is(win, gBrowser.selectedBrowser.contentWindow, "Saw the correct window");
|
||||||
|
is(tabEvents, "STARTUP;INITIALIZING;INITIALIZED;DESTROYING;BEFORE_DESTROYED;DESTROYED;",
|
||||||
"The notifications weren't fired in the correct order.");
|
"The notifications weren't fired in the correct order.");
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let tab0, tab1, tab2;
|
||||||
|
let testStep = -1;
|
||||||
|
|
||||||
|
let expected = [];
|
||||||
|
function expect(notification, win) {
|
||||||
|
expected.push({ notification: notification, window: win });
|
||||||
|
}
|
||||||
|
|
||||||
|
function notification(win, topic) {
|
||||||
|
if (expected.length == 0) {
|
||||||
|
is(topic, null, "Shouldn't see a notification");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { notification, window } = expected.shift();
|
||||||
|
is(topic, notification, "Saw the expected notification");
|
||||||
|
is(win, window, "Saw the expected window");
|
||||||
|
}
|
||||||
|
|
||||||
|
function after(notification, callback) {
|
||||||
|
function observer() {
|
||||||
|
Services.obs.removeObserver(observer, notification);
|
||||||
|
executeSoon(callback);
|
||||||
|
}
|
||||||
|
Services.obs.addObserver(observer, notification, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
if (!isTiltEnabled()) {
|
||||||
|
info("Skipping tab switch test because Tilt isn't enabled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isWebGLSupported()) {
|
||||||
|
info("Skipping tab switch test because WebGL isn't supported.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.obs.addObserver(notification, STARTUP, false);
|
||||||
|
Services.obs.addObserver(notification, INITIALIZING, false);
|
||||||
|
Services.obs.addObserver(notification, INITIALIZED, false);
|
||||||
|
Services.obs.addObserver(notification, DESTROYING, false);
|
||||||
|
Services.obs.addObserver(notification, BEFORE_DESTROYED, false);
|
||||||
|
Services.obs.addObserver(notification, DESTROYED, false);
|
||||||
|
Services.obs.addObserver(notification, SHOWN, false);
|
||||||
|
Services.obs.addObserver(notification, HIDDEN, false);
|
||||||
|
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
tab0 = gBrowser.selectedTab;
|
||||||
|
nextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTab2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
let testSteps = [
|
||||||
|
function step0() {
|
||||||
|
tab1 = createTab(function() {
|
||||||
|
expect(STARTUP, tab1.linkedBrowser.contentWindow);
|
||||||
|
expect(INITIALIZING, tab1.linkedBrowser.contentWindow);
|
||||||
|
expect(INITIALIZED, tab1.linkedBrowser.contentWindow);
|
||||||
|
after(INITIALIZED, nextStep);
|
||||||
|
|
||||||
|
createTilt({}, false, function suddenDeath()
|
||||||
|
{
|
||||||
|
info("Tilt could not be initialized properly.");
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function step1() {
|
||||||
|
expect(HIDDEN, tab1.linkedBrowser.contentWindow);
|
||||||
|
|
||||||
|
tab2 = createTab(function() {
|
||||||
|
expect(STARTUP, tab2.linkedBrowser.contentWindow);
|
||||||
|
expect(INITIALIZING, tab2.linkedBrowser.contentWindow);
|
||||||
|
expect(INITIALIZED, tab2.linkedBrowser.contentWindow);
|
||||||
|
after(INITIALIZED, nextStep);
|
||||||
|
|
||||||
|
createTilt({}, false, function suddenDeath()
|
||||||
|
{
|
||||||
|
info("Tilt could not be initialized properly.");
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function step2() {
|
||||||
|
expect(HIDDEN, tab2.linkedBrowser.contentWindow);
|
||||||
|
after(HIDDEN, nextStep);
|
||||||
|
|
||||||
|
gBrowser.selectedTab = tab0;
|
||||||
|
},
|
||||||
|
function step3() {
|
||||||
|
expect(SHOWN, tab2.linkedBrowser.contentWindow);
|
||||||
|
after(SHOWN, nextStep);
|
||||||
|
|
||||||
|
gBrowser.selectedTab = tab2;
|
||||||
|
},
|
||||||
|
function step4() {
|
||||||
|
expect(HIDDEN, tab2.linkedBrowser.contentWindow);
|
||||||
|
expect(SHOWN, tab1.linkedBrowser.contentWindow);
|
||||||
|
after(SHOWN, nextStep);
|
||||||
|
|
||||||
|
gBrowser.selectedTab = tab1;
|
||||||
|
},
|
||||||
|
function step5() {
|
||||||
|
expect(HIDDEN, tab1.linkedBrowser.contentWindow);
|
||||||
|
expect(SHOWN, tab2.linkedBrowser.contentWindow);
|
||||||
|
after(SHOWN, nextStep);
|
||||||
|
|
||||||
|
gBrowser.selectedTab = tab2;
|
||||||
|
},
|
||||||
|
function step6() {
|
||||||
|
expect(DESTROYING, tab2.linkedBrowser.contentWindow);
|
||||||
|
expect(BEFORE_DESTROYED, tab2.linkedBrowser.contentWindow);
|
||||||
|
expect(DESTROYED, tab2.linkedBrowser.contentWindow);
|
||||||
|
after(DESTROYED, nextStep);
|
||||||
|
|
||||||
|
Tilt.destroy(Tilt.currentWindowId, true);
|
||||||
|
},
|
||||||
|
function step7() {
|
||||||
|
expect(SHOWN, tab1.linkedBrowser.contentWindow);
|
||||||
|
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
tab2 = null;
|
||||||
|
|
||||||
|
expect(DESTROYING, tab1.linkedBrowser.contentWindow);
|
||||||
|
expect(HIDDEN, tab1.linkedBrowser.contentWindow);
|
||||||
|
expect(BEFORE_DESTROYED, tab1.linkedBrowser.contentWindow);
|
||||||
|
expect(DESTROYED, tab1.linkedBrowser.contentWindow);
|
||||||
|
after(DESTROYED, nextStep);
|
||||||
|
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
tab1 = null;
|
||||||
|
},
|
||||||
|
function step8_cleanup() {
|
||||||
|
is(gBrowser.selectedTab, tab0, "Should be back to the first tab");
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
if (tab1) {
|
||||||
|
gBrowser.removeTab(tab1);
|
||||||
|
tab1 = null;
|
||||||
|
}
|
||||||
|
if (tab2) {
|
||||||
|
gBrowser.removeTab(tab2);
|
||||||
|
tab2 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.obs.removeObserver(notification, STARTUP);
|
||||||
|
Services.obs.removeObserver(notification, INITIALIZING);
|
||||||
|
Services.obs.removeObserver(notification, INITIALIZED);
|
||||||
|
Services.obs.removeObserver(notification, DESTROYING);
|
||||||
|
Services.obs.removeObserver(notification, BEFORE_DESTROYED);
|
||||||
|
Services.obs.removeObserver(notification, DESTROYED);
|
||||||
|
Services.obs.removeObserver(notification, SHOWN);
|
||||||
|
Services.obs.removeObserver(notification, HIDDEN);
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextStep() {
|
||||||
|
let step = testSteps.shift();
|
||||||
|
info("Executing " + step.name);
|
||||||
|
step();
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ function createNewTab() {
|
||||||
|
|
||||||
tab1 = createTab(function() {
|
tab1 = createTab(function() {
|
||||||
Services.obs.addObserver(finalize, DESTROYED, false);
|
Services.obs.addObserver(finalize, DESTROYED, false);
|
||||||
|
Services.obs.addObserver(tab_STARTUP, STARTUP, false);
|
||||||
Services.obs.addObserver(tab_INITIALIZING, INITIALIZING, false);
|
Services.obs.addObserver(tab_INITIALIZING, INITIALIZING, false);
|
||||||
Services.obs.addObserver(tab_DESTROYING, DESTROYING, false);
|
Services.obs.addObserver(tab_DESTROYING, DESTROYING, false);
|
||||||
Services.obs.addObserver(tab_SHOWN, SHOWN, false);
|
Services.obs.addObserver(tab_SHOWN, SHOWN, false);
|
||||||
|
@ -48,23 +49,33 @@ function createNewTab() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function tab_INITIALIZING() {
|
function tab_STARTUP(win) {
|
||||||
|
info("Handling the STARTUP notification.");
|
||||||
|
is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
|
||||||
|
tabEvents += "STARTUP;";
|
||||||
|
}
|
||||||
|
|
||||||
|
function tab_INITIALIZING(win) {
|
||||||
info("Handling the INITIALIZING notification.");
|
info("Handling the INITIALIZING notification.");
|
||||||
|
is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "INITIALIZING;";
|
tabEvents += "INITIALIZING;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function tab_DESTROYING() {
|
function tab_DESTROYING(win) {
|
||||||
info("Handling the DESTROYING notification.");
|
info("Handling the DESTROYING notification.");
|
||||||
|
is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "DESTROYING;";
|
tabEvents += "DESTROYING;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function tab_SHOWN() {
|
function tab_SHOWN(win) {
|
||||||
info("Handling the SHOWN notification.");
|
info("Handling the SHOWN notification.");
|
||||||
|
is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "SHOWN;";
|
tabEvents += "SHOWN;";
|
||||||
}
|
}
|
||||||
|
|
||||||
function tab_HIDDEN() {
|
function tab_HIDDEN(win) {
|
||||||
info("Handling the HIDDEN notification.");
|
info("Handling the HIDDEN notification.");
|
||||||
|
is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
|
||||||
tabEvents += "HIDDEN;";
|
tabEvents += "HIDDEN;";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +94,14 @@ let testSteps = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function finalize() {
|
function finalize(win) {
|
||||||
if (!tabEvents) {
|
if (!tabEvents) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
is(tabEvents, "INITIALIZING;HIDDEN;SHOWN;DESTROYING;",
|
is(win, tab1.linkedBrowser.contentWindow, "Saw the correct window");
|
||||||
|
|
||||||
|
is(tabEvents, "STARTUP;INITIALIZING;HIDDEN;SHOWN;DESTROYING;",
|
||||||
"The notifications weren't fired in the correct order.");
|
"The notifications weren't fired in the correct order.");
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
|
@ -74,13 +74,13 @@ function test() {
|
||||||
let store = dom.traverse(iframe.contentWindow);
|
let store = dom.traverse(iframe.contentWindow);
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
{ name: "html", depth: 0 * STACK_THICKNESS },
|
{ name: "html", depth: 0 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "head", depth: 1 * STACK_THICKNESS },
|
{ name: "head", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "body", depth: 1 * STACK_THICKNESS },
|
{ name: "body", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "style", depth: 2 * STACK_THICKNESS },
|
{ name: "style", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "script", depth: 2 * STACK_THICKNESS },
|
{ name: "script", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "div", depth: 2 * STACK_THICKNESS },
|
{ name: "div", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "span", depth: 3 * STACK_THICKNESS },
|
{ name: "span", depth: 3 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
];
|
];
|
||||||
|
|
||||||
is(store.nodes.length, expected.length,
|
is(store.nodes.length, expected.length,
|
||||||
|
@ -93,6 +93,8 @@ function test() {
|
||||||
"traversed node " + (i + 1) + " isn't the expected one.");
|
"traversed node " + (i + 1) + " isn't the expected one.");
|
||||||
is(store.info[i].coord.depth, expected[i].depth,
|
is(store.info[i].coord.depth, expected[i].depth,
|
||||||
"traversed node " + (i + 1) + " doesn't have the expected depth.");
|
"traversed node " + (i + 1) + " doesn't have the expected depth.");
|
||||||
|
is(store.info[i].coord.thickness, expected[i].thickness,
|
||||||
|
"traversed node " + (i + 1) + " doesn't have the expected thickness.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,22 +123,22 @@ function test() {
|
||||||
let store = dom.traverse(iframe.contentWindow);
|
let store = dom.traverse(iframe.contentWindow);
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
{ name: "html", depth: 0 * STACK_THICKNESS },
|
{ name: "html", depth: 0 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "head", depth: 1 * STACK_THICKNESS },
|
{ name: "head", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "body", depth: 1 * STACK_THICKNESS },
|
{ name: "body", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "div", depth: 2 * STACK_THICKNESS },
|
{ name: "div", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "span", depth: 2 * STACK_THICKNESS },
|
{ name: "span", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "iframe", depth: 2 * STACK_THICKNESS },
|
{ name: "iframe", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "span", depth: 2 * STACK_THICKNESS },
|
{ name: "span", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "iframe", depth: 2 * STACK_THICKNESS },
|
{ name: "iframe", depth: 2 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "html", depth: 3 * STACK_THICKNESS },
|
{ name: "html", depth: 3 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "html", depth: 3 * STACK_THICKNESS },
|
{ name: "html", depth: 3 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "head", depth: 4 * STACK_THICKNESS },
|
{ name: "head", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "body", depth: 4 * STACK_THICKNESS },
|
{ name: "body", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "head", depth: 4 * STACK_THICKNESS },
|
{ name: "head", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "body", depth: 4 * STACK_THICKNESS },
|
{ name: "body", depth: 4 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "span", depth: 5 * STACK_THICKNESS },
|
{ name: "span", depth: 5 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
{ name: "div", depth: 5 * STACK_THICKNESS },
|
{ name: "div", depth: 5 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
];
|
];
|
||||||
|
|
||||||
is(store.nodes.length, expected.length,
|
is(store.nodes.length, expected.length,
|
||||||
|
@ -151,6 +151,8 @@ function test() {
|
||||||
"traversed node " + (i + 1) + " isn't the expected one.");
|
"traversed node " + (i + 1) + " isn't the expected one.");
|
||||||
is(store.info[i].coord.depth, expected[i].depth,
|
is(store.info[i].coord.depth, expected[i].depth,
|
||||||
"traversed node " + (i + 1) + " doesn't have the expected depth.");
|
"traversed node " + (i + 1) + " doesn't have the expected depth.");
|
||||||
|
is(store.info[i].coord.thickness, expected[i].thickness,
|
||||||
|
"traversed node " + (i + 1) + " doesn't have the expected thickness.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const STACK_THICKNESS = 15;
|
||||||
|
|
||||||
|
function init(callback) {
|
||||||
|
let iframe = gBrowser.ownerDocument.createElement("iframe");
|
||||||
|
|
||||||
|
iframe.addEventListener("load", function onLoad() {
|
||||||
|
iframe.removeEventListener("load", onLoad, true);
|
||||||
|
callback(iframe);
|
||||||
|
|
||||||
|
gBrowser.parentNode.removeChild(iframe);
|
||||||
|
finish();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
iframe.setAttribute("src", ["data:text/html,",
|
||||||
|
"<!DOCTYPE html>",
|
||||||
|
"<html>",
|
||||||
|
"<body style='margin: 0;'>",
|
||||||
|
"<div>",
|
||||||
|
"<p>Foo</p>",
|
||||||
|
"<div>",
|
||||||
|
"<span>Bar</span>",
|
||||||
|
"</div>",
|
||||||
|
"<div></div>",
|
||||||
|
"</div>",
|
||||||
|
"</body>",
|
||||||
|
"</html>"
|
||||||
|
].join(""));
|
||||||
|
|
||||||
|
gBrowser.parentNode.appendChild(iframe);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nodeCallback(aContentWindow, aNode, aParentPosition) {
|
||||||
|
let coord = TiltUtils.DOM.getNodePosition(aContentWindow, aNode, aParentPosition);
|
||||||
|
|
||||||
|
if (aNode.localName != "div")
|
||||||
|
coord.thickness = 0;
|
||||||
|
|
||||||
|
if (aNode.localName == "span")
|
||||||
|
coord.depth += STACK_THICKNESS;
|
||||||
|
|
||||||
|
return coord;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
waitForExplicitFinish();
|
||||||
|
ok(TiltUtils, "The TiltUtils object doesn't exist.");
|
||||||
|
|
||||||
|
let dom = TiltUtils.DOM;
|
||||||
|
ok(dom, "The TiltUtils.DOM wasn't found.");
|
||||||
|
|
||||||
|
init(function(iframe) {
|
||||||
|
let store = dom.traverse(iframe.contentWindow, {
|
||||||
|
nodeCallback: nodeCallback
|
||||||
|
});
|
||||||
|
|
||||||
|
let expected = [
|
||||||
|
{ name: "html", depth: 0 * STACK_THICKNESS, thickness: 0 },
|
||||||
|
{ name: "head", depth: 0 * STACK_THICKNESS, thickness: 0 },
|
||||||
|
{ name: "body", depth: 0 * STACK_THICKNESS, thickness: 0 },
|
||||||
|
{ name: "div", depth: 0 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
|
{ name: "p", depth: 1 * STACK_THICKNESS, thickness: 0 },
|
||||||
|
{ name: "div", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
|
{ name: "div", depth: 1 * STACK_THICKNESS, thickness: STACK_THICKNESS },
|
||||||
|
{ name: "span", depth: 3 * STACK_THICKNESS, thickness: 0 },
|
||||||
|
];
|
||||||
|
|
||||||
|
is(store.nodes.length, expected.length,
|
||||||
|
"The traverse() function didn't walk the correct number of nodes.");
|
||||||
|
is(store.info.length, expected.length,
|
||||||
|
"The traverse() function didn't examine the correct number of nodes.");
|
||||||
|
|
||||||
|
for (let i = 0; i < expected.length; i++) {
|
||||||
|
is(store.info[i].name, expected[i].name,
|
||||||
|
"traversed node " + (i + 1) + " isn't the expected one.");
|
||||||
|
is(store.info[i].coord.depth, expected[i].depth,
|
||||||
|
"traversed node " + (i + 1) + " doesn't have the expected depth.");
|
||||||
|
is(store.info[i].coord.thickness, expected[i].thickness,
|
||||||
|
"traversed node " + (i + 1) + " doesn't have the expected thickness.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ function test() {
|
||||||
webGLLoad = true;
|
webGLLoad = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
visualizer.init();
|
||||||
|
|
||||||
ok(webGLError ^ webGLLoad,
|
ok(webGLError ^ webGLLoad,
|
||||||
"The WebGL context should either be created or not.");
|
"The WebGL context should either be created or not.");
|
||||||
|
|
|
@ -50,6 +50,7 @@ const DEFAULT_HTML = "data:text/html," +
|
||||||
|
|
||||||
let Tilt = TiltManager.getTiltForBrowser(window);
|
let Tilt = TiltManager.getTiltForBrowser(window);
|
||||||
|
|
||||||
|
const STARTUP = Tilt.NOTIFICATIONS.STARTUP;
|
||||||
const INITIALIZING = Tilt.NOTIFICATIONS.INITIALIZING;
|
const INITIALIZING = Tilt.NOTIFICATIONS.INITIALIZING;
|
||||||
const INITIALIZED = Tilt.NOTIFICATIONS.INITIALIZED;
|
const INITIALIZED = Tilt.NOTIFICATIONS.INITIALIZED;
|
||||||
const DESTROYING = Tilt.NOTIFICATIONS.DESTROYING;
|
const DESTROYING = Tilt.NOTIFICATIONS.DESTROYING;
|
||||||
|
|
|
@ -10,7 +10,6 @@ const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
const CONSOLEAPI_CLASS_ID = "{b49c18f8-3379-4fc0-8c90-d7772c1a9ff3}";
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
@ -23,15 +22,29 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||||
"resource://gre/modules/Services.jsm");
|
"resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
||||||
|
"resource://gre/modules/devtools/dbg-server.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient",
|
||||||
|
"resource://gre/modules/devtools/dbg-client.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
||||||
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "webConsoleDefinition",
|
||||||
|
"resource:///modules/devtools/ToolDefinitions.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "ViewHelpers",
|
||||||
|
"resource:///modules/devtools/ViewHelpers.jsm");
|
||||||
|
|
||||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||||
|
|
||||||
|
const BROWSER_CONSOLE_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["HUDService"];
|
this.EXPORTED_SYMBOLS = ["HUDService"];
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -75,14 +88,39 @@ HUD_SERVICE.prototype =
|
||||||
*
|
*
|
||||||
* @param object aTarget
|
* @param object aTarget
|
||||||
* The target that the web console will connect to.
|
* The target that the web console will connect to.
|
||||||
* @param nsIDOMElement aIframe
|
* @param nsIDOMWindow aIframeWindow
|
||||||
* The iframe element into which to place the web console.
|
* The window where the web console UI is already loaded.
|
||||||
|
* @param nsIDOMWindow aChromeWindow
|
||||||
|
* The window of the web console owner.
|
||||||
* @return object
|
* @return object
|
||||||
* A Promise object for the opening of the new WebConsole instance.
|
* A Promise object for the opening of the new WebConsole instance.
|
||||||
*/
|
*/
|
||||||
openWebConsole: function HS_openWebConsole(aTarget, aIframe)
|
openWebConsole:
|
||||||
|
function HS_openWebConsole(aTarget, aIframeWindow, aChromeWindow)
|
||||||
{
|
{
|
||||||
let hud = new WebConsole(aTarget, aIframe);
|
let hud = new WebConsole(aTarget, aIframeWindow, aChromeWindow);
|
||||||
|
this.hudReferences[hud.hudId] = hud;
|
||||||
|
return hud.init();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a Browser Console for the given target.
|
||||||
|
*
|
||||||
|
* @see devtools/framework/Target.jsm for details about targets.
|
||||||
|
*
|
||||||
|
* @param object aTarget
|
||||||
|
* The target that the browser console will connect to.
|
||||||
|
* @param nsIDOMWindow aIframeWindow
|
||||||
|
* The window where the browser console UI is already loaded.
|
||||||
|
* @param nsIDOMWindow aChromeWindow
|
||||||
|
* The window of the browser console owner.
|
||||||
|
* @return object
|
||||||
|
* A Promise object for the opening of the new BrowserConsole instance.
|
||||||
|
*/
|
||||||
|
openBrowserConsole:
|
||||||
|
function HS_openBrowserConsole(aTarget, aIframeWindow, aChromeWindow)
|
||||||
|
{
|
||||||
|
let hud = new BrowserConsole(aTarget, aIframeWindow, aChromeWindow);
|
||||||
this.hudReferences[hud.hudId] = hud;
|
this.hudReferences[hud.hudId] = hud;
|
||||||
return hud.init();
|
return hud.init();
|
||||||
},
|
},
|
||||||
|
@ -144,24 +182,27 @@ HUD_SERVICE.prototype =
|
||||||
* that displays console log data as well as provides an interactive terminal to
|
* that displays console log data as well as provides an interactive terminal to
|
||||||
* manipulate the target's document content.
|
* manipulate the target's document content.
|
||||||
*
|
*
|
||||||
* This object only wraps the iframe that holds the Web Console UI.
|
* This object only wraps the iframe that holds the Web Console UI. This is
|
||||||
|
* meant to be an integration point between the Firefox UI and the Web Console
|
||||||
|
* UI and features.
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param object aTarget
|
* @param object aTarget
|
||||||
* The target that the web console will connect to.
|
* The target that the web console will connect to.
|
||||||
* @param nsIDOMElement aIframe
|
* @param nsIDOMWindow aIframeWindow
|
||||||
* iframe into which we should create the WebConsole UI.
|
* The window where the web console UI is already loaded.
|
||||||
|
* @param nsIDOMWindow aChromeWindow
|
||||||
|
* The window of the web console owner.
|
||||||
*/
|
*/
|
||||||
function WebConsole(aTarget, aIframe)
|
function WebConsole(aTarget, aIframeWindow, aChromeWindow)
|
||||||
{
|
{
|
||||||
this.iframe = aIframe;
|
this.iframeWindow = aIframeWindow;
|
||||||
this.iframe.className = "web-console-frame";
|
this.chromeWindow = aChromeWindow;
|
||||||
this.chromeDocument = this.iframe.ownerDocument;
|
|
||||||
this.chromeWindow = this.chromeDocument.defaultView;
|
|
||||||
this.hudId = "hud_" + Date.now();
|
this.hudId = "hud_" + Date.now();
|
||||||
this.target = aTarget;
|
this.target = aTarget;
|
||||||
|
|
||||||
this.browserWindow = this.chromeWindow.top;
|
this.browserWindow = this.chromeWindow.top;
|
||||||
|
|
||||||
let element = this.browserWindow.document.documentElement;
|
let element = this.browserWindow.document.documentElement;
|
||||||
if (element.getAttribute("windowtype") != "navigator:browser") {
|
if (element.getAttribute("windowtype") != "navigator:browser") {
|
||||||
this.browserWindow = HUDService.currentContext();
|
this.browserWindow = HUDService.currentContext();
|
||||||
|
@ -169,11 +210,12 @@ function WebConsole(aTarget, aIframe)
|
||||||
}
|
}
|
||||||
|
|
||||||
WebConsole.prototype = {
|
WebConsole.prototype = {
|
||||||
|
iframeWindow: null,
|
||||||
chromeWindow: null,
|
chromeWindow: null,
|
||||||
chromeDocument: null,
|
browserWindow: null,
|
||||||
hudId: null,
|
hudId: null,
|
||||||
target: null,
|
target: null,
|
||||||
iframe: null,
|
_browserConsole: false,
|
||||||
_destroyer: null,
|
_destroyer: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,37 +254,8 @@ WebConsole.prototype = {
|
||||||
*/
|
*/
|
||||||
init: function WC_init()
|
init: function WC_init()
|
||||||
{
|
{
|
||||||
let deferred = Promise.defer();
|
this.ui = new this.iframeWindow.WebConsoleFrame(this);
|
||||||
|
return this.ui.init().then(() => this);
|
||||||
let onIframeLoad = function() {
|
|
||||||
this.iframe.removeEventListener("load", onIframeLoad, true);
|
|
||||||
initUI();
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
let initUI = function() {
|
|
||||||
this.iframeWindow = this.iframe.contentWindow.wrappedJSObject;
|
|
||||||
this.ui = new this.iframeWindow.WebConsoleFrame(this);
|
|
||||||
this.ui.init().then(onSuccess, onFailure);
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
let onSuccess = function() {
|
|
||||||
deferred.resolve(this);
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
let onFailure = function(aReason) {
|
|
||||||
deferred.reject(aReason);
|
|
||||||
};
|
|
||||||
|
|
||||||
let win, doc;
|
|
||||||
if ((win = this.iframe.contentWindow) &&
|
|
||||||
(doc = win.document) &&
|
|
||||||
doc.readyState == "complete") {
|
|
||||||
initUI();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.iframe.addEventListener("load", onIframeLoad, true);
|
|
||||||
}
|
|
||||||
return deferred.promise;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -360,6 +373,10 @@ WebConsole.prototype = {
|
||||||
let panelWin = null;
|
let panelWin = null;
|
||||||
let debuggerWasOpen = true;
|
let debuggerWasOpen = true;
|
||||||
let toolbox = gDevTools.getToolbox(this.target);
|
let toolbox = gDevTools.getToolbox(this.target);
|
||||||
|
if (!toolbox) {
|
||||||
|
self.viewSource(aSourceURL, aSourceLine);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!toolbox.getPanel("jsdebugger")) {
|
if (!toolbox.getPanel("jsdebugger")) {
|
||||||
debuggerWasOpen = false;
|
debuggerWasOpen = false;
|
||||||
|
@ -404,6 +421,40 @@ WebConsole.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve information about the JavaScript debugger's stackframes list. This
|
||||||
|
* is used to allow the Web Console to evaluate code in the selected
|
||||||
|
* stackframe.
|
||||||
|
*
|
||||||
|
* @return object|null
|
||||||
|
* An object which holds:
|
||||||
|
* - frames: the active ThreadClient.cachedFrames array.
|
||||||
|
* - selected: depth/index of the selected stackframe in the debugger
|
||||||
|
* UI.
|
||||||
|
* If the debugger is not open or if it's not paused, then |null| is
|
||||||
|
* returned.
|
||||||
|
*/
|
||||||
|
getDebuggerFrames: function WC_getDebuggerFrames()
|
||||||
|
{
|
||||||
|
let toolbox = gDevTools.getToolbox(this.target);
|
||||||
|
if (!toolbox) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let panel = toolbox.getPanel("jsdebugger");
|
||||||
|
if (!panel) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let framesController = panel.panelWin.gStackFrames;
|
||||||
|
let thread = framesController.activeThread;
|
||||||
|
if (thread && thread.paused) {
|
||||||
|
return {
|
||||||
|
frames: thread.cachedFrames,
|
||||||
|
selected: framesController.currentFrame,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the object. Call this method to avoid memory leaks when the Web
|
* Destroy the object. Call this method to avoid memory leaks when the Web
|
||||||
* Console is closed.
|
* Console is closed.
|
||||||
|
@ -452,11 +503,102 @@ WebConsole.prototype = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A BrowserConsole instance is an interactive console initialized *per target*
|
||||||
|
* that displays console log data as well as provides an interactive terminal to
|
||||||
|
* manipulate the target's document content.
|
||||||
|
*
|
||||||
|
* This object only wraps the iframe that holds the Browser Console UI. This is
|
||||||
|
* meant to be an integration point between the Firefox UI and the Browser Console
|
||||||
|
* UI and features.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param object aTarget
|
||||||
|
* The target that the browser console will connect to.
|
||||||
|
* @param nsIDOMWindow aIframeWindow
|
||||||
|
* The window where the browser console UI is already loaded.
|
||||||
|
* @param nsIDOMWindow aChromeWindow
|
||||||
|
* The window of the browser console owner.
|
||||||
|
*/
|
||||||
|
function BrowserConsole()
|
||||||
|
{
|
||||||
|
WebConsole.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewHelpers.create({ constructor: BrowserConsole, proto: WebConsole.prototype },
|
||||||
|
{
|
||||||
|
_browserConsole: true,
|
||||||
|
_bc_init: null,
|
||||||
|
_bc_destroyer: null,
|
||||||
|
|
||||||
|
$init: WebConsole.prototype.init,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the Browser Console instance.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
* A Promise for the initialization.
|
||||||
|
*/
|
||||||
|
init: function BC_init()
|
||||||
|
{
|
||||||
|
if (this._bc_init) {
|
||||||
|
return this._bc_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
let window = this.iframeWindow;
|
||||||
|
let onClose = () => {
|
||||||
|
window.removeEventListener("unload", onClose);
|
||||||
|
this.destroy();
|
||||||
|
};
|
||||||
|
window.addEventListener("unload", onClose);
|
||||||
|
|
||||||
|
this._bc_init = this.$init().then((aReason) => {
|
||||||
|
let title = this.ui.rootElement.getAttribute("browserConsoleTitle");
|
||||||
|
this.ui.rootElement.setAttribute("title", title);
|
||||||
|
return aReason;
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._bc_init;
|
||||||
|
},
|
||||||
|
|
||||||
|
$destroy: WebConsole.prototype.destroy,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the object.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
* A Promise object that is resolved once the Browser Console is closed.
|
||||||
|
*/
|
||||||
|
destroy: function BC_destroy()
|
||||||
|
{
|
||||||
|
if (this._bc_destroyer) {
|
||||||
|
return this._bc_destroyer.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._bc_destroyer = Promise.defer();
|
||||||
|
|
||||||
|
let chromeWindow = this.chromeWindow;
|
||||||
|
this.$destroy().then(() =>
|
||||||
|
this.target.client.close(() => {
|
||||||
|
HeadsUpDisplayUICommands._browserConsoleID = null;
|
||||||
|
chromeWindow.close();
|
||||||
|
this._bc_destroyer.resolve(null);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return this._bc_destroyer.promise;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// HeadsUpDisplayUICommands
|
// HeadsUpDisplayUICommands
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var HeadsUpDisplayUICommands = {
|
var HeadsUpDisplayUICommands = {
|
||||||
|
_browserConsoleID: null,
|
||||||
|
_browserConsoleDefer: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the Web Console for the current tab.
|
* Toggle the Web Console for the current tab.
|
||||||
*
|
*
|
||||||
|
@ -493,6 +635,83 @@ var HeadsUpDisplayUICommands = {
|
||||||
let panel = toolbox ? toolbox.getPanel("webconsole") : null;
|
let panel = toolbox ? toolbox.getPanel("webconsole") : null;
|
||||||
return panel ? panel.hud : null;
|
return panel ? panel.hud : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the Browser Console.
|
||||||
|
*/
|
||||||
|
toggleBrowserConsole: function UIC_toggleBrowserConsole()
|
||||||
|
{
|
||||||
|
if (this._browserConsoleID) {
|
||||||
|
let hud = HUDService.getHudReferenceById(this._browserConsoleID);
|
||||||
|
return hud.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._browserConsoleDefer) {
|
||||||
|
return this._browserConsoleDefer.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._browserConsoleDefer = Promise.defer();
|
||||||
|
|
||||||
|
function connect()
|
||||||
|
{
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
if (!DebuggerServer.initialized) {
|
||||||
|
DebuggerServer.init();
|
||||||
|
DebuggerServer.addBrowserActors();
|
||||||
|
}
|
||||||
|
|
||||||
|
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
client.connect(() =>
|
||||||
|
client.listTabs((aResponse) =>
|
||||||
|
deferred.resolve({ form: aResponse, client: client })
|
||||||
|
));
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
let target;
|
||||||
|
function getTarget(aConnection)
|
||||||
|
{
|
||||||
|
let options = {
|
||||||
|
form: aConnection.form,
|
||||||
|
client: aConnection.client,
|
||||||
|
chrome: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
return TargetFactory.forRemoteTab(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openWindow(aTarget)
|
||||||
|
{
|
||||||
|
target = aTarget;
|
||||||
|
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
let win = Services.ww.openWindow(null, webConsoleDefinition.url, "_blank",
|
||||||
|
BROWSER_CONSOLE_WINDOW_FEATURES, null);
|
||||||
|
win.addEventListener("load", function onLoad() {
|
||||||
|
win.removeEventListener("load", onLoad);
|
||||||
|
deferred.resolve(win);
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect().then(getTarget).then(openWindow).then((aWindow) =>
|
||||||
|
HUDService.openBrowserConsole(target, aWindow, aWindow)
|
||||||
|
.then((aBrowserConsole) => {
|
||||||
|
this._browserConsoleID = aBrowserConsole.hudId;
|
||||||
|
this._browserConsoleDefer.resolve(aBrowserConsole);
|
||||||
|
this._browserConsoleDefer = null;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return this._browserConsoleDefer.promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
get browserConsole() {
|
||||||
|
return HUDService.getHudReferenceById(this._browserConsoleID);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const HUDService = new HUD_SERVICE();
|
const HUDService = new HUD_SERVICE();
|
||||||
|
|
|
@ -41,26 +41,52 @@ WebConsolePanel.prototype = {
|
||||||
{
|
{
|
||||||
let parentDoc = this._toolbox.doc;
|
let parentDoc = this._toolbox.doc;
|
||||||
let iframe = parentDoc.getElementById("toolbox-panel-iframe-webconsole");
|
let iframe = parentDoc.getElementById("toolbox-panel-iframe-webconsole");
|
||||||
let promise;
|
iframe.className = "web-console-frame";
|
||||||
|
|
||||||
// Local debugging needs to make the target remote.
|
// Make sure the iframe content window is ready.
|
||||||
if (!this.target.isRemote) {
|
let deferredIframe = Promise.defer();
|
||||||
promise = this.target.makeRemote();
|
let win, doc;
|
||||||
} else {
|
if ((win = iframe.contentWindow) &&
|
||||||
promise = Promise.resolve(this.target);
|
(doc = win.document) &&
|
||||||
|
doc.readyState == "complete") {
|
||||||
|
deferredIframe.resolve(null);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iframe.addEventListener("load", function onIframeLoad() {
|
||||||
|
iframe.removeEventListener("load", onIframeLoad, true);
|
||||||
|
deferredIframe.resolve(null);
|
||||||
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise
|
// Local debugging needs to make the target remote.
|
||||||
.then(function(aTarget) {
|
let promiseTarget;
|
||||||
|
if (!this.target.isRemote) {
|
||||||
|
promiseTarget = this.target.makeRemote();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
promiseTarget = Promise.resolve(this.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Wait for the iframe to load.
|
||||||
|
// 2. Wait for the remote target.
|
||||||
|
// 3. Open the Web Console.
|
||||||
|
return deferredIframe.promise
|
||||||
|
.then(() => promiseTarget)
|
||||||
|
.then((aTarget) => {
|
||||||
this._frameWindow._remoteTarget = aTarget;
|
this._frameWindow._remoteTarget = aTarget;
|
||||||
return HUDService.openWebConsole(this.target, iframe);
|
|
||||||
}.bind(this))
|
let webConsoleUIWindow = iframe.contentWindow.wrappedJSObject;
|
||||||
.then(function onSuccess(aWebConsole) {
|
let chromeWindow = iframe.ownerDocument.defaultView;
|
||||||
|
|
||||||
|
return HUDService.openWebConsole(this.target, webConsoleUIWindow,
|
||||||
|
chromeWindow);
|
||||||
|
})
|
||||||
|
.then((aWebConsole) => {
|
||||||
this.hud = aWebConsole;
|
this.hud = aWebConsole;
|
||||||
this._isReady = true;
|
this._isReady = true;
|
||||||
this.emit("ready");
|
this.emit("ready");
|
||||||
return this;
|
return this;
|
||||||
}.bind(this), function onError(aReason) {
|
}, (aReason) => {
|
||||||
let msg = "WebConsolePanel open failed. " +
|
let msg = "WebConsolePanel open failed. " +
|
||||||
aReason.error + ": " + aReason.message;
|
aReason.error + ": " + aReason.message;
|
||||||
dump(msg + "\n");
|
dump(msg + "\n");
|
||||||
|
@ -80,9 +106,7 @@ WebConsolePanel.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this._destroyer = this.hud.destroy();
|
this._destroyer = this.hud.destroy();
|
||||||
this._destroyer.then(function() {
|
this._destroyer.then(() => this.emit("destroyed"));
|
||||||
this.emit("destroyed");
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
return this._destroyer;
|
return this._destroyer;
|
||||||
},
|
},
|
||||||
|
|
|
@ -42,7 +42,6 @@ MOCHITEST_BROWSER_FILES = \
|
||||||
browser_webconsole_jsterm.js \
|
browser_webconsole_jsterm.js \
|
||||||
browser_webconsole_null_and_undefined_output.js \
|
browser_webconsole_null_and_undefined_output.js \
|
||||||
browser_webconsole_output_order.js \
|
browser_webconsole_output_order.js \
|
||||||
browser_webconsole_property_panel.js \
|
|
||||||
browser_webconsole_property_provider.js \
|
browser_webconsole_property_provider.js \
|
||||||
browser_webconsole_bug_587617_output_copy.js \
|
browser_webconsole_bug_587617_output_copy.js \
|
||||||
browser_webconsole_bug_585237_line_limit.js \
|
browser_webconsole_bug_585237_line_limit.js \
|
||||||
|
@ -116,10 +115,12 @@ MOCHITEST_BROWSER_FILES = \
|
||||||
browser_output_longstring_expand.js \
|
browser_output_longstring_expand.js \
|
||||||
browser_netpanel_longstring_expand.js \
|
browser_netpanel_longstring_expand.js \
|
||||||
browser_repeated_messages_accuracy.js \
|
browser_repeated_messages_accuracy.js \
|
||||||
head.js \
|
|
||||||
browser_webconsole_bug_821877_csp_errors.js \
|
browser_webconsole_bug_821877_csp_errors.js \
|
||||||
test-bug-821877-csperrors.html \
|
browser_eval_in_debugger_stackframe.js \
|
||||||
test-bug-821877-csperrors.html^headers^ \
|
browser_console_variables_view.js \
|
||||||
|
browser_console_variables_view_while_debugging.js \
|
||||||
|
browser_console.js \
|
||||||
|
head.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifeq ($(OS_ARCH), Darwin)
|
ifeq ($(OS_ARCH), Darwin)
|
||||||
|
@ -217,6 +218,9 @@ MOCHITEST_BROWSER_FILES += \
|
||||||
test-bug-766001-console-log.js \
|
test-bug-766001-console-log.js \
|
||||||
test-bug-766001-js-console-links.html \
|
test-bug-766001-js-console-links.html \
|
||||||
test-bug-766001-js-errors.js \
|
test-bug-766001-js-errors.js \
|
||||||
|
test-bug-821877-csperrors.html \
|
||||||
|
test-bug-821877-csperrors.html^headers^ \
|
||||||
|
test-eval-in-stackframe.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
|
@ -52,7 +52,7 @@ function test()
|
||||||
gBrowser.selectedBrowser.addEventListener("load", onPageLoad2, true);
|
gBrowser.selectedBrowser.addEventListener("load", onPageLoad2, true);
|
||||||
content.location = TEST_URI2;
|
content.location = TEST_URI2;
|
||||||
},
|
},
|
||||||
failureFn: finishTest,
|
failureFn: finishTestWithError,
|
||||||
};
|
};
|
||||||
|
|
||||||
function onPageLoad2() {
|
function onPageLoad2() {
|
||||||
|
@ -82,7 +82,7 @@ function test()
|
||||||
gBrowser.goBack();
|
gBrowser.goBack();
|
||||||
waitForSuccess(waitForBack);
|
waitForSuccess(waitForBack);
|
||||||
},
|
},
|
||||||
failureFn: finishTest,
|
failureFn: finishTestWithError,
|
||||||
};
|
};
|
||||||
|
|
||||||
let waitForBack = {
|
let waitForBack = {
|
||||||
|
@ -98,7 +98,7 @@ function test()
|
||||||
|
|
||||||
waitForSuccess(waitForLocation3);
|
waitForSuccess(waitForLocation3);
|
||||||
},
|
},
|
||||||
failureFn: finishTest,
|
failureFn: finishTestWithError,
|
||||||
};
|
};
|
||||||
|
|
||||||
let waitForLocation3 = {
|
let waitForLocation3 = {
|
||||||
|
@ -118,6 +118,12 @@ function test()
|
||||||
|
|
||||||
executeSoon(finishTest);
|
executeSoon(finishTest);
|
||||||
},
|
},
|
||||||
failureFn: finishTest,
|
failureFn: finishTestWithError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function finishTestWithError()
|
||||||
|
{
|
||||||
|
info("output content: " + hud.outputNode.textContent);
|
||||||
|
finishTest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test the basic features of the Browser Console, bug 587757.
|
||||||
|
|
||||||
|
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
HUDConsoleUI.toggleBrowserConsole().then(consoleOpened);
|
||||||
|
}
|
||||||
|
|
||||||
|
function consoleOpened(hud)
|
||||||
|
{
|
||||||
|
hud.jsterm.clearOutput(true);
|
||||||
|
|
||||||
|
expectUncaughtException();
|
||||||
|
executeSoon(() => {
|
||||||
|
foobarExceptionBug587757();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a message from a chrome window.
|
||||||
|
hud.iframeWindow.console.log("bug587757a");
|
||||||
|
|
||||||
|
// Add a message from a content window.
|
||||||
|
content.console.log("bug587757b");
|
||||||
|
|
||||||
|
// Test eval.
|
||||||
|
hud.jsterm.execute("document.location.href");
|
||||||
|
|
||||||
|
// Check for network requests.
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.onload = () => info("xhr loaded, status is: " + xhr.status);
|
||||||
|
xhr.open("get", TEST_URI, true);
|
||||||
|
xhr.send();
|
||||||
|
|
||||||
|
let chromeConsole = -1;
|
||||||
|
let contentConsole = -1;
|
||||||
|
let execValue = -1;
|
||||||
|
let exception = -1;
|
||||||
|
let xhrRequest = false;
|
||||||
|
|
||||||
|
let output = hud.outputNode;
|
||||||
|
function performChecks()
|
||||||
|
{
|
||||||
|
let text = output.textContent;
|
||||||
|
chromeConsole = text.indexOf("bug587757a");
|
||||||
|
contentConsole = text.indexOf("bug587757b");
|
||||||
|
execValue = text.indexOf("browser.xul");
|
||||||
|
exception = text.indexOf("foobarExceptionBug587757");
|
||||||
|
|
||||||
|
xhrRequest = false;
|
||||||
|
let urls = output.querySelectorAll(".webconsole-msg-url");
|
||||||
|
for (let url of urls) {
|
||||||
|
if (url.value.indexOf(TEST_URI) > -1) {
|
||||||
|
xhrRequest = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResults()
|
||||||
|
{
|
||||||
|
isnot(chromeConsole, -1, "chrome window console.log() is displayed");
|
||||||
|
isnot(contentConsole, -1, "content window console.log() is displayed");
|
||||||
|
isnot(execValue, -1, "jsterm eval result is displayed");
|
||||||
|
isnot(exception, -1, "exception is displayed");
|
||||||
|
ok(xhrRequest, "xhr request is displayed");
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForSuccess({
|
||||||
|
name: "messages displayed",
|
||||||
|
validatorFn: () => {
|
||||||
|
performChecks();
|
||||||
|
return chromeConsole > -1 &&
|
||||||
|
contentConsole > -1 &&
|
||||||
|
execValue > -1 &&
|
||||||
|
exception > -1 &&
|
||||||
|
xhrRequest;
|
||||||
|
},
|
||||||
|
successFn: () => {
|
||||||
|
showResults();
|
||||||
|
executeSoon(finishTest);
|
||||||
|
},
|
||||||
|
failureFn: () => {
|
||||||
|
showResults();
|
||||||
|
info("output: " + output.textContent);
|
||||||
|
executeSoon(finishTest);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
|
@ -36,17 +36,18 @@ function performTest(hud)
|
||||||
|
|
||||||
let clickable = hud.outputNode.querySelector(".hud-clickable");
|
let clickable = hud.outputNode.querySelector(".hud-clickable");
|
||||||
ok(clickable, "the console.log() object .hud-clickable was found");
|
ok(clickable, "the console.log() object .hud-clickable was found");
|
||||||
isnot(clickable.textContent.indexOf("omgBug676722"), -1,
|
isnot(clickable.textContent.indexOf("Object"), -1,
|
||||||
"clickable node content is correct");
|
"clickable node content is correct");
|
||||||
|
|
||||||
document.addEventListener("popupshown", function _onPopupShown(aEvent) {
|
hud.jsterm.once("variablesview-fetched",
|
||||||
document.removeEventListener("popupshown", _onPopupShown);
|
(aEvent, aVar) => {
|
||||||
|
ok(aVar, "object inspector opened on click");
|
||||||
|
|
||||||
isnot(aEvent.target.label.indexOf("omgBug676722"), -1,
|
findVariableViewProperties(aVar, [{
|
||||||
"object inspector opened on click");
|
name: "abba",
|
||||||
|
value: "omgBug676722",
|
||||||
executeSoon(finishTest);
|
}], { webconsole: hud }).then(finishTest);
|
||||||
});
|
});
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
|
EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test that makes sure web console eval happens in the user-selected stackframe
|
||||||
|
// from the js debugger.
|
||||||
|
|
||||||
|
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
|
||||||
|
|
||||||
|
let gWebConsole, gJSTerm, gVariablesView;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
addTab(TEST_URI);
|
||||||
|
browser.addEventListener("load", function onLoad() {
|
||||||
|
browser.removeEventListener("load", onLoad, true);
|
||||||
|
openConsole(null, consoleOpened);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function consoleOpened(hud)
|
||||||
|
{
|
||||||
|
gWebConsole = hud;
|
||||||
|
gJSTerm = hud.jsterm;
|
||||||
|
gJSTerm.execute("fooObj", onExecuteFooObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExecuteFooObj()
|
||||||
|
{
|
||||||
|
let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
|
||||||
|
ok(msg, "output message found");
|
||||||
|
isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
|
||||||
|
|
||||||
|
gJSTerm.once("variablesview-fetched", onFooObjFetch);
|
||||||
|
|
||||||
|
executeSoon(() =>
|
||||||
|
EventUtils.synthesizeMouse(msg, 2, 2, {}, gWebConsole.iframeWindow)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFooObjFetch(aEvent, aVar)
|
||||||
|
{
|
||||||
|
gVariablesView = aVar._variablesView;
|
||||||
|
ok(gVariablesView, "variables view object");
|
||||||
|
|
||||||
|
findVariableViewProperties(aVar, [
|
||||||
|
{ name: "testProp", value: "testValue" },
|
||||||
|
], { webconsole: gWebConsole }).then(onTestPropFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTestPropFound(aResults)
|
||||||
|
{
|
||||||
|
let prop = aResults[0].matchedProp;
|
||||||
|
ok(prop, "matched the |testProp| property in the variables view");
|
||||||
|
|
||||||
|
is(content.wrappedJSObject.fooObj.testProp, aResults[0].value,
|
||||||
|
"|fooObj.testProp| value is correct");
|
||||||
|
|
||||||
|
// Check that property value updates work and that jsterm functions can be
|
||||||
|
// used.
|
||||||
|
updateVariablesViewProperty({
|
||||||
|
property: prop,
|
||||||
|
field: "value",
|
||||||
|
string: "document.title + window.location + $('p')",
|
||||||
|
webconsole: gWebConsole,
|
||||||
|
callback: onFooObjFetchAfterUpdate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFooObjFetchAfterUpdate(aEvent, aVar)
|
||||||
|
{
|
||||||
|
info("onFooObjFetchAfterUpdate");
|
||||||
|
let para = content.document.querySelector("p");
|
||||||
|
let expectedValue = content.document.title + content.location + para;
|
||||||
|
|
||||||
|
findVariableViewProperties(aVar, [
|
||||||
|
{ name: "testProp", value: expectedValue },
|
||||||
|
], { webconsole: gWebConsole }).then(onUpdatedTestPropFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onUpdatedTestPropFound(aResults)
|
||||||
|
{
|
||||||
|
let prop = aResults[0].matchedProp;
|
||||||
|
ok(prop, "matched the updated |testProp| property value");
|
||||||
|
|
||||||
|
is(content.wrappedJSObject.fooObj.testProp, aResults[0].value,
|
||||||
|
"|fooObj.testProp| value has been updated");
|
||||||
|
|
||||||
|
// Check that property name updates work.
|
||||||
|
updateVariablesViewProperty({
|
||||||
|
property: prop,
|
||||||
|
field: "name",
|
||||||
|
string: "testUpdatedProp",
|
||||||
|
webconsole: gWebConsole,
|
||||||
|
callback: onFooObjFetchAfterPropRename,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFooObjFetchAfterPropRename(aEvent, aVar)
|
||||||
|
{
|
||||||
|
info("onFooObjFetchAfterPropRename");
|
||||||
|
|
||||||
|
let para = content.document.querySelector("p");
|
||||||
|
let expectedValue = content.document.title + content.location + para;
|
||||||
|
|
||||||
|
// Check that the new value is in the variables view.
|
||||||
|
findVariableViewProperties(aVar, [
|
||||||
|
{ name: "testUpdatedProp", value: expectedValue },
|
||||||
|
], { webconsole: gWebConsole }).then(onRenamedTestPropFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRenamedTestPropFound(aResults)
|
||||||
|
{
|
||||||
|
let prop = aResults[0].matchedProp;
|
||||||
|
ok(prop, "matched the renamed |testProp| property");
|
||||||
|
|
||||||
|
ok(!content.wrappedJSObject.fooObj.testProp,
|
||||||
|
"|fooObj.testProp| has been deleted");
|
||||||
|
is(content.wrappedJSObject.fooObj.testUpdatedProp, aResults[0].value,
|
||||||
|
"|fooObj.testUpdatedProp| is correct");
|
||||||
|
|
||||||
|
// Check that property value updates that cause exceptions are reported in
|
||||||
|
// the web console output.
|
||||||
|
updateVariablesViewProperty({
|
||||||
|
property: prop,
|
||||||
|
field: "value",
|
||||||
|
string: "foobarzFailure()",
|
||||||
|
webconsole: gWebConsole,
|
||||||
|
callback: onPropUpdateError,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPropUpdateError(aEvent, aVar)
|
||||||
|
{
|
||||||
|
info("onPropUpdateError");
|
||||||
|
|
||||||
|
let para = content.document.querySelector("p");
|
||||||
|
let expectedValue = content.document.title + content.location + para;
|
||||||
|
|
||||||
|
// Make sure the property did not change.
|
||||||
|
findVariableViewProperties(aVar, [
|
||||||
|
{ name: "testUpdatedProp", value: expectedValue },
|
||||||
|
], { webconsole: gWebConsole }).then(onRenamedTestPropFoundAgain);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRenamedTestPropFoundAgain(aResults)
|
||||||
|
{
|
||||||
|
let prop = aResults[0].matchedProp;
|
||||||
|
ok(prop, "matched the renamed |testProp| property again");
|
||||||
|
|
||||||
|
let outputNode = gWebConsole.outputNode;
|
||||||
|
|
||||||
|
waitForSuccess({
|
||||||
|
name: "exception in property update reported in the web console output",
|
||||||
|
validatorFn: () => outputNode.textContent.indexOf("foobarzFailure") != -1,
|
||||||
|
successFn: testPropDelete.bind(null, prop),
|
||||||
|
failureFn: testPropDelete.bind(null, prop),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPropDelete(aProp)
|
||||||
|
{
|
||||||
|
gVariablesView.window.focus();
|
||||||
|
aProp.focus();
|
||||||
|
|
||||||
|
executeSoon(() => {
|
||||||
|
EventUtils.synthesizeKey("VK_DELETE", {}, gVariablesView.window);
|
||||||
|
gWebConsole = gJSTerm = gVariablesView = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
waitForSuccess({
|
||||||
|
name: "property deleted",
|
||||||
|
validatorFn: () => !("testUpdatedProp" in content.wrappedJSObject.fooObj),
|
||||||
|
successFn: finishTest,
|
||||||
|
failureFn: finishTest,
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test that makes sure web console eval happens in the user-selected stackframe
|
||||||
|
// from the js debugger, when changing the value of a property in the variables
|
||||||
|
// view.
|
||||||
|
|
||||||
|
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
|
||||||
|
|
||||||
|
let gWebConsole, gJSTerm, gDebuggerWin, gThread, gDebuggerController,
|
||||||
|
gStackframes, gVariablesView;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
addTab(TEST_URI);
|
||||||
|
browser.addEventListener("load", function onLoad() {
|
||||||
|
browser.removeEventListener("load", onLoad, true);
|
||||||
|
openConsole(null, consoleOpened);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function consoleOpened(hud)
|
||||||
|
{
|
||||||
|
gWebConsole = hud;
|
||||||
|
gJSTerm = hud.jsterm;
|
||||||
|
|
||||||
|
executeSoon(() => {
|
||||||
|
info("openDebugger");
|
||||||
|
openDebugger().then(debuggerOpened);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function debuggerOpened(aResult)
|
||||||
|
{
|
||||||
|
gDebuggerWin = aResult.panelWin;
|
||||||
|
gDebuggerController = gDebuggerWin.DebuggerController;
|
||||||
|
gThread = gDebuggerController.activeThread;
|
||||||
|
gStackframes = gDebuggerController.StackFrames;
|
||||||
|
|
||||||
|
executeSoon(() => {
|
||||||
|
gThread.addOneTimeListener("framesadded", onFramesAdded);
|
||||||
|
|
||||||
|
info("firstCall()");
|
||||||
|
content.wrappedJSObject.firstCall();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFramesAdded()
|
||||||
|
{
|
||||||
|
info("onFramesAdded");
|
||||||
|
|
||||||
|
executeSoon(() =>
|
||||||
|
openConsole(null, () =>
|
||||||
|
gJSTerm.execute("fooObj", onExecuteFooObj)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function onExecuteFooObj()
|
||||||
|
{
|
||||||
|
let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
|
||||||
|
ok(msg, "output message found");
|
||||||
|
isnot(msg.textContent.indexOf("[object Object]"), -1, "message text check");
|
||||||
|
|
||||||
|
gJSTerm.once("variablesview-fetched", onFooObjFetch);
|
||||||
|
|
||||||
|
executeSoon(() => EventUtils.synthesizeMouse(msg, 2, 2, {},
|
||||||
|
gWebConsole.iframeWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFooObjFetch(aEvent, aVar)
|
||||||
|
{
|
||||||
|
gVariablesView = aVar._variablesView;
|
||||||
|
ok(gVariablesView, "variables view object");
|
||||||
|
|
||||||
|
findVariableViewProperties(aVar, [
|
||||||
|
{ name: "testProp2", value: "testValue2" },
|
||||||
|
{ name: "testProp", value: "testValue", dontMatch: true },
|
||||||
|
], { webconsole: gWebConsole }).then(onTestPropFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTestPropFound(aResults)
|
||||||
|
{
|
||||||
|
let prop = aResults[0].matchedProp;
|
||||||
|
ok(prop, "matched the |testProp2| property in the variables view");
|
||||||
|
|
||||||
|
// Check that property value updates work and that jsterm functions can be
|
||||||
|
// used.
|
||||||
|
updateVariablesViewProperty({
|
||||||
|
property: prop,
|
||||||
|
field: "value",
|
||||||
|
string: "document.title + foo2 + $('p')",
|
||||||
|
webconsole: gWebConsole,
|
||||||
|
callback: onFooObjFetchAfterUpdate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFooObjFetchAfterUpdate(aEvent, aVar)
|
||||||
|
{
|
||||||
|
info("onFooObjFetchAfterUpdate");
|
||||||
|
let para = content.document.querySelector("p");
|
||||||
|
let expectedValue = content.document.title + "foo2SecondCall" + para;
|
||||||
|
|
||||||
|
findVariableViewProperties(aVar, [
|
||||||
|
{ name: "testProp2", value: expectedValue },
|
||||||
|
], { webconsole: gWebConsole }).then(onUpdatedTestPropFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onUpdatedTestPropFound(aResults)
|
||||||
|
{
|
||||||
|
let prop = aResults[0].matchedProp;
|
||||||
|
ok(prop, "matched the updated |testProp2| property value");
|
||||||
|
|
||||||
|
// Check that testProp2 was updated.
|
||||||
|
executeSoon(() => gJSTerm.execute("fooObj.testProp2", onExecuteFooObjTestProp2));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExecuteFooObjTestProp2()
|
||||||
|
{
|
||||||
|
let para = content.document.querySelector("p");
|
||||||
|
let expected = content.document.title + "foo2SecondCall" + para;
|
||||||
|
|
||||||
|
isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
|
||||||
|
"fooObj.testProp2 is correct");
|
||||||
|
|
||||||
|
gWebConsole = gJSTerm = gDebuggerWin = gThread = gDebuggerController =
|
||||||
|
gStackframes = gVariablesView = null;
|
||||||
|
executeSoon(finishTest);
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test that makes sure web console eval happens in the user-selected stackframe
|
||||||
|
// from the js debugger.
|
||||||
|
|
||||||
|
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-eval-in-stackframe.html";
|
||||||
|
|
||||||
|
let gWebConsole, gJSTerm, gDebuggerWin, gThread, gDebuggerController, gStackframes;
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
addTab(TEST_URI);
|
||||||
|
browser.addEventListener("load", function onLoad() {
|
||||||
|
browser.removeEventListener("load", onLoad, true);
|
||||||
|
openConsole(null, consoleOpened);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function consoleOpened(hud)
|
||||||
|
{
|
||||||
|
gWebConsole = hud;
|
||||||
|
gJSTerm = hud.jsterm;
|
||||||
|
gJSTerm.execute("foo", onExecuteFoo);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExecuteFoo()
|
||||||
|
{
|
||||||
|
isnot(gWebConsole.outputNode.textContent.indexOf("globalFooBug783499"), -1,
|
||||||
|
"|foo| value is correct");
|
||||||
|
|
||||||
|
gJSTerm.clearOutput();
|
||||||
|
|
||||||
|
// Test for Bug 690529 - Web Console and Scratchpad should evaluate
|
||||||
|
// expressions in the scope of the content window, not in a sandbox.
|
||||||
|
executeSoon(() => gJSTerm.execute("foo2 = 'newFoo'; window.foo2", onNewFoo2));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onNewFoo2()
|
||||||
|
{
|
||||||
|
is(gWebConsole.outputNode.textContent.indexOf("undefined"), -1,
|
||||||
|
"|undefined| is not displayed after adding |foo2|");
|
||||||
|
|
||||||
|
let msg = gWebConsole.outputNode.querySelector(".webconsole-msg-output");
|
||||||
|
ok(msg, "output result found");
|
||||||
|
|
||||||
|
isnot(msg.textContent.indexOf("newFoo"), -1,
|
||||||
|
"'newFoo' is displayed after adding |foo2|");
|
||||||
|
|
||||||
|
gJSTerm.clearOutput();
|
||||||
|
|
||||||
|
info("openDebugger");
|
||||||
|
executeSoon(() => openDebugger().then(debuggerOpened));
|
||||||
|
}
|
||||||
|
|
||||||
|
function debuggerOpened(aResult)
|
||||||
|
{
|
||||||
|
gDebuggerWin = aResult.panelWin;
|
||||||
|
gDebuggerController = gDebuggerWin.DebuggerController;
|
||||||
|
gThread = gDebuggerController.activeThread;
|
||||||
|
gStackframes = gDebuggerController.StackFrames;
|
||||||
|
|
||||||
|
info("openConsole");
|
||||||
|
executeSoon(() =>
|
||||||
|
openConsole(null, () =>
|
||||||
|
gJSTerm.execute("foo + foo2", onExecuteFooAndFoo2)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExecuteFooAndFoo2()
|
||||||
|
{
|
||||||
|
let expected = "globalFooBug783499newFoo";
|
||||||
|
isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
|
||||||
|
"|foo + foo2| is displayed after starting the debugger");
|
||||||
|
|
||||||
|
executeSoon(() => {
|
||||||
|
gJSTerm.clearOutput();
|
||||||
|
|
||||||
|
info("openDebugger");
|
||||||
|
openDebugger().then(() => {
|
||||||
|
gThread.addOneTimeListener("framesadded", onFramesAdded);
|
||||||
|
|
||||||
|
info("firstCall()");
|
||||||
|
content.wrappedJSObject.firstCall();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFramesAdded()
|
||||||
|
{
|
||||||
|
info("onFramesAdded, openConsole() now");
|
||||||
|
executeSoon(() =>
|
||||||
|
openConsole(null, () =>
|
||||||
|
gJSTerm.execute("foo + foo2", onExecuteFooAndFoo2InSecondCall)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExecuteFooAndFoo2InSecondCall()
|
||||||
|
{
|
||||||
|
let expected = "globalFooBug783499foo2SecondCall";
|
||||||
|
isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
|
||||||
|
"|foo + foo2| from |secondCall()|");
|
||||||
|
|
||||||
|
executeSoon(() => {
|
||||||
|
gJSTerm.clearOutput();
|
||||||
|
|
||||||
|
info("openDebugger and selectFrame(1)");
|
||||||
|
|
||||||
|
openDebugger().then(() => {
|
||||||
|
gStackframes.selectFrame(1);
|
||||||
|
|
||||||
|
info("openConsole");
|
||||||
|
executeSoon(() =>
|
||||||
|
openConsole(null, () =>
|
||||||
|
gJSTerm.execute("foo + foo2 + foo3", onExecuteFoo23InFirstCall)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExecuteFoo23InFirstCall()
|
||||||
|
{
|
||||||
|
let expected = "fooFirstCallnewFoofoo3FirstCall";
|
||||||
|
isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
|
||||||
|
"|foo + foo2 + foo3| from |firstCall()|");
|
||||||
|
|
||||||
|
executeSoon(() =>
|
||||||
|
gJSTerm.execute("foo = 'abba'; foo3 = 'bug783499'; foo + foo3",
|
||||||
|
onExecuteFooAndFoo3ChangesInFirstCall));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExecuteFooAndFoo3ChangesInFirstCall()
|
||||||
|
{
|
||||||
|
let expected = "abbabug783499";
|
||||||
|
isnot(gWebConsole.outputNode.textContent.indexOf(expected), -1,
|
||||||
|
"|foo + foo3| updated in |firstCall()|");
|
||||||
|
|
||||||
|
is(content.wrappedJSObject.foo, "globalFooBug783499", "|foo| in content window");
|
||||||
|
is(content.wrappedJSObject.foo2, "newFoo", "|foo2| in content window");
|
||||||
|
ok(!content.wrappedJSObject.foo3, "|foo3| was not added to the content window");
|
||||||
|
|
||||||
|
gWebConsole = gJSTerm = gDebuggerWin = gThread = gDebuggerController =
|
||||||
|
gStackframes = null;
|
||||||
|
executeSoon(finishTest);
|
||||||
|
}
|
|
@ -21,13 +21,14 @@ function performTest(hud)
|
||||||
{
|
{
|
||||||
hud.jsterm.clearOutput(true);
|
hud.jsterm.clearOutput(true);
|
||||||
|
|
||||||
content.console.log("fooBug773466a");
|
hud.jsterm.execute("console.log('fooBug773466a')");
|
||||||
content.console.dir(function funBug773466(){});
|
hud.jsterm.execute("myObj = Object.create(null)");
|
||||||
|
hud.jsterm.execute("console.dir(myObj)");
|
||||||
waitForSuccess({
|
waitForSuccess({
|
||||||
name: "eval results are shown",
|
name: "eval results are shown",
|
||||||
validatorFn: function()
|
validatorFn: function()
|
||||||
{
|
{
|
||||||
return hud.outputNode.textContent.indexOf("funBug773466") > -1;
|
return hud.outputNode.querySelector(".webconsole-msg-inspector");
|
||||||
},
|
},
|
||||||
successFn: function()
|
successFn: function()
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,8 +37,8 @@ function performTest(hud)
|
||||||
|
|
||||||
let msg = hud.outputNode.querySelector(".webconsole-msg-output");
|
let msg = hud.outputNode.querySelector(".webconsole-msg-output");
|
||||||
ok(msg, "eval output node found");
|
ok(msg, "eval output node found");
|
||||||
isnot(msg.textContent.indexOf("HTMLDivElement"), -1,
|
is(msg.textContent.indexOf("HTMLDivElement"), -1,
|
||||||
"HTMLDivElement string found");
|
"HTMLDivElement string not displayed");
|
||||||
EventUtils.synthesizeMouseAtCenter(msg, {type: "mousemove"});
|
EventUtils.synthesizeMouseAtCenter(msg, {type: "mousemove"});
|
||||||
ok(!gBrowser._bug772506, "no content variable");
|
ok(!gBrowser._bug772506, "no content variable");
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ function tabLoad2(aEvent) {
|
||||||
function networkPanelShown(aEvent) {
|
function networkPanelShown(aEvent) {
|
||||||
document.removeEventListener(aEvent.type, networkPanelShown, false);
|
document.removeEventListener(aEvent.type, networkPanelShown, false);
|
||||||
|
|
||||||
|
info("networkPanelShown");
|
||||||
|
|
||||||
document.addEventListener("popupshown", networkPanelShowFailure, false);
|
document.addEventListener("popupshown", networkPanelShowFailure, false);
|
||||||
|
|
||||||
// The network panel should not open for the second time.
|
// The network panel should not open for the second time.
|
||||||
|
@ -70,6 +72,8 @@ function networkPanelShowFailure(aEvent) {
|
||||||
function networkPanelHidden(aEvent) {
|
function networkPanelHidden(aEvent) {
|
||||||
this.removeEventListener(aEvent.type, networkPanelHidden, false);
|
this.removeEventListener(aEvent.type, networkPanelHidden, false);
|
||||||
|
|
||||||
|
info("networkPanelHidden");
|
||||||
|
|
||||||
// The network panel should not show because this is a mouse event that starts
|
// The network panel should not show because this is a mouse event that starts
|
||||||
// in a position and ends in another.
|
// in a position and ends in another.
|
||||||
EventUtils.sendMouseEvent({type: "mousedown", clientX: 3, clientY: 4},
|
EventUtils.sendMouseEvent({type: "mousedown", clientX: 3, clientY: 4},
|
||||||
|
@ -94,73 +98,25 @@ function networkPanelHidden(aEvent) {
|
||||||
|
|
||||||
// Done with the network output. Now test the jsterm output and the property
|
// Done with the network output. Now test the jsterm output and the property
|
||||||
// panel.
|
// panel.
|
||||||
HUD.jsterm.setInputValue("document");
|
HUD.jsterm.execute("document", () => {
|
||||||
HUD.jsterm.execute();
|
info("jsterm execute 'document' callback");
|
||||||
|
|
||||||
waitForSuccess({
|
HUD.jsterm.once("variablesview-open", onVariablesViewOpen);
|
||||||
name: "jsterm output message",
|
let outputItem = outputNode
|
||||||
validatorFn: function()
|
.querySelector(".webconsole-msg-output .hud-clickable");
|
||||||
{
|
ok(outputItem, "jsterm output message found");
|
||||||
return outputNode.querySelector(".webconsole-msg-output .hud-clickable");
|
|
||||||
},
|
|
||||||
successFn: function()
|
|
||||||
{
|
|
||||||
document.addEventListener("popupshown", propertyPanelShown, false);
|
|
||||||
|
|
||||||
// Send the mousedown and click events such that the property panel opens.
|
// Send the mousedown and click events such that the property panel opens.
|
||||||
EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
|
EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
|
||||||
EventUtils.sendMouseEvent({type: "click"}, outputItem);
|
EventUtils.sendMouseEvent({type: "click"}, outputItem);
|
||||||
},
|
|
||||||
failureFn: finishTest,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function propertyPanelShown(aEvent) {
|
function onVariablesViewOpen() {
|
||||||
document.removeEventListener(aEvent.type, propertyPanelShown, false);
|
info("onVariablesViewOpen");
|
||||||
|
|
||||||
document.addEventListener("popupshown", propertyPanelShowFailure, false);
|
|
||||||
|
|
||||||
// The property panel should not open for the second time.
|
|
||||||
EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
|
|
||||||
EventUtils.sendMouseEvent({type: "click"}, outputItem);
|
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
aEvent.target.addEventListener("popuphidden", propertyPanelHidden, false);
|
|
||||||
aEvent.target.hidePopup();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function propertyPanelShowFailure(aEvent) {
|
|
||||||
document.removeEventListener(aEvent.type, propertyPanelShowFailure, false);
|
|
||||||
|
|
||||||
ok(false, "the property panel should not show");
|
|
||||||
}
|
|
||||||
|
|
||||||
function propertyPanelHidden(aEvent) {
|
|
||||||
this.removeEventListener(aEvent.type, propertyPanelHidden, false);
|
|
||||||
|
|
||||||
// The property panel should not show because this is a mouse event that
|
|
||||||
// starts in a position and ends in another.
|
|
||||||
EventUtils.sendMouseEvent({type: "mousedown", clientX: 3, clientY: 4},
|
|
||||||
outputItem);
|
|
||||||
EventUtils.sendMouseEvent({type: "click", clientX: 5, clientY: 6},
|
|
||||||
outputItem);
|
|
||||||
|
|
||||||
// The property panel should not show because this is a middle-click.
|
|
||||||
EventUtils.sendMouseEvent({type: "mousedown", button: 1},
|
|
||||||
outputItem);
|
|
||||||
EventUtils.sendMouseEvent({type: "click", button: 1},
|
|
||||||
outputItem);
|
|
||||||
|
|
||||||
// The property panel should not show because this is a right-click.
|
|
||||||
EventUtils.sendMouseEvent({type: "mousedown", button: 2},
|
|
||||||
outputItem);
|
|
||||||
EventUtils.sendMouseEvent({type: "click", button: 2},
|
|
||||||
outputItem);
|
|
||||||
|
|
||||||
executeSoon(function() {
|
|
||||||
document.removeEventListener("popupshown", propertyPanelShowFailure, false);
|
|
||||||
HUD = outputItem = null;
|
HUD = outputItem = null;
|
||||||
executeSoon(finishTest);
|
executeSoon(finishTest);
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,6 +19,8 @@ let openTabs = [];
|
||||||
let loadedTabCount = 0;
|
let loadedTabCount = 0;
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
requestLongerTimeout(2);
|
||||||
|
|
||||||
// Add two tabs in the main window.
|
// Add two tabs in the main window.
|
||||||
addTabs(win1);
|
addTabs(win1);
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ function openConsoles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForSuccess({
|
waitForSuccess({
|
||||||
timeout: 10000,
|
timeout: 15000,
|
||||||
name: "4 web consoles opened",
|
name: "4 web consoles opened",
|
||||||
validatorFn: function()
|
validatorFn: function()
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,11 +24,11 @@ let initialString = longString.substring(0,
|
||||||
|
|
||||||
let inputValues = [
|
let inputValues = [
|
||||||
// [showsPropertyPanel?, input value, expected output format,
|
// [showsPropertyPanel?, input value, expected output format,
|
||||||
// print() output, console output, optional console API test]
|
// print() output, console API output, optional console API test]
|
||||||
|
|
||||||
// 0
|
// 0
|
||||||
[false, "'hello \\nfrom \\rthe \\\"string world!'",
|
[false, "'hello \\nfrom \\rthe \\\"string world!'",
|
||||||
'"hello \\nfrom \\rthe \\"string world!"',
|
'"hello \nfrom \rthe "string world!"',
|
||||||
"hello \nfrom \rthe \"string world!"],
|
"hello \nfrom \rthe \"string world!"],
|
||||||
|
|
||||||
// 1
|
// 1
|
||||||
|
@ -52,7 +52,7 @@ let inputValues = [
|
||||||
[false, "'42'", '"42"', "42"],
|
[false, "'42'", '"42"', "42"],
|
||||||
|
|
||||||
// 7
|
// 7
|
||||||
[false, "/foobar/", "/foobar/"],
|
[true, "/foobar/", "[object RegExp]", '"/foobar/"', "[object RegExp]"],
|
||||||
|
|
||||||
// 8
|
// 8
|
||||||
[false, "null", "null"],
|
[false, "null", "null"],
|
||||||
|
@ -64,36 +64,30 @@ let inputValues = [
|
||||||
[false, "true", "true"],
|
[false, "true", "true"],
|
||||||
|
|
||||||
// 11
|
// 11
|
||||||
[false, "document.getElementById", "function getElementById() {\n [native code]\n}",
|
[true, "document.getElementById", "[object Function]",
|
||||||
"function getElementById() {\n [native code]\n}",
|
"function getElementById() {\n [native code]\n}",
|
||||||
"function getElementById() {\n [native code]\n}",
|
"[object Function]"],
|
||||||
"document.wrappedJSObject.getElementById"],
|
|
||||||
|
|
||||||
// 12
|
// 12
|
||||||
[false, "(function() { return 42; })", "function () { return 42; }",
|
[true, "(function() { return 42; })", "[object Function]",
|
||||||
"function () { return 42; }",
|
"function () { return 42; }", "[object Function]"],
|
||||||
"(function () { return 42; })"],
|
|
||||||
|
|
||||||
// 13
|
// 13
|
||||||
[false, "new Date(" + dateNow + ")", (new Date(dateNow)).toString()],
|
[true, "new Date(" + dateNow + ")", "[object Date]", (new Date(dateNow)).toString(), "[object Date]"],
|
||||||
|
|
||||||
// 14
|
// 14
|
||||||
[true, "document.body", "[object HTMLBodyElement", "[object HTMLBodyElement",
|
[true, "document.body", "[object HTMLBodyElement]"],
|
||||||
"[object HTMLBodyElement",
|
|
||||||
"document.wrappedJSObject.body"],
|
|
||||||
|
|
||||||
// 15
|
// 15
|
||||||
[true, "window.location", TEST_URI],
|
[true, "window.location", "[object Location]", TEST_URI, "[object Location]"],
|
||||||
|
|
||||||
// 16
|
// 16
|
||||||
[true, "[1,2,3,'a','b','c','4','5']", '[1, 2, 3, "a", "b", "c", "4", "5"]',
|
[true, "[1,2,3,'a','b','c','4','5']", '[object Array]',
|
||||||
'1,2,3,a,b,c,4,5',
|
'1,2,3,a,b,c,4,5',
|
||||||
'[1, 2, 3, "a", "b", "c", "4", "5"]'],
|
"[object Array]"],
|
||||||
|
|
||||||
// 17
|
// 17
|
||||||
[true, "({a:'b', c:'d', e:1, f:'2'})", '({a:"b", c:"d", e:1, f:"2"})',
|
[true, "({a:'b', c:'d', e:1, f:'2'})", "[object Object]"],
|
||||||
"[object Object",
|
|
||||||
'({a:"b", c:"d", e:1, f:"2"})'],
|
|
||||||
|
|
||||||
// 18
|
// 18
|
||||||
[false, "'" + longString + "'",
|
[false, "'" + longString + "'",
|
||||||
|
@ -154,10 +148,7 @@ function testGen() {
|
||||||
|
|
||||||
// Test the console.log() output.
|
// Test the console.log() output.
|
||||||
|
|
||||||
// Ugly but it does the job.
|
HUD.jsterm.execute("console.log(" + consoleTest + ")");
|
||||||
with (content) {
|
|
||||||
eval("content.console.log(" + consoleTest + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
waitForSuccess({
|
waitForSuccess({
|
||||||
name: "console.log message for test #" + cpos,
|
name: "console.log message for test #" + cpos,
|
||||||
|
@ -233,28 +224,28 @@ function testGen() {
|
||||||
// Test click on output.
|
// Test click on output.
|
||||||
let eventHandlerID = eventHandlers.length + 1;
|
let eventHandlerID = eventHandlers.length + 1;
|
||||||
|
|
||||||
let propertyPanelShown = function(aEvent) {
|
let propertyPanelShown = function(aEvent, aView, aOptions) {
|
||||||
let label = aEvent.target.getAttribute("label");
|
if (aOptions.label.indexOf(expectedOutput) == -1) {
|
||||||
if (!label || label.indexOf(inputValue) == -1) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.removeEventListener(aEvent.type, propertyPanelShown, false);
|
HUD.jsterm.off("variablesview-open", propertyPanelShown);
|
||||||
|
|
||||||
eventHandlers[eventHandlerID] = null;
|
eventHandlers[eventHandlerID] = null;
|
||||||
|
|
||||||
ok(showsPropertyPanel,
|
ok(showsPropertyPanel,
|
||||||
"the property panel shown for inputValues[" + cpos + "]");
|
"the property panel shown for inputValues[" + cpos + "]");
|
||||||
|
|
||||||
aEvent.target.hidePopup();
|
HUD.jsterm._splitter.state = "collapsed";
|
||||||
|
|
||||||
popupShown[cpos] = true;
|
popupShown[cpos] = true;
|
||||||
|
|
||||||
if (showsPropertyPanel) {
|
if (showsPropertyPanel) {
|
||||||
subtestNext();
|
executeSoon(subtestNext);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("popupshown", propertyPanelShown, false);
|
HUD.jsterm.on("variablesview-open", propertyPanelShown);
|
||||||
|
|
||||||
eventHandlers.push(propertyPanelShown);
|
eventHandlers.push(propertyPanelShown);
|
||||||
|
|
||||||
|
@ -281,7 +272,7 @@ function testEnd() {
|
||||||
|
|
||||||
for (let i = 0; i < eventHandlers.length; i++) {
|
for (let i = 0; i < eventHandlers.length; i++) {
|
||||||
if (eventHandlers[i]) {
|
if (eventHandlers[i]) {
|
||||||
document.removeEventListener("popupshown", eventHandlers[i], false);
|
HUD.jsterm.off("variablesview-open", eventHandlers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +287,7 @@ function testEnd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
requestLongerTimeout(2);
|
||||||
addTab(TEST_URI);
|
addTab(TEST_URI);
|
||||||
browser.addEventListener("load", tabLoad, true);
|
browser.addEventListener("load", tabLoad, true);
|
||||||
}
|
}
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче