Merge from mozilla-central.

This commit is contained in:
David Anderson 2012-09-10 12:16:38 -07:00
commit 09854d2b71
391 changed files with 6992 additions and 3628 deletions

View File

@ -15,6 +15,10 @@ ifeq ($(OS_ARCH),WINNT)
DIRS += $(DEPTH)/xulrunner/tools/redit
endif
ifneq ($(GAIADIR),)
DIRS += gaia
endif
DIRS += app
include $(topsrcdir)/config/rules.mk

View File

@ -16,7 +16,11 @@ DEFINES += -DENABLE_MARIONETTE=1
endif
ifndef LIBXUL_SDK
ifneq ($(GAIADIR),)
PROGRAM=$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
else
PROGRAM=$(MOZ_APP_NAME)$(BIN_SUFFIX)
endif
CPPSRCS = nsBrowserApp.cpp

View File

@ -4,75 +4,8 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>html</string>
<string>htm</string>
<string>shtml</string>
<string>xht</string>
<string>xhtml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>HTML Document</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>HTML</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>text</string>
<string>txt</string>
<string>js</string>
<string>log</string>
<string>css</string>
<string>xul</string>
<string>rdf</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>Text Document</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>TEXT</string>
<string>utxt</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>jpeg</string>
<string>jpg</string>
<string>png</string>
<string>gif</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>fileBookmark.icns</string>
<key>CFBundleTypeName</key>
<string>document.icns</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>GIFf</string>
<string>JPEG</string>
<string>PNGf</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>%MOZ_APP_NAME%</string>
<string>b2g</string>
<key>CFBundleGetInfoString</key>
<string>%APP_NAME% %APP_VERSION%</string>
<key>CFBundleIconFile</key>
@ -89,45 +22,6 @@
<string>%APP_VERSION%</string>
<key>CFBundleSignature</key>
<string>MOZB</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLIconFile</key>
<string>document.icns</string>
<key>CFBundleURLName</key>
<string>http URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
</array>
</dict>
<dict>
<key>CFBundleURLIconFile</key>
<string>document.icns</string>
<key>CFBundleURLName</key>
<string>https URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>https</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>ftp URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ftp</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>file URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>file</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>%APP_VERSION%</string>
<key>NSAppleScriptEnabled</key>

View File

@ -352,8 +352,7 @@ var shell = {
this.sendChromeEvent({
type: 'open-app',
url: msg.uri,
origin: origin,
manifest: msg.manifest,
manifestURL: msg.manifest,
isActivity: (msg.type == 'activity'),
target: msg.target
});
@ -601,7 +600,7 @@ var WebappsHelper = {
shell.sendChromeEvent({
"type": "webapps-launch",
"url": manifest.fullLaunchPath(json.startPoint),
"origin": json.origin
"manifestURL": json.manifestURL
});
});
break;

42
b2g/gaia/Makefile.in Normal file
View File

@ -0,0 +1,42 @@
# 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/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
GAIA_PATH := gaia/profile
# We don't have a wrapper script on Windows yet
ifneq ($(OS_ARCH),WINNT)
PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
CSRCS = run-b2g.c
DEFINES += \
-DB2G_NAME=\"$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)\" \
-DGAIA_PATH=\"$(GAIA_PATH)\" \
$(NULL)
# This is needed to avoid making run-b2g depend on mozglue
WRAP_LDFLAGS :=
endif
GENERATED_DIRS += $(DIST)/bin/$(GAIA_PATH)
include $(topsrcdir)/config/rules.mk
libs::
# Below here is how Gaia gets built
# The Gaia build system freaks out when N > 1 for -jN
$(MAKE) -j1 -C $(GAIADIR) clean
$(MAKE) -j1 -C $(GAIADIR) profile GAIA_DOMAIN=desktop-builds.$(MOZ_APP_NAME).mozilla.org
(cd $(GAIADIR)/profile && tar $(TAR_CREATE_FLAGS) - .) | (cd $(abspath $(DIST))/bin/$(GAIA_PATH) && tar -xf -)

47
b2g/gaia/run-b2g.c Normal file
View File

@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
#ifndef B2G_NAME
#define B2G_NAME "b2g-bin"
#endif
#ifndef GAIA_PATH
#define GAIA_PATH "gaia/profile"
#endif
#define NOMEM "Could not allocate enough memory"
void error(char* msg){
fprintf(stderr, "ERROR: %s\n", msg);
}
int main(int argc, char* argv[], char* envp[]){
char* cwd = NULL;
char* full_path = NULL;
char* full_profile_path = NULL;
printf("Starting %s\n", B2G_NAME);
cwd = realpath(dirname(argv[0]), NULL);
full_path = (char*) malloc(strlen(cwd) + strlen(B2G_NAME) + 2);
if (!full_path) {
error(NOMEM);
return -2;
}
full_profile_path = (char*) malloc(strlen(cwd) + strlen(GAIA_PATH) + 2);
if (!full_profile_path) {
error(NOMEM);
return -2;
}
sprintf(full_path, "%s/%s", cwd, B2G_NAME);
sprintf(full_profile_path, "%s/%s", cwd, GAIA_PATH);
free(cwd);
printf("Running: %s -profile %s\n", full_path, full_profile_path);
fflush(stdout);
fflush(stderr);
execle(full_path, full_path, "-profile", full_profile_path, NULL, envp);
error("unable to start");
perror(argv[0]);
free(full_path);
free(full_profile_path);
return -1;
}

View File

@ -701,3 +701,9 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
#ifdef XP_MACOSX
@BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
#endif
#ifdef PACKAGE_GAIA
[gaia]
@BINPATH@/gaia/*
@BINPATH@/b2g-bin@BIN_SUFFIX@
#endif

View File

@ -89,7 +89,7 @@
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focus();" disabled="true"/>
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/>
<command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
<command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();"/>
<command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true" hidden="true"/>

View File

@ -220,6 +220,7 @@ let SocialFlyout = {
// create and initialize the panel for this window
let iframe = document.createElement("iframe");
iframe.setAttribute("type", "content");
iframe.setAttribute("class", "social-panel-frame");
iframe.setAttribute("flex", "1");
iframe.setAttribute("origin", Social.provider.origin);
panel.appendChild(iframe);
@ -536,6 +537,7 @@ var SocialToolbar = {
if (!notificationFrame) {
notificationFrame = document.createElement("iframe");
notificationFrame.setAttribute("type", "content");
notificationFrame.setAttribute("class", "social-panel-frame");
notificationFrame.setAttribute("id", notificationFrameId);
notificationFrame.setAttribute("mozbrowser", "true");
notificationFrames.appendChild(notificationFrame);

View File

@ -658,7 +658,7 @@ var allTabs = {
} catch (e) {}
tabstring = tab.label + " " + tab.label.toLocaleLowerCase() + " " + tabstring;
for (let i = 0; i < filter.length; i++)
matches += tabstring.indexOf(filter[i]) > -1;
matches += tabstring.contains(filter[i]);
}
if (matches < filter.length || tab.hidden) {
preview.hidden = true;

View File

@ -1049,7 +1049,7 @@ var gBrowserInit = {
// set default character set if provided
if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
if (window.arguments[1].indexOf("charset=") != -1) {
if (window.arguments[1].startsWith("charset=")) {
var arrayArgComponents = window.arguments[1].split("=");
if (arrayArgComponents) {
//we should "inherit" the charset menu setting in a new window
@ -2758,7 +2758,7 @@ function getMeOutOfHere() {
url = prefs.getComplexValue("browser.startup.homepage",
Ci.nsIPrefLocalizedString).data;
// If url is a pipe-delimited set of pages, just take the first one.
if (url.indexOf("|") != -1)
if (url.contains("|"))
url = url.split("|")[0];
} catch(e) {
Components.utils.reportError("Couldn't get homepage pref: " + e);
@ -3467,7 +3467,7 @@ function FillHistoryMenu(aParent) {
function addToUrlbarHistory(aUrlToAdd) {
if (aUrlToAdd &&
aUrlToAdd.indexOf(" ") == -1 &&
!aUrlToAdd.contains(" ") &&
!/[\x00-\x1F]/.test(aUrlToAdd))
PlacesUIUtils.markPageAsTyped(aUrlToAdd);
}

View File

@ -268,10 +268,12 @@
</hbox>
</panel>
<panel id="social-notification-panel" type="arrow" hidden="true" noautofocus="true">
<panel id="social-notification-panel" class="social-panel"
type="arrow" hidden="true" noautofocus="true">
<box id="social-notification-box" flex="1"></box>
</panel>
<panel id="social-flyout-panel"
class="social-panel"
onpopupshown="SocialFlyout.onShown()"
onpopuphidden="SocialFlyout.onHidden()"
side="right"

View File

@ -64,7 +64,7 @@
<command id="cmd_pluginsToggle" oncommand="onRadioClick('plugins');"/>
</commandset>
<keyset>
<keyset id="pageInfoKeySet">
<key key="&closeWindow.key;" modifiers="accel" command="cmd_close"/>
<key keycode="VK_ESCAPE" command="cmd_close"/>
#ifdef XP_MACOSX
@ -102,50 +102,50 @@
<!-- General page information -->
<vbox id="generalPanel">
<textbox class="header" readonly="true" id="titletext"/>
<grid>
<grid id="generalGrid">
<columns>
<column/>
<column class="gridSeparator"/>
<column flex="1"/>
</columns>
<rows>
<row>
<rows id="generalRows">
<row id="generalURLRow">
<label control="urltext" value="&generalURL;"/>
<separator/>
<textbox readonly="true" id="urltext"/>
</row>
<row>
<row id="generalSeparatorRow1">
<separator class="thin"/>
</row>
<row>
<row id="generalTypeRow">
<label control="typetext" value="&generalType;"/>
<separator/>
<textbox readonly="true" id="typetext"/>
</row>
<row>
<row id="generalModeRow">
<label control="modetext" value="&generalMode;"/>
<separator/>
<textbox readonly="true" crop="end" id="modetext"/>
</row>
<row>
<row id="generalEncodingRow">
<label control="encodingtext" value="&generalEncoding;"/>
<separator/>
<textbox readonly="true" id="encodingtext"/>
</row>
<row>
<row id="generalSizeRow">
<label control="sizetext" value="&generalSize;"/>
<separator/>
<textbox readonly="true" id="sizetext"/>
</row>
<row>
<row id="generalReferrerRow">
<label control="refertext" value="&generalReferrer;"/>
<separator/>
<textbox readonly="true" id="refertext"/>
</row>
<row>
<row id="generalSeparatorRow2">
<separator class="thin"/>
</row>
<row>
<row id="generalModifiedRow">
<label control="modifiedtext" value="&generalModified;"/>
<separator/>
<textbox readonly="true" id="modifiedtext"/>
@ -165,14 +165,14 @@
persist="width" flex="4"
onclick="gMetaView.onPageMediaSort('meta-content');"/>
</treecols>
<treechildren flex="1"/>
<treechildren id="metatreechildren" flex="1"/>
</tree>
</groupbox>
<groupbox id="securityBox">
<caption id="securityBoxCaption" label="&securityHeader;"/>
<description id="general-security-identity" class="header"/>
<description id="general-security-privacy" class="header"/>
<hbox align="right">
<hbox id="securityDetailsButtonBox" align="right">
<button id="security-view-details" label="&generalSecurityDetails;"
accesskey="&generalSecurityDetails.accesskey;"
oncommand="onClickMore();"/>
@ -205,7 +205,7 @@
width="1" id="image-count" label="&mediaCount;"
onclick="gImageView.onPageMediaSort('image-count');"/>
</treecols>
<treechildren flex="1"/>
<treechildren id="imagetreechildren" flex="1"/>
</tree>
<splitter orient="vertical" id="mediaSplitter"/>
<vbox flex="1" id="mediaPreviewBox" collapsed="true">
@ -215,51 +215,51 @@
<column class="gridSeparator"/>
<column flex="1"/>
</columns>
<rows>
<row>
<rows id="mediaRows">
<row id="mediaLocationRow">
<label control="imageurltext" value="&mediaLocation;"/>
<separator/>
<textbox readonly="true" id="imageurltext"/>
</row>
<row>
<row id="mediaTypeRow">
<label control="imagetypetext" value="&generalType;"/>
<separator/>
<textbox readonly="true" id="imagetypetext"/>
</row>
<row>
<row id="mediaSizeRow">
<label control="imagesizetext" value="&generalSize;"/>
<separator/>
<textbox readonly="true" id="imagesizetext"/>
</row>
<row>
<row id="mediaDimensionRow">
<label control="imagedimensiontext" value="&mediaDimension;"/>
<separator/>
<textbox readonly="true" id="imagedimensiontext"/>
</row>
<row>
<row id="mediaTextRow">
<label control="imagetext" value="&mediaText;"/>
<separator/>
<textbox readonly="true" id="imagetext"/>
</row>
<row>
<row id="mediaLongdescRow">
<label control="imagelongdesctext" value="&mediaLongdesc;"/>
<separator/>
<textbox readonly="true" id="imagelongdesctext"/>
</row>
</rows>
</grid>
<hbox align="end">
<vbox>
<hbox id="imageSaveBox" align="end">
<vbox id="blockImageBox">
<checkbox id="blockImage" hidden="true" oncommand="onBlockImage()"
accesskey="&mediaBlockImage.accesskey;"/>
<label control="thepreviewimage" value="&mediaPreview;" class="header"/>
</vbox>
<spacer flex="1"/>
<spacer id="imageSaveBoxSpacer" flex="1"/>
<button label="&mediaSaveAs;" accesskey="&mediaSaveAs.accesskey;"
icon="save" id="imagesaveasbutton"
oncommand="saveMedia();"/>
</hbox>
<vbox class="inset iframe" flex="1" pack="center">
<vbox id="imagecontainerbox" class="inset iframe" flex="1" pack="center">
<hbox id="theimagecontainer" pack="center">
<image id="thepreviewimage"/>
</hbox>
@ -269,9 +269,10 @@
</vbox>
</vbox>
<hbox id="mediaSaveBox" collapsed="true">
<spacer flex="1"/>
<spacer id="mediaSaveBoxSpacer" flex="1"/>
<button label="&mediaSaveAs;" accesskey="&mediaSaveAs2.accesskey;"
icon="save" oncommand="saveMedia();"/>
icon="save" id="mediasaveasbutton"
oncommand="saveMedia();"/>
</hbox>
</vbox>
@ -282,17 +283,17 @@
<!-- Permissions -->
<vbox id="permPanel">
<hbox>
<hbox id="permHostBox">
<label value="&permissionsFor;" control="hostText" />
<textbox id="hostText" class="header" readonly="true"
crop="end" flex="1"/>
</hbox>
<vbox id="permList" flex="1">
<vbox class="permission">
<vbox class="permission" id="permImageRow">
<label class="permissionLabel" id="permImageLabel"
value="&permImage;" control="imageRadioGroup"/>
<hbox role="group" aria-labelledby="permImageLabel">
<hbox id="permImageBox" role="group" aria-labelledby="permImageLabel">
<checkbox id="imageDef" command="cmd_imageDef" label="&permUseDefault;"/>
<spacer flex="1"/>
<radiogroup id="imageRadioGroup" orient="horizontal">
@ -301,10 +302,10 @@
</radiogroup>
</hbox>
</vbox>
<vbox class="permission">
<vbox class="permission" id="permPopupRow">
<label class="permissionLabel" id="permPopupLabel"
value="&permPopup;" control="popupRadioGroup"/>
<hbox role="group" aria-labelledby="permPopupLabel">
<hbox id="permPopupBox" role="group" aria-labelledby="permPopupLabel">
<checkbox id="popupDef" command="cmd_popupDef" label="&permUseDefault;"/>
<spacer flex="1"/>
<radiogroup id="popupRadioGroup" orient="horizontal">
@ -313,10 +314,10 @@
</radiogroup>
</hbox>
</vbox>
<vbox class="permission">
<vbox class="permission" id="permCookieRow">
<label class="permissionLabel" id="permCookieLabel"
value="&permCookie;" control="cookieRadioGroup"/>
<hbox role="group" aria-labelledby="permCookieLabel">
<hbox id="permCookieBox" role="group" aria-labelledby="permCookieLabel">
<checkbox id="cookieDef" command="cmd_cookieDef" label="&permUseDefault;"/>
<spacer flex="1"/>
<radiogroup id="cookieRadioGroup" orient="horizontal">
@ -326,10 +327,10 @@
</radiogroup>
</hbox>
</vbox>
<vbox class="permission">
<vbox class="permission" id="permInstallRow">
<label class="permissionLabel" id="permInstallLabel"
value="&permInstall;" control="installRadioGroup"/>
<hbox role="group" aria-labelledby="permInstallLabel">
<hbox id="permInstallBox" role="group" aria-labelledby="permInstallLabel">
<checkbox id="installDef" command="cmd_installDef" label="&permUseDefault;"/>
<spacer flex="1"/>
<radiogroup id="installRadioGroup" orient="horizontal">
@ -338,10 +339,10 @@
</radiogroup>
</hbox>
</vbox>
<vbox class="permission">
<vbox class="permission" id="permGeoRow" >
<label class="permissionLabel" id="permGeoLabel"
value="&permGeo;" control="geoRadioGroup"/>
<hbox role="group" aria-labelledby="permGeoLabel">
<hbox id="permGeoBox" role="group" aria-labelledby="permGeoLabel">
<checkbox id="geoDef" command="cmd_geoDef" label="&permAskAlways;"/>
<spacer flex="1"/>
<radiogroup id="geoRadioGroup" orient="horizontal">
@ -350,10 +351,10 @@
</radiogroup>
</hbox>
</vbox>
<vbox class="permission">
<vbox class="permission" id="permIndexedDBRow">
<label class="permissionLabel" id="permIndexedDBLabel"
value="&permIndexedDB;" control="indexedDBRadioGroup"/>
<hbox role="group" aria-labelledby="permIndexedDBLabel">
<hbox id="permIndexedDBBox" role="group" aria-labelledby="permIndexedDBLabel">
<checkbox id="indexedDBDef" command="cmd_indexedDBDef" label="&permUseDefault;"/>
<spacer flex="1"/>
<radiogroup id="indexedDBRadioGroup" orient="horizontal">
@ -363,9 +364,9 @@
<radio id="indexedDB#2" command="cmd_indexedDBToggle" label="&permBlock;"/>
</radiogroup>
</hbox>
<hbox>
<hbox id="permIndexedDBBox2">
<spacer flex="1"/>
<vbox pack="center">
<vbox id="permIndexedDBStatusBox" pack="center">
<label id="indexedDBStatus" control="indexedDBClear" hidden="true"/>
</vbox>
<button id="indexedDBClear" label="&permClearStorage;" hidden="true"
@ -375,7 +376,7 @@
<vbox class="permission" id="permPluginsRow">
<label class="permissionLabel" id="permPluginsLabel"
value="&permPlugins;" control="pluginsRadioGroup"/>
<hbox role="group" aria-labelledby="permPluginsLabel">
<hbox id="permPluginsBox" role="group" aria-labelledby="permPluginsLabel">
<checkbox id="pluginsDef" command="cmd_pluginsDef" label="&permAskAlways;"/>
<spacer flex="1"/>
<radiogroup id="pluginsRadioGroup" orient="horizontal">
@ -384,10 +385,10 @@
</radiogroup>
</hbox>
</vbox>
<vbox class="permission">
<vbox class="permission" id="permFullscreenRow">
<label class="permissionLabel" id="permFullscreenLabel"
value="&permFullscreen;" control="fullscreenRadioGroup"/>
<hbox role="group" aria-labelledby="permFullscreenLabel">
<hbox id="permFullscreenBox" role="group" aria-labelledby="permFullscreenLabel">
<checkbox id="fullscreenDef" command="cmd_fullscreenDef" label="&permUseDefault;"/>
<spacer flex="1"/>
<radiogroup id="fullscreenRadioGroup" orient="horizontal">
@ -405,13 +406,14 @@
<!-- Identity Section -->
<groupbox id="security-identity-groupbox" flex="1">
<caption id="security-identity" label="&securityView.identity.header;"/>
<grid flex="1">
<grid id="security-identity-grid" flex="1">
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row><!-- Domain -->
<rows id="security-identity-rows">
<!-- Domain -->
<row id="security-identity-domain-row">
<label id="security-identity-domain-label"
class="fieldLabel"
value="&securityView.identity.domain;"
@ -419,7 +421,8 @@
<textbox id="security-identity-domain-value"
class="fieldValue" readonly="true"/>
</row>
<row><!-- Owner -->
<!-- Owner -->
<row id="security-identity-owner-row">
<label id="security-identity-owner-label"
class="fieldLabel"
value="&securityView.identity.owner;"
@ -427,7 +430,8 @@
<textbox id="security-identity-owner-value"
class="fieldValue" readonly="true"/>
</row>
<row><!-- Verifier -->
<!-- Verifier -->
<row id="security-identity-verifier-row">
<label id="security-identity-verifier-label"
class="fieldLabel"
value="&securityView.identity.verifier;"
@ -438,7 +442,8 @@
</rows>
</grid>
<spacer flex="1"/>
<hbox pack="end"><!-- Cert button -->
<!-- Cert button -->
<hbox id="security-view-cert-box" pack="end">
<button id="security-view-cert" label="&securityView.certView;"
accesskey="&securityView.accesskey;"
oncommand="security.viewCert();"/>
@ -448,13 +453,14 @@
<!-- Privacy & History section -->
<groupbox id="security-privacy-groupbox" flex="1">
<caption id="security-privacy" label="&securityView.privacy.header;" />
<grid>
<grid id="security-privacy-grid">
<columns>
<column flex="1"/>
<column flex="1"/>
</columns>
<rows>
<row><!-- History -->
<rows id="security-privacy-rows">
<!-- History -->
<row id="security-privacy-history-row">
<label id="security-privacy-history-label"
control="security-privacy-history-value"
class="fieldLabel">&securityView.privacy.history;</label>
@ -463,11 +469,12 @@
value="&securityView.unknown;"
readonly="true"/>
</row>
<row><!-- Cookies -->
<!-- Cookies -->
<row id="security-privacy-cookies-row">
<label id="security-privacy-cookies-label"
control="security-privacy-cookies-value"
class="fieldLabel">&securityView.privacy.cookies;</label>
<hbox align="center">
<hbox id="security-privacy-cookies-box" align="center">
<textbox id="security-privacy-cookies-value"
class="fieldValue"
value="&securityView.unknown;"
@ -479,11 +486,12 @@
oncommand="security.viewCookies();"/>
</hbox>
</row>
<row><!-- Passwords -->
<!-- Passwords -->
<row id="security-privacy-passwords-row">
<label id="security-privacy-passwords-label"
control="security-privacy-passwords-value"
class="fieldLabel">&securityView.privacy.passwords;</label>
<hbox align="center">
<hbox id="security-privacy-passwords-box" align="center">
<textbox id="security-privacy-passwords-value"
class="fieldValue"
value="&securityView.unknown;"
@ -502,7 +510,7 @@
<!-- Technical Details section -->
<groupbox id="security-technical-groupbox" flex="1">
<caption id="security-technical" label="&securityView.technical.header;" />
<vbox flex="1">
<vbox id="security-technical-box" flex="1">
<label id="security-technical-shortform" class="fieldValue"/>
<description id="security-technical-longform1" class="fieldLabel"/>
<description id="security-technical-longform2" class="fieldLabel"/>

View File

@ -7,12 +7,10 @@
<binding id="chatbox">
<content orient="vertical" mousethrough="never">
<xul:hbox class="chat-titlebar" xbl:inherits="minimized">
<xul:hbox class="chat-titlebar" xbl:inherits="minimized,selected"
onclick="document.getBindingParent(this).toggle();">
<xul:image class="chat-status-icon" xbl:inherits="src=image"/>
<xul:label class="chat-title" flex="1" xbl:inherits="value=label,crop"/>
<xul:toolbarbutton class="chat-toggle-button chat-toolbarbutton"
xbl:inherits="minimized"
oncommand="document.getBindingParent(this).toggle();"/>
<xul:toolbarbutton class="chat-close-button chat-toolbarbutton"
oncommand="document.getBindingParent(this).close();"/>
</xul:hbox>
@ -132,7 +130,19 @@
</getter>
</property>
<field name="selectedChat"/>
<property name="selectedChat">
<getter><![CDATA[
return this._selectedChat;
]]></getter>
<setter><![CDATA[
if (this._selectedChat)
this._selectedChat.removeAttribute("selected");
this._selectedChat = val;
if (val) {
this._selectedChat.setAttribute("selected", "true");
}
]]></setter>
</property>
<field name="menuitemMap">new WeakMap()</field>
<field name="chatboxForURL">new Map();</field>

View File

@ -57,8 +57,8 @@ let RemoteTabViewer = {
let item = this._tabsList.getItemAtIndex(i);
let hide = false;
if (item.getAttribute("type") == "tab") {
if (item.getAttribute("url").toLowerCase().indexOf(val) == -1 &&
item.getAttribute("title").toLowerCase().indexOf(val) == -1)
if (!item.getAttribute("url").toLowerCase().contains(val) &&
!item.getAttribute("title").toLowerCase().contains(val))
hide = true;
else
clientTabs++;

View File

@ -795,7 +795,7 @@
// add the scheme and host to the title to prevent spoofing.
// XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
try {
if (docElement.getAttribute("chromehidden").indexOf("location") != -1) {
if (docElement.getAttribute("chromehidden").contains("location")) {
var uri = this.mURIFixup.createExposableURI(
aBrowser.currentURI);
if (uri.scheme == "about")
@ -3750,7 +3750,7 @@
} catch (ex) {}
// valid urls don't contain spaces ' '; if we have a space it isn't a valid url.
if (!url || url.indexOf(" ") != -1)
if (!url || url.contains(" "))
return;
let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground");

View File

@ -19,7 +19,7 @@ function afterZoomAndLoad(aCallback, aTab) {
value = undefined;
oldAPTS.call(FullZoom, value, browser);
// Don't reset _applyPrefToSetting until we've seen the about:blank load(s)
if (browser && (browser.currentURI.spec.indexOf("http:") != -1)) {
if (browser && browser.currentURI.spec.startsWith("http:")) {
FullZoom._applyPrefToSetting = oldAPTS;
didZoom = true;
}

View File

@ -28,7 +28,7 @@ function test() {
executeSoon(function () {
let consoleListener = {
observe: function (m) {
if (m.message.indexOf("NS_ERROR_DOM_BAD_URI") > -1) {
if (m.message.contains("NS_ERROR_DOM_BAD_URI")) {
ok(true, "drop was blocked");
executeSoon(finish);
}

View File

@ -756,7 +756,7 @@ function triggerSecondaryCommand(popup, index) {
}, false);
// One down event to open the popup
EventUtils.synthesizeKey("VK_DOWN", { altKey: (navigator.platform.indexOf("Mac") == -1) });
EventUtils.synthesizeKey("VK_DOWN", { altKey: !navigator.platform.contains("Mac") });
}
function loadURI(uri, callback) {

View File

@ -91,6 +91,7 @@ var tests = {
}
},
testWorkerChatWindow: function(next) {
const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
let port = Social.provider.port;
ok(port, "provider has a port");
port.onmessage = function (e) {
@ -103,10 +104,11 @@ var tests = {
chats.selectedChat.close();
}
ok(!chats.selectedChat, "chats are all closed");
ensureSocialUrlNotRemembered(chatUrl);
next();
break;
}
}
port.postMessage({topic: "test-worker-chat" });
port.postMessage({topic: "test-worker-chat", data: chatUrl});
}
}

View File

@ -143,7 +143,7 @@ function checkOKButton() {
// This rest of particular test doesn't really apply on Mac, since buttons
// aren't focusable by default.
if (navigator.platform.indexOf("Mac") != -1) {
if (navigator.platform.contains("Mac")) {
executeSoon(testCloseBySpace);
return;
}
@ -151,7 +151,7 @@ function checkOKButton() {
let displayName = document.getElementById("socialUserDisplayName");
// Linux has the buttons in the [unshare] [ok] order, so displayName will come first.
if (navigator.platform.indexOf("Linux") != -1) {
if (navigator.platform.contains("Linux")) {
checkNextInTabOrder(displayName, function () {
checkNextInTabOrder(undoButton, function () {
checkNextInTabOrder(okButton, testCloseBySpace);

View File

@ -64,7 +64,7 @@ onconnect = function(e) {
testPort.postMessage({topic:"got-flyout-visibility", result: event.data.result});
break;
case "test-worker-chat":
apiPort.postMessage({topic: "social.request-chat", data: "https://example.com/browser/browser/base/content/test/social_chat.html" });
apiPort.postMessage({topic: "social.request-chat", data: event.data.data });
break;
case "social.initialize":
// This is the workerAPI port, respond and set up a notification icon.

View File

@ -76,7 +76,7 @@ function handleMessageEvents(event) {
catch (e) {
var bodyInnerHTML = "";
}
if (cacheCount == 2 || (bodyInnerHTML.indexOf("error") != -1)) {
if (cacheCount == 2 || bodyInnerHTML.contains("error")) {
clearInterval(intervalID);
is(cacheCount, 2, "frame not reloaded successfully");
if (cacheCount != 2) {

View File

@ -466,7 +466,7 @@
return selectedVal;
// The selection doesn't span the full domain if it doesn't contain a slash and is
// followed by some character other than a slash.
if (selectedVal.indexOf("/") == -1) {
if (!selectedVal.contains("/")) {
let remainder = inputVal.replace(selectedVal, "");
if (remainder != "" && remainder[0] != "/")
return selectedVal;

View File

@ -4,7 +4,7 @@
"use strict";
let EXPORTED_SYMBOLS = ["PageThumbs", "PageThumbsStorage", "PageThumbsCache"];
let EXPORTED_SYMBOLS = ["PageThumbs", "PageThumbsStorage"];
const Cu = Components.utils;
const Cc = Components.classes;
@ -533,63 +533,3 @@ let PageThumbsHistoryObserver = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
};
/**
* A singleton handling the storage of page thumbnails.
*/
let PageThumbsCache = {
/**
* Calls the given callback with a cache entry opened for reading.
* @param aKey The key identifying the desired cache entry.
* @param aCallback The callback that is called when the cache entry is ready.
*/
getReadEntry: function Cache_getReadEntry(aKey, aCallback) {
// Try to open the desired cache entry.
this._openCacheEntry(aKey, Ci.nsICache.ACCESS_READ, aCallback);
},
/**
* Opens the cache entry identified by the given key.
* @param aKey The key identifying the desired cache entry.
* @param aAccess The desired access mode (see nsICache.ACCESS_* constants).
* @param aCallback The function to be called when the cache entry was opened.
*/
_openCacheEntry: function Cache_openCacheEntry(aKey, aAccess, aCallback) {
function onCacheEntryAvailable(aEntry, aAccessGranted, aStatus) {
let validAccess = aAccess == aAccessGranted;
let validStatus = Components.isSuccessCode(aStatus);
// Check if a valid entry was passed and if the
// access we requested was actually granted.
if (aEntry && !(validAccess && validStatus)) {
aEntry.close();
aEntry = null;
}
aCallback(aEntry);
}
let listener = this._createCacheListener(onCacheEntryAvailable);
this._cacheSession.asyncOpenCacheEntry(aKey, aAccess, listener);
},
/**
* Returns a cache listener implementing the nsICacheListener interface.
* @param aCallback The callback to be called when the cache entry is available.
* @return The new cache listener.
*/
_createCacheListener: function Cache_createCacheListener(aCallback) {
return {
onCacheEntryAvailable: aCallback,
QueryInterface: XPCOMUtils.generateQI([Ci.nsICacheListener])
};
}
};
/**
* Define a lazy getter for the cache session.
*/
XPCOMUtils.defineLazyGetter(PageThumbsCache, "_cacheSession", function () {
return Services.cache.createSession(PageThumbs.scheme,
Ci.nsICache.STORE_ON_DISK, true);
});

View File

@ -74,13 +74,8 @@ Protocol.prototype = {
newChannel: function Proto_newChannel(aURI) {
let {url} = parseURI(aURI);
let file = PageThumbsStorage.getFileForURL(url);
if (file.exists()) {
let fileuri = Services.io.newFileURI(file);
return Services.io.newChannelFromURI(fileuri);
}
return new Channel(aURI);
let fileuri = Services.io.newFileURI(file);
return Services.io.newChannelFromURI(fileuri);
},
/**
@ -95,299 +90,6 @@ Protocol.prototype = {
let NSGetFactory = XPCOMUtils.generateNSGetFactory([Protocol]);
/**
* A channel implementation responsible for delivering cached thumbnails.
*/
function Channel(aURI) {
this._uri = aURI;
// nsIChannel
this.originalURI = aURI;
// nsIHttpChannel
this._responseHeaders = {"content-type": PageThumbs.contentType};
}
Channel.prototype = {
_uri: null,
_referrer: null,
_canceled: false,
_status: Cr.NS_OK,
_isPending: false,
_wasOpened: false,
_responseText: "OK",
_responseStatus: 200,
_responseHeaders: null,
_requestMethod: "GET",
_requestStarted: false,
_allowPipelining: true,
_requestSucceeded: true,
/* :::::::: nsIChannel ::::::::::::::: */
get URI() this._uri,
owner: null,
notificationCallbacks: null,
get securityInfo() null,
contentType: PageThumbs.contentType,
contentCharset: null,
contentLength: -1,
get contentDisposition() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
get contentDispositionFilename() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
get contentDispositionHeader() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
open: function Channel_open() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_IMPLEMENTED);
},
asyncOpen: function Channel_asyncOpen(aListener, aContext) {
if (this._isPending)
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_ALREADY_OPENED);
if (this._canceled)
return (Components.returnCode = this._status);
this._isPending = true;
this._wasOpened = true;
this._listener = aListener;
this._context = aContext;
if (this.loadGroup)
this.loadGroup.addRequest(this, null);
if (this._canceled)
return;
let {url} = parseURI(this._uri);
if (!url) {
this._serveThumbnailNotFound();
return;
}
PageThumbsCache.getReadEntry(url, function (aEntry) {
let inputStream = aEntry && aEntry.openInputStream(0);
if (!inputStream || !inputStream.available()) {
if (aEntry)
aEntry.close();
this._serveThumbnailNotFound();
return;
}
this._entry = aEntry;
this._pump = Cc["@mozilla.org/network/input-stream-pump;1"].
createInstance(Ci.nsIInputStreamPump);
this._pump.init(inputStream, -1, -1, 0, 0, true);
this._pump.asyncRead(this, null);
this._trackThumbnailHitOrMiss(true);
}.bind(this));
},
/**
* Serves a "404 Not Found" if we didn't find the requested thumbnail.
*/
_serveThumbnailNotFound: function Channel_serveThumbnailNotFound() {
this._responseStatus = 404;
this._responseText = "Not Found";
this._requestSucceeded = false;
this.onStartRequest(this, null);
this.onStopRequest(this, null, Cr.NS_OK);
this._trackThumbnailHitOrMiss(false);
},
/**
* Implements telemetry tracking for thumbnail cache hits and misses.
* @param aFound Whether the thumbnail was found.
*/
_trackThumbnailHitOrMiss: function Channel_trackThumbnailHitOrMiss(aFound) {
Services.telemetry.getHistogramById("FX_THUMBNAILS_HIT_OR_MISS")
.add(aFound);
},
/* :::::::: nsIStreamListener ::::::::::::::: */
onStartRequest: function Channel_onStartRequest(aRequest, aContext) {
if (!this.canceled && Components.isSuccessCode(this._status))
this._status = aRequest.status;
this._requestStarted = true;
this._listener.onStartRequest(this, this._context);
},
onDataAvailable: function Channel_onDataAvailable(aRequest, aContext,
aInStream, aOffset, aCount) {
this._listener.onDataAvailable(this, this._context, aInStream, aOffset, aCount);
},
onStopRequest: function Channel_onStopRequest(aRequest, aContext, aStatus) {
this._isPending = false;
this._status = aStatus;
this._listener.onStopRequest(this, this._context, aStatus);
this._listener = null;
this._context = null;
if (this._entry)
this._entry.close();
if (this.loadGroup)
this.loadGroup.removeRequest(this, null, aStatus);
},
/* :::::::: nsIRequest ::::::::::::::: */
get status() this._status,
get name() this._uri.spec,
isPending: function Channel_isPending() this._isPending,
loadFlags: Ci.nsIRequest.LOAD_NORMAL,
loadGroup: null,
cancel: function Channel_cancel(aStatus) {
if (this._canceled)
return;
this._canceled = true;
this._status = aStatus;
if (this._pump)
this._pump.cancel(aStatus);
},
suspend: function Channel_suspend() {
if (this._pump)
this._pump.suspend();
},
resume: function Channel_resume() {
if (this._pump)
this._pump.resume();
},
/* :::::::: nsIHttpChannel ::::::::::::::: */
get referrer() this._referrer,
set referrer(aReferrer) {
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
this._referrer = aReferrer;
},
get requestMethod() this._requestMethod,
set requestMethod(aMethod) {
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
this._requestMethod = aMethod.toUpperCase();
},
get allowPipelining() this._allowPipelining,
set allowPipelining(aAllow) {
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_FAILURE);
this._allowPipelining = aAllow;
},
redirectionLimit: 10,
get responseStatus() {
if (this._requestStarted)
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
return this._responseStatus;
},
get responseStatusText() {
if (this._requestStarted)
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
return this._responseText;
},
get requestSucceeded() {
if (this._requestStarted)
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
return this._requestSucceeded;
},
isNoCacheResponse: function Channel_isNoCacheResponse() false,
isNoStoreResponse: function Channel_isNoStoreResponse() false,
getRequestHeader: function Channel_getRequestHeader() {
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
setRequestHeader: function Channel_setRequestHeader() {
if (this._wasOpened)
throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
},
visitRequestHeaders: function Channel_visitRequestHeaders() {},
getResponseHeader: function Channel_getResponseHeader(aHeader) {
let name = aHeader.toLowerCase();
if (name in this._responseHeaders)
return this._responseHeaders[name];
throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
},
setResponseHeader: function Channel_setResponseHeader(aHeader, aValue, aMerge) {
let name = aHeader.toLowerCase();
if (!aValue && !aMerge)
delete this._responseHeaders[name];
else
this._responseHeaders[name] = aValue;
},
visitResponseHeaders: function Channel_visitResponseHeaders(aVisitor) {
for (let name in this._responseHeaders) {
let value = this._responseHeaders[name];
try {
aVisitor.visitHeader(name, value);
} catch (e) {
// The visitor can throw to stop the iteration.
return;
}
}
},
/* :::::::: nsIHttpChannelInternal ::::::::::::::: */
documentURI: null,
get canceled() this._canceled,
allowSpdy: false,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel,
Ci.nsIHttpChannel,
Ci.nsIHttpChannelInternal,
Ci.nsIRequest])
}
/**
* Parses a given URI and extracts all parameters relevant to this protocol.
* @param aURI The URI to parse.

View File

@ -41,7 +41,7 @@ gcli.addCommand({
manual: gcli.lookup("screenshotFullPageManual")
},
{
name: "node",
name: "selector",
type: "node",
defaultValue: null,
description: gcli.lookup("inspectNodeDesc"),
@ -59,7 +59,7 @@ gcli.addCommand({
return promise;
}
else {
return this.grabScreen(document, args.filename, args.fullpage, args.node);
return this.grabScreen(document, args.filename, args.fullpage, args.selector);
}
},
grabScreen:

View File

@ -1707,7 +1707,7 @@ var types = require('gcli/types');
var Type = require('gcli/types').Type;
var Status = require('gcli/types').Status;
var Conversion = require('gcli/types').Conversion;
var Speller = require('gcli/types/spell').Speller;
var spell = require('gcli/types/spell');
/**
@ -1888,13 +1888,14 @@ SelectionType.prototype._findPredictions = function(arg) {
}
// Try fuzzy matching if we don't get a prefix match
if (false && predictions.length === 0) {
var speller = new Speller();
var names = lookup.map(function(opt) {
return opt.name;
if (predictions.length === 0) {
var names = [];
lookup.forEach(function(opt) {
if (!opt.value.hidden) {
names.push(opt.name);
}
});
speller.train(names);
var corrected = speller.correct(match);
var corrected = spell.correct(match, names);
if (corrected) {
lookup.forEach(function(opt) {
if (opt.name === corrected) {
@ -2005,154 +2006,117 @@ exports.SelectionType = SelectionType;
});
/*
* Copyright (c) 2009 Panagiotis Astithas
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* Copyright 2012, Mozilla Foundation and contributors
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
define('gcli/types/spell', ['require', 'exports', 'module' ], function(require, exports, module) {
/*
* A spell-checker based on Damerau-Levenshtein distance.
*/
var INSERTION_COST = 1;
var DELETION_COST = 1;
var SWAP_COST = 1;
var SUBSTITUTION_COST = 2;
var MAX_EDIT_DISTANCE = 4;
/**
* A spell-checker based on the statistical algorithm described by Peter Norvig
* in http://norvig.com/spell-correct.html, and converted to JavaScript by Past
* http://past.github.com/speller/
*
* Usage requires a two-step process:
* 1) call speller.train() one or more times with a large text to train the
* language model
* 2) call speller.correct(word) to retrieve the correction for the specified
* word
* Compute Damerau-Levenshtein Distance
* @see http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
*/
function Speller() {
// A map of words to the count of times they were encountered during training.
this._nWords = {};
}
function damerauLevenshteinDistance(wordi, wordj) {
var N = wordi.length;
var M = wordj.length;
Speller.letters = "abcdefghijklmnopqrstuvwxyz".split("");
// We only need to store three rows of our dynamic programming matrix.
// (Without swap, it would have been two.)
var row0 = new Array(N+1);
var row1 = new Array(N+1);
var row2 = new Array(N+1);
var tmp;
/**
* A function that trains the language model with the words in the supplied
* text. Multiple invocation of this function can extend the training of the
* model.
*/
Speller.prototype.train = function(words) {
words.forEach(function(word) {
word = word.toLowerCase();
this._nWords[word] = this._nWords.hasOwnProperty(word) ?
this._nWords[word] + 1 :
1;
}, this);
var i, j;
// The distance between the empty string and a string of size i is the cost
// of i insertions.
for (i = 0; i <= N; i++) {
row1[i] = i * INSERTION_COST;
}
// Row-by-row, we're computing the edit distance between substrings wordi[0..i]
// and wordj[0..j].
for (j = 1; j <= M; j++)
{
// Edit distance between wordi[0..0] and wordj[0..j] is the cost of j
// insertions.
row0[0] = j * INSERTION_COST;
for (i = 1; i <= N; i++)
{
// Handle deletion, insertion and substitution: we can reach each cell
// from three other cells corresponding to those three operations. We
// want the minimum cost.
row0[i] = Math.min(
row0[i-1] + DELETION_COST,
row1[i] + INSERTION_COST,
row1[i-1] + (wordi[i-1] === wordj[j-1] ? 0 : SUBSTITUTION_COST));
// We handle swap too, eg. distance between help and hlep should be 1. If
// we find such a swap, there's a chance to update row0[1] to be lower.
if (i > 1 && j > 1 && wordi[i-1] === wordj[j-2] && wordj[j-1] === wordi[i-2]) {
row0[i] = Math.min(row0[i], row2[i-2] + SWAP_COST);
}
}
tmp = row2;
row2 = row1;
row1 = row0;
row0 = tmp;
}
return row1[N];
};
/**
* A function that returns the correction for the specified word.
*/
Speller.prototype.correct = function(word) {
if (this._nWords.hasOwnProperty(word)) {
return word;
}
exports.correct = function(word, names) {
var distance = {};
var sorted_candidates;
var candidates = {};
var list = this._edits(word);
list.forEach(function(edit) {
if (this._nWords.hasOwnProperty(edit)) {
candidates[this._nWords[edit]] = edit;
names.forEach(function(candidate) {
distance[candidate] = damerauLevenshteinDistance(word, candidate);
});
sorted_candidates = names.sort(function(worda, wordb) {
if (distance[worda] !== distance[wordb]) {
return distance[worda] - distance[wordb];
} else {
// if the score is the same, always return the first string
// in the lexicographical order
return worda < wordb;
}
}, this);
});
if (this._countKeys(candidates) > 0) {
return candidates[this._max(candidates)];
if (distance[sorted_candidates[0]] <= MAX_EDIT_DISTANCE) {
return sorted_candidates[0];
} else {
return undefined;
}
list.forEach(function(edit) {
this._edits(edit).forEach(function(w) {
if (this._nWords.hasOwnProperty(w)) {
candidates[this._nWords[w]] = w;
}
}, this);
}, this);
return this._countKeys(candidates) > 0 ?
candidates[this._max(candidates)] :
null;
};
/**
* A helper function that counts the keys in the supplied object.
*/
Speller.prototype._countKeys = function(object) {
// return Object.keys(object).length; ?
var count = 0;
for (var attr in object) {
if (object.hasOwnProperty(attr)) {
count++;
}
}
return count;
};
/**
* A helper function that returns the word with the most occurrences in the
* language model, among the supplied candidates.
* @param candidates
*/
Speller.prototype._max = function(candidates) {
var arr = [];
for (var candidate in candidates) {
if (candidates.hasOwnProperty(candidate)) {
arr.push(candidate);
}
}
return Math.max.apply(null, arr);
};
/**
* A function that returns the set of possible corrections of the specified
* word. The edits can be deletions, insertions, alterations or transpositions.
*/
Speller.prototype._edits = function(word) {
var results = [];
// Deletion
for (var i = 0; i < word.length; i++) {
results.push(word.slice(0, i) + word.slice(i + 1));
}
// Transposition
for (i = 0; i < word.length - 1; i++) {
results.push(word.slice(0, i) + word.slice(i + 1, i + 2)
+ word.slice(i, i + 1) + word.slice(i + 2));
}
// Alteration
for (i = 0; i < word.length; i++) {
Speller.letters.forEach(function(l) {
results.push(word.slice(0, i) + l + word.slice(i + 1));
}, this);
}
// Insertion
for (i = 0; i <= word.length; i++) {
Speller.letters.forEach(function(l) {
results.push(word.slice(0, i) + l + word.slice(i));
}, this);
}
return results;
};
exports.Speller = Speller;
});
/*
@ -4068,7 +4032,9 @@ exports._empty = [];
*/
exports.setDocument = function(document) {
doc = document;
exports._empty = doc.querySelectorAll('x>:root');
if (doc != null) {
exports._empty = doc.querySelectorAll('x>:root');
}
};
/**
@ -5127,7 +5093,7 @@ var view = require('gcli/ui/view');
var l10n = require('gcli/l10n');
var canon = require('gcli/canon');
var Promise = require('gcli/promise').Promise;
var Q = require('gcli/promise');
var Status = require('gcli/types').Status;
var Conversion = require('gcli/types').Conversion;
@ -5190,8 +5156,6 @@ function Assignment(param, paramIndex) {
this.paramIndex = paramIndex;
this.onAssignmentChange = util.createEvent('Assignment.onAssignmentChange');
this.setBlank();
}
/**
@ -5275,39 +5239,6 @@ Assignment.prototype.isInName = function() {
this.conversion.arg.prefix.slice(-1) !== ' ';
};
/**
* Report on the status of the last parse() conversion.
* We force mutations to happen through this method rather than have
* setValue and setArgument functions to help maintain integrity when we
* have ArrayArguments and don't want to get confused. This way assignments
* are just containers for a conversion rather than things that store
* a connection between an arg/value.
* @see types.Conversion
*/
Assignment.prototype.setConversion = function(conversion) {
var oldConversion = this.conversion;
this.conversion = conversion;
this.conversion.assign(this);
if (this.conversion.equals(oldConversion)) {
return;
}
this.onAssignmentChange({
assignment: this,
conversion: this.conversion,
oldConversion: oldConversion
});
};
/**
* Setup an empty value for the conversion by parsing an empty argument.
*/
Assignment.prototype.setBlank = function() {
this.setConversion(this.param.type.getBlank());
};
/**
* Make sure that there is some content for this argument by using an
* Argument of '' if needed.
@ -5454,8 +5385,6 @@ function CommandAssignment() {
this.param = new canon.Parameter(commandParamMetadata);
this.paramIndex = -1;
this.onAssignmentChange = util.createEvent('CommandAssignment.onAssignmentChange');
this.setBlank();
}
CommandAssignment.prototype = Object.create(Assignment.prototype);
@ -5540,6 +5469,7 @@ function Requisition(environment, doc) {
// The command that we are about to execute.
// @see setCommandConversion()
this.commandAssignment = new CommandAssignment();
this._setAssignment(this.commandAssignment, null, true);
// The object that stores of Assignment objects that we are filling out.
// The Assignment objects are stored under their param.name for named
@ -5626,6 +5556,7 @@ Requisition.prototype._commandAssignmentChanged = function(ev) {
for (var i = 0; i < command.params.length; i++) {
var param = command.params[i];
var assignment = new Assignment(param, i);
this._setAssignment(assignment, null, true);
assignment.onAssignmentChange.add(this._assignmentChanged, this);
this._assignments[param.name] = assignment;
}
@ -5748,40 +5679,81 @@ Requisition.prototype.getAssignments = function(includeCommand) {
};
/**
* Alter the given assignment using the given arg. This function is better than
* calling assignment.setConversion(assignment.param.type.parse(arg)) because
* it adjusts the args in this requisition to keep things up to date
* Alter the given assignment using the given arg.
* @param assignment The assignment to alter
* @param arg The new value for the assignment. An instance of Argument, or an
* instance of Conversion, or null to set the blank value.
*/
Requisition.prototype.setAssignment = function(assignment, arg) {
var originalArgs = assignment.arg.getArgs();
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
this._setAssignment(assignment, arg, false);
};
var replacementArgs = arg.getArgs();
var maxLen = Math.max(originalArgs.length, replacementArgs.length);
for (var i = 0; i < maxLen; i++) {
// If there are no more original args, or if the original arg was blank
// (i.e. not typed by the user), we'll just need to add at the end
if (i >= originalArgs.length || originalArgs[i].type === 'BlankArgument') {
this._args.push(replacementArgs[i]);
continue;
}
/**
* Internal function to alter the given assignment using the given arg.
* @param assignment The assignment to alter
* @param arg The new value for the assignment. An instance of Argument, or an
* instance of Conversion, or null to set the blank value.
* @param skipArgUpdate (default=false) Adjusts the args in this requisition to
* keep things up to date. Args should only be skipped when setAssignment is
* being called as part of the update process.
*/
Requisition.prototype._setAssignment = function(assignment, arg, skipArgUpdate) {
if (!skipArgUpdate) {
var originalArgs = assignment.arg.getArgs();
var index = this._args.indexOf(originalArgs[i]);
if (index === -1) {
console.error('Couldn\'t find ', originalArgs[i], ' in ', this._args);
throw new Error('Couldn\'t find ' + originalArgs[i]);
}
// Update the args array
var replacementArgs = arg.getArgs();
var maxLen = Math.max(originalArgs.length, replacementArgs.length);
for (var i = 0; i < maxLen; i++) {
// If there are no more original args, or if the original arg was blank
// (i.e. not typed by the user), we'll just need to add at the end
if (i >= originalArgs.length || originalArgs[i].type === 'BlankArgument') {
this._args.push(replacementArgs[i]);
continue;
}
// If there are no more replacement args, we just remove the original args
// Otherwise swap original args and replacements
if (i >= replacementArgs.length) {
this._args.splice(index, 1);
}
else {
this._args[index] = replacementArgs[i];
var index = this._args.indexOf(originalArgs[i]);
if (index === -1) {
console.error('Couldn\'t find ', originalArgs[i], ' in ', this._args);
throw new Error('Couldn\'t find ' + originalArgs[i]);
}
// If there are no more replacement args, we just remove the original args
// Otherwise swap original args and replacements
if (i >= replacementArgs.length) {
this._args.splice(index, 1);
}
else {
this._args[index] = replacementArgs[i];
}
}
}
var conversion;
if (arg == null) {
conversion = assignment.param.type.getBlank();
}
else if (typeof arg.getStatus === 'function') {
conversion = arg;
}
else {
conversion = assignment.param.type.parse(arg);
}
var oldConversion = assignment.conversion;
assignment.conversion = conversion;
assignment.conversion.assign(assignment);
if (assignment.conversion.equals(oldConversion)) {
return;
}
assignment.onAssignmentChange({
assignment: assignment,
conversion: assignment.conversion,
oldConversion: oldConversion
});
};
/**
@ -5789,7 +5761,7 @@ Requisition.prototype.setAssignment = function(assignment, arg) {
*/
Requisition.prototype.setBlankArguments = function() {
this.getAssignments().forEach(function(assignment) {
assignment.setBlank();
this._setAssignment(assignment, null, true);
}, this);
};
@ -6148,8 +6120,8 @@ Requisition.prototype.getAssignmentAt = function(cursor) {
* @param input (optional) The command to execute. See above.
*/
Requisition.prototype.exec = function(input) {
var command;
var args;
var command = null;
var args = null;
var hidden = false;
if (input && input.hidden) {
hidden = true;
@ -6200,33 +6172,58 @@ Requisition.prototype.exec = function(input) {
this.commandOutputManager.onOutput({ output: output });
var onDone = function(data) {
output.complete(data);
};
var onError = function(error) {
console.error(error);
output.error = true;
output.complete(error);
};
try {
var context = exports.createExecutionContext(this);
var reply = command.exec(args, context);
if (reply != null && typeof reply.then === 'function') {
reply.then(
function(data) { output.complete(data); },
function(error) { output.error = true; output.complete(error); });
output.promise = reply;
// Add progress to our promise and add a handler for it here
// See bug 659300
}
else {
output.complete(reply);
}
this._then(reply, onDone, onError);
}
catch (ex) {
console.error(ex);
output.error = true;
output.complete(ex);
onError(ex);
}
this.update('');
return output;
};
/**
* Different types of promise have different ways of doing 'then'. This is a
* catch-all so we can ignore the differences. It also handles concrete values
* and calls onDone directly if thing is not a promise.
* @param thing The value to test for 'promiseness'
* @param onDone The action to take if thing is resolved
* @param onError The action to take if thing is rejected
*/
Requisition.prototype._then = function(thing, onDone, onError) {
var then = null;
if (thing != null && typeof thing.then === 'function') {
// Old GCLI style / simple promises with a then function
then = thing.then;
}
else if (thing != null && thing.promise != null &&
typeof thing.promise.then === 'function') {
// Q / Mozilla add-ons style
then = thing.promise.then;
}
if (then != null) {
then(onDone, onError);
}
else {
onDone(thing);
}
};
/**
* Called by the UI when ever the user interacts with a command line input
* @param typed The contents of the input field
@ -6517,7 +6514,7 @@ Requisition.prototype._split = function(args) {
// Special case: if the user enters { console.log('foo'); } then we need to
// use the hidden 'eval' command
conversion = new Conversion(evalCommand, new ScriptArgument());
this.commandAssignment.setConversion(conversion);
this._setAssignment(this.commandAssignment, conversion, true);
return;
}
@ -6525,8 +6522,8 @@ Requisition.prototype._split = function(args) {
while (argsUsed <= args.length) {
var arg = (argsUsed === 1) ?
args[0] :
new MergedArgument(args, 0, argsUsed);
args[0] :
new MergedArgument(args, 0, argsUsed);
conversion = this.commandAssignment.param.type.parse(arg);
// We only want to carry on if this command is a parent command,
@ -6544,7 +6541,7 @@ Requisition.prototype._split = function(args) {
argsUsed++;
}
this.commandAssignment.setConversion(conversion);
this._setAssignment(this.commandAssignment, conversion, true);
for (var i = 0; i < argsUsed; i++) {
args.shift();
@ -6590,11 +6587,8 @@ Requisition.prototype._assign = function(args) {
if (this.assignmentCount === 1) {
var assignment = this.getAssignment(0);
if (assignment.param.type instanceof StringType) {
var arg = (args.length === 1) ?
args[0] :
new MergedArgument(args);
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
var arg = (args.length === 1) ? args[0] : new MergedArgument(args);
this._setAssignment(assignment, arg, true);
return;
}
}
@ -6639,8 +6633,7 @@ Requisition.prototype._assign = function(args) {
arrayArg.addArgument(arg);
}
else {
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
this._setAssignment(assignment, arg, true);
}
}
else {
@ -6657,7 +6650,7 @@ Requisition.prototype._assign = function(args) {
// If not set positionally, and we can't set it non-positionally,
// we have to default it to prevent previous values surviving
if (!assignment.param.isPositionalAllowed) {
assignment.setBlank();
this._setAssignment(assignment, null, true);
return;
}
@ -6674,7 +6667,7 @@ Requisition.prototype._assign = function(args) {
}
else {
if (args.length === 0) {
assignment.setBlank();
this._setAssignment(assignment, null, true);
}
else {
var arg = args.splice(0, 1)[0];
@ -6688,8 +6681,7 @@ Requisition.prototype._assign = function(args) {
this._unassigned.push(new UnassignedAssignment(this, arg));
}
else {
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
this._setAssignment(assignment, arg, true);
}
}
}
@ -6698,8 +6690,7 @@ Requisition.prototype._assign = function(args) {
// Now we need to assign the array argument (if any)
Object.keys(arrayArgs).forEach(function(name) {
var assignment = this.getAssignment(name);
var conversion = assignment.param.type.parse(arrayArgs[name]);
assignment.setConversion(conversion);
this._setAssignment(assignment, arrayArgs[name], true);
}, this);
// What's left is can't be assigned, but we need to extract
@ -6729,17 +6720,31 @@ function Output(options) {
}
/**
* Called when there is data to display
* @param data
* Called when there is data to display, but the command is still executing
* @param data The new data. If the data structure has been altered but the
* root object is still the same, The same root object should be passed in the
* data parameter.
* @param ev Optional additional event data, for example to explain how the
* data structure has changed
*/
Output.prototype.complete = function(data) {
Output.prototype.changed = function(data, ev) {
this.data = data;
ev = ev || {};
ev.output = this;
this.onChange(ev);
};
/**
* Called when there is data to display, and the command has finished executing
* See changed() for details on parameters.
*/
Output.prototype.complete = function(data, ev) {
this.end = new Date();
this.duration = this.end.getTime() - this.start.getTime();
this.completed = true;
this.onChange({ output: this });
this.changed(data, ev);
};
/**
@ -6830,8 +6835,15 @@ exports.createExecutionContext = function(requisition) {
document: requisition.document,
environment: requisition.environment,
createView: view.createView,
defer: function() {
return Q.defer();
},
/**
* @deprecated Use defer() instead, which does the same thing, but is not
* confusingly named
*/
createPromise: function() {
return new Promise();
return Q.defer();
}
};
};
@ -6856,8 +6868,13 @@ exports.createExecutionContext = function(requisition) {
define('gcli/promise', ['require', 'exports', 'module' ], function(require, exports, module) {
Components.utils.import("resource:///modules/devtools/Promise.jsm");
exports.Promise = Promise;
var imported = {};
Components.utils.import("resource://gre/modules/commonjs/promise/core.js",
imported);
exports.defer = imported.Promise.defer;
exports.resolve = imported.Promise.resolve;
exports.reject = imported.Promise.reject;
});
define("text!gcli/ui/intro.html", [], "\n" +
@ -7237,7 +7254,7 @@ FocusManager.prototype._checkShow = function() {
if (fire) {
if (this._debug) {
console.debug('FocusManager.onVisibilityChange', ev);
console.log('FocusManager.onVisibilityChange', ev);
}
this.onVisibilityChange(ev);
}
@ -7735,6 +7752,9 @@ Field.prototype.destroy = function() {
delete this.messageElement;
};
// Note: We could/should probably change Fields from working with Conversions
// to working with Arguments (Tokens), which makes for less calls to parse()
/**
* Update this field display with the value from this conversion.
* Subclasses should provide an implementation of this function.
@ -9393,7 +9413,9 @@ Inputter.prototype.textChanged = function() {
input.typed = newStr;
this._processCaretChange(input);
this.element.value = newStr;
if (this.element.value !== newStr) {
this.element.value = newStr;
}
this.onInputChange({ inputState: input });
};
@ -9469,8 +9491,12 @@ Inputter.prototype._processCaretChange = function(input) {
cursor: { start: start, end: end }
};
this.element.selectionStart = start;
this.element.selectionEnd = end;
if (this.element.selectionStart !== start) {
this.element.selectionStart = start;
}
if (this.element.selectionEnd !== end) {
this.element.selectionEnd = end;
}
this._checkAssignment(start);
@ -9605,7 +9631,7 @@ Inputter.prototype.onKeyUp = function(ev) {
// If the user is on a valid value, then we increment the value, but if
// they've typed something that's not right we page through predictions
if (this.assignment.getStatus() === Status.VALID) {
this.requisition.increment(assignment);
this.requisition.increment(this.assignment);
// See notes on focusManager.onInputChange in onKeyDown
if (this.focusManager) {
this.focusManager.onInputChange();
@ -9629,7 +9655,7 @@ Inputter.prototype.onKeyUp = function(ev) {
else {
// See notes above for the UP key
if (this.assignment.getStatus() === Status.VALID) {
this.requisition.decrement(assignment);
this.requisition.decrement(this.assignment);
// See notes on focusManager.onInputChange in onKeyDown
if (this.focusManager) {
this.focusManager.onInputChange();
@ -10314,7 +10340,7 @@ Tooltip.prototype.selectChoice = function(ev) {
* Called by the onFieldChange event on the current Field
*/
Tooltip.prototype.fieldChanged = function(ev) {
this.assignment.setConversion(ev.conversion);
this.requisition.setAssignment(this.assignment, ev.conversion.arg);
var isError = ev.conversion.message != null && ev.conversion.message !== '';
this.focusManager.setError(isError);

View File

@ -163,8 +163,8 @@ function testPrefStatus() {
helpers.setInput('pref list');
helpers.check({
input: 'pref list',
hints: '',
markup: 'EEEEVEEEE',
hints: ' -> pref set',
markup: 'IIIIVIIII',
status: 'ERROR'
});
}

View File

@ -108,8 +108,8 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
* @param options Lookup of options that customize test running. Includes:
* - window (default=undefined) A reference to the DOM window. If left
* undefined then a reduced set of tests will run.
* - isNode (default=false) Are we running under NodeJS, specifically, are we
* using JSDom, which isn't a 100% complete DOM implementation.
* - isJsdom (default=false) Are we running under JSDom, specifically, which
* isn't a 100% complete DOM implementation.
* Some tests are skipped when using NodeJS.
* - display (default=undefined) A reference to a Display implementation.
* A reduced set of tests will run if left undefined
@ -119,12 +119,12 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
* |requisition.exec()| which prevents the display from becoming messed up,
* however use of hideExec restricts the set of tests that are run
*/
exports.run = function(options) {
exports.runAsync = function(options, callback) {
options = options || {};
examiner.mergeDefaultOptions(options);
examiner.reset();
examiner.run(options);
examiner.runAsync(options, callback);
// A better set of default than those specified above, come from the set
// that are passed to run().
@ -155,13 +155,6 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
// setTimeout keeps stack traces clear of RequireJS frames
window.setTimeout(function() {
var options = {
window: window,
display: window.display,
hideExec: true
};
exports.run(options);
window.createDebugCheck = function() {
require([ 'gclitest/helpers' ], function(helpers) {
helpers.setup(options);
@ -198,7 +191,15 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
mockCommands.setup();
});
};
window.testCommands();
var options = {
window: window,
display: window.display,
hideExec: true
};
exports.runAsync(options, function() {
window.testCommands();
});
}, 10);
return {
@ -326,25 +327,6 @@ examiner.mergeDefaultOptions = function(options) {
});
};
/**
* Run the tests defined in the test suite synchronously
*/
examiner.run = function(options) {
Object.keys(examiner.suites).forEach(function(suiteName) {
var suite = examiner.suites[suiteName];
suite.run(options);
}.bind(this));
if (options.detailedResultLog) {
examiner.detailedResultLog();
}
else {
console.log('Completed test suite');
}
return examiner.suites;
};
/**
* Run all the tests asynchronously
*/
@ -477,21 +459,6 @@ Suite.prototype.reset = function() {
}, this);
};
/**
* Run all the tests in this suite synchronously
*/
Suite.prototype.run = function(options) {
if (!this._setup(options)) {
return;
}
Object.keys(this.tests).forEach(function(testName) {
this.tests[testName].run(options);
}, this);
this._shutdown(options);
};
/**
* Run all the tests in this suite asynchronously
*/
@ -636,6 +603,9 @@ function Test(suite, name, func) {
this.func = func;
this.title = name.replace(/^test/, '').replace(/([A-Z])/g, ' $1');
this.outstanding = [];
this.callback = undefined;
this.failures = [];
this.status = stati.notrun;
this.checks = 0;
@ -645,16 +615,20 @@ function Test(suite, name, func) {
* Reset the test to its original state
*/
Test.prototype.reset = function() {
this.outstanding = [];
this.callback = undefined;
this.failures = [];
this.status = stati.notrun;
this.checks = 0;
};
/**
* Run just a single test
* Run all the tests in this suite asynchronously
*/
Test.prototype.run = function(options) {
Test.prototype.runAsync = function(options, callback) {
assert.currentTest = this;
this.callback = callback;
this.status = stati.executing;
this.failures = [];
this.checks = 0;
@ -675,18 +649,20 @@ Test.prototype.run = function(options) {
}
assert.currentTest = null;
this.checkFinish();
};
/**
* Run all the tests in this suite asynchronously
* Check to see if the currently executing test is completed (i.e. the list of
* outstanding tasks has all been completed)
*/
Test.prototype.runAsync = function(options, callback) {
setTimeout(function() {
this.run(options);
if (typeof callback === 'function') {
callback();
Test.prototype.checkFinish = function() {
if (this.outstanding.length == 0) {
if (typeof this.callback === 'function') {
this.callback();
}
}.bind(this), delay);
}
};
/**
@ -892,21 +868,25 @@ define('gclitest/testCanon', ['require', 'exports', 'module' , 'gclitest/helpers
* limitations under the License.
*/
define('gclitest/helpers', ['require', 'exports', 'module' , 'test/assert', 'gcli/util'], function(require, exports, module) {
define('gclitest/helpers', ['require', 'exports', 'module' , 'test/assert'], function(require, exports, module) {
var test = require('test/assert');
var util = require('gcli/util');
// A copy of this code exists in firefox mochitests; when updated here it
// should be updated there too. Hence the use of an exports synonym for non
// AMD contexts.
var helpers = exports;
helpers._display = undefined;
helpers._options = undefined;
helpers.setup = function(options) {
helpers._options = options;
helpers._display = options.display;
};
helpers.shutdown = function(options) {
helpers._options = undefined;
helpers._display = undefined;
};
@ -1025,6 +1005,16 @@ helpers.setInput = function(typed, cursor) {
if (cursor) {
helpers._display.inputter.setCursor({ start: cursor, end: cursor });
}
else {
// This is a hack because jsdom appears to not handle cursor updates
// in the same way as most browsers.
if (helpers._options.isJsdom) {
helpers._display.inputter.setCursor({
start: typed.length,
end: typed.length
});
}
}
helpers._display.focusManager.onInputChange();
};
@ -1589,7 +1579,7 @@ exports.testElement = function(options) {
test.ok(assign1.arg.type === 'BlankArgument');
test.is(undefined, assign1.value);
if (!options.isNode) {
if (!options.isJsdom) {
update({ typed: 'tse :root', cursor: { start: 9, end: 9 } });
test.is( 'VVVVVVVVV', statuses);
test.is(Status.VALID, status);
@ -1625,7 +1615,7 @@ exports.testElement = function(options) {
test.is(undefined, assign1.value);
}
else {
test.log('Skipping :root test due to jsdom (from isNode)');
test.log('Skipping :root test due to jsdom');
}
update({ typed: 'tse #', cursor: { start: 5, end: 5 } });
@ -2360,7 +2350,7 @@ exports.testActivate = function(options) {
helpers.setInput('tsg d');
helpers.check({
hints: ' [options]'
hints: ' [options] -> ccc'
});
helpers.setInput('tsg aa');
@ -2774,9 +2764,10 @@ var mockDoc = {
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gclitest/testFocus', ['require', 'exports', 'module' , 'gclitest/helpers', 'gclitest/mockCommands'], function(require, exports, module) {
define('gclitest/testFocus', ['require', 'exports', 'module' , 'test/assert', 'gclitest/helpers', 'gclitest/mockCommands'], function(require, exports, module) {
var test = require('test/assert');
var helpers = require('gclitest/helpers');
var mockCommands = require('gclitest/mockCommands');
@ -2791,6 +2782,11 @@ exports.shutdown = function(options) {
};
exports.testBasic = function(options) {
if (options.isJsdom) {
test.log('jsdom does not pass on focus events properly, skipping testBasic');
return;
}
helpers.focusInput();
helpers.exec(options, 'help');
@ -3343,9 +3339,8 @@ exports.testHidden = function(options) {
helpers.setInput('tshidde');
helpers.check({
input: 'tshidde',
markup: 'EEEEEEE',
status: 'ERROR',
hints: '',
hints: ' -> tse',
status: 'ERROR'
});
helpers.setInput('tshidden');
@ -3470,10 +3465,11 @@ exports.testHidden = function(options) {
* limitations under the License.
*/
define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers', 'test/assert'], function(require, exports, module) {
define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers', 'test/assert', 'gcli/canon'], function(require, exports, module) {
var helpers = require('gclitest/helpers');
var test = require('test/assert');
var canon = require('gcli/canon');
exports.setup = function(options) {
helpers.setup(options);
@ -3484,8 +3480,8 @@ define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers
};
exports.testIntroStatus = function(options) {
if (options.isFirefox) {
test.log('Skipping testIntroStatus in Firefox.');
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
@ -3507,8 +3503,8 @@ define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers
};
exports.testIntroExec = function(options) {
if (options.isFirefox) {
test.log('Skipping testIntroExec in Firefox.');
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
@ -3683,7 +3679,10 @@ exports.testBasic = function(options) {
input('{ document.title');
check('VVVVVVVVVVVVVVVV', Status.VALID, 'document.title', 0);
test.ok('donteval' in options.window, 'donteval exists');
if (!options.isJsdom) {
// jsdom causes an eval here, maybe that's node/v8?
test.ok('donteval' in options.window, 'donteval exists');
}
input('{ don');
check('VVIII', Status.ERROR, 'don', 'donteval');
@ -3832,12 +3831,12 @@ exports.testComplete = function(options) {
check('{ wind', COMPLETES_TO, '{ window', 0);
check('{ window.docum', COMPLETES_TO, '{ window.document', 0);
// Bug 717228: This fails under node
if (!options.isNode) {
// Bug 717228: This fails under jsdom
if (!options.isJsdom) {
check('{ window.document.titl', COMPLETES_TO, '{ window.document.title ', 0);
}
else {
test.log('Running under Node. Skipping tests due to bug 717228.');
test.log('Skipping tests due to jsdom and bug 717228.');
}
}
};
@ -4008,61 +4007,66 @@ exports.testNode = function(options) {
}
});
helpers.setInput('tse :root');
helpers.check({
input: 'tse :root',
hints: ' [options]',
markup: 'VVVVVVVVV',
cursor: 9,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
if (options.isJsdom) {
test.log('skipping node tests because jsdom');
}
else {
helpers.setInput('tse :root');
helpers.check({
input: 'tse :root',
hints: ' [options]',
markup: 'VVVVVVVVV',
cursor: 9,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
helpers.setInput('tse :root ');
helpers.check({
input: 'tse :root ',
hints: '[options]',
markup: 'VVVVVVVVVV',
cursor: 10,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root ', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
test.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
helpers.setInput('tse :root ');
helpers.check({
input: 'tse :root ',
hints: '[options]',
markup: 'VVVVVVVVVV',
cursor: 10,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root ', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
test.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
helpers.setInput('tse #gcli-nomatch');
helpers.check({
input: 'tse #gcli-nomatch',
hints: ' [options]',
markup: 'VVVVIIIIIIIIIIIII',
cursor: 17,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' #gcli-nomatch',
status: 'INCOMPLETE',
message: 'No matches'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
helpers.setInput('tse #gcli-nomatch');
helpers.check({
input: 'tse #gcli-nomatch',
hints: ' [options]',
markup: 'VVVVIIIIIIIIIIIII',
cursor: 17,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' #gcli-nomatch',
status: 'INCOMPLETE',
message: 'No matches'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
}
helpers.setInput('tse #');
helpers.check({
@ -4131,6 +4135,11 @@ exports.testNode = function(options) {
exports.testNodes = function(options) {
var requisition = options.display.requisition;
if (options.isJsdom) {
test.log('skipping node tests because jsdom');
return;
}
helpers.setInput('tse :root --nodes *');
helpers.check({
input: 'tse :root --nodes *',
@ -4236,13 +4245,14 @@ exports.testNodes = function(options) {
* limitations under the License.
*/
define('gclitest/testPref', ['require', 'exports', 'module' , 'gcli/commands/pref', 'gclitest/helpers', 'gclitest/mockSettings', 'test/assert'], function(require, exports, module) {
define('gclitest/testPref', ['require', 'exports', 'module' , 'gcli/commands/pref', 'gclitest/helpers', 'gclitest/mockSettings', 'test/assert', 'gcli/canon'], function(require, exports, module) {
var pref = require('gcli/commands/pref');
var helpers = require('gclitest/helpers');
var mockSettings = require('gclitest/mockSettings');
var test = require('test/assert');
var canon = require('gcli/canon');
exports.setup = function(options) {
@ -4270,6 +4280,11 @@ exports.testPrefShowStatus = function(options) {
return;
}
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
helpers.setInput('pref s');
helpers.check({
typed: 'pref s',
@ -4333,6 +4348,11 @@ exports.testPrefSetStatus = function(options) {
return;
}
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
helpers.setInput('pref s');
helpers.check({
typed: 'pref s',
@ -4352,7 +4372,7 @@ exports.testPrefSetStatus = function(options) {
helpers.setInput('pref xxx');
helpers.check({
typed: 'pref xxx',
markup: 'EEEEVEEE',
markup: 'IIIIVIII',
status: 'ERROR'
});
@ -4395,6 +4415,11 @@ exports.testPrefExec = function(options) {
return;
}
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
var initialAllowSet = pref.allowSet.value;
pref.allowSet.value = false;
@ -4744,12 +4769,11 @@ exports.testPredictions = function(options) {
var resource3 = types.getType({ name: 'resource', include: 'text/css' });
var options3 = resource3.getLookup();
// jsdom fails to support digging into stylesheets
if (!options.isNode) {
if (!options.isJsdom) {
test.ok(options3.length >= 1, 'have resources');
}
else {
test.log('Running under Node. ' +
'Skipping checks due to jsdom document.stylsheets support.');
test.log('Skipping checks due to jsdom document.stylsheets support.');
}
options3.forEach(function(prediction) {
checkPrediction(resource3, prediction);
@ -5018,7 +5042,7 @@ exports.testChange = function(options) {
define('gclitest/testSpell', ['require', 'exports', 'module' , 'test/assert', 'gcli/types/spell'], function(require, exports, module) {
var test = require('test/assert');
var Speller = require('gcli/types/spell').Speller;
var spell = require('gcli/types/spell');
exports.setup = function() {
};
@ -5032,15 +5056,14 @@ exports.testSpellerSimple = function(options) {
return;
}
var speller = new Speller();
speller.train(Object.keys(options.window));
var alternatives = Object.keys(options.window);
test.is(speller.correct('document'), 'document');
test.is(speller.correct('documen'), 'document');
test.is(speller.correct('ocument'), 'document');
test.is(speller.correct('odcument'), 'document');
test.is(spell.correct('document', alternatives), 'document');
test.is(spell.correct('documen', alternatives), 'document');
test.is(spell.correct('ocument', alternatives), 'document');
test.is(spell.correct('odcument', alternatives), 'document');
test.is(speller.correct('========='), null);
test.is(spell.correct('=========', alternatives), undefined);
};
@ -5458,7 +5481,7 @@ function type(typed, tests, options) {
inputter.setCursor({ start: tests.cursor, end: tests.cursor });
}
if (!options.isNode) {
if (!options.isJsdom) {
if (tests.important) {
test.ok(tooltip.field.isImportant, 'Important for ' + typed);
}
@ -5488,8 +5511,8 @@ exports.testActivate = function(options) {
return;
}
if (options.isNode) {
test.log('Running under Node. Reduced checks due to JSDom.textContent');
if (options.isJsdom) {
test.log('Reduced checks due to JSDom.textContent');
}
type(' ', { }, options);
@ -5506,11 +5529,9 @@ exports.testActivate = function(options) {
type('tsb tt', {
important: true,
options: [ ],
error: 'Can\'t use \'tt\'.'
options: [ 'true' ]
}, options);
type('asdf', {
important: false,
options: [ ],
@ -5572,9 +5593,8 @@ function forEachType(options, callback) {
}
exports.testDefault = function(options) {
if (options.isNode) {
test.log('Running under Node. ' +
'Skipping tests due to issues with resource type.');
if (options.isJsdom) {
test.log('Skipping tests due to issues with resource type.');
return;
}

View File

@ -14,8 +14,11 @@ var a = function() {
var anon = a();
anon.displayName = "anonFunc";
var inferred = a();
function evalCall() {
eval("anon();");
eval("inferred();");
}
</script>

View File

@ -3,6 +3,9 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that anonymous functions appear in the stack frame list with either
// their displayName property or a SpiderMonkey-inferred name.
var gPane = null;
var gTab = null;
var gDebuggee = null;
@ -36,13 +39,35 @@ function testAnonCall() {
is(frames.querySelector("#stackframe-0 .dbg-stackframe-name").getAttribute("value"),
"anonFunc", "Frame name should be anonFunc");
resumeAndFinish();
testInferredName();
}}, 0);
});
gDebuggee.evalCall();
}
function testInferredName() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let frames = gDebugger.DebuggerView.StackFrames._frames;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(frames.querySelector("#stackframe-0 .dbg-stackframe-name").getAttribute("value"),
"a/<", "Frame name should be a/<");
resumeAndFinish();
}}, 0);
});
gDebugger.DebuggerController.activeThread.resume();
}
function resumeAndFinish() {
gDebugger.DebuggerController.activeThread.resume(function() {
removeTab(gTab);

View File

@ -6,9 +6,9 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
let tempScope = {};
Cu.import("resource:///modules/devtools/dbg-server.jsm", tempScope);
Cu.import("resource:///modules/devtools/dbg-client.jsm", tempScope);
Cu.import("resource:///modules/Services.jsm", tempScope);
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
Cu.import("resource://gre/modules/Services.jsm", tempScope);
let DebuggerServer = tempScope.DebuggerServer;
let DebuggerTransport = tempScope.DebuggerTransport;
let DebuggerClient = tempScope.DebuggerClient;

View File

@ -35,6 +35,7 @@ const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
const BUTTON_POSITION_SAVE = 0;
const BUTTON_POSITION_CANCEL = 1;
const BUTTON_POSITION_DONT_SAVE = 2;
const BUTTON_POSITION_REVERT=0;
let keysbundle = Services.strings.createBundle("chrome://global-platform/locale/platformKeys.properties");
@ -922,6 +923,72 @@ var Scratchpad = {
}
},
/**
* Restore content from saved version of current file.
*
* @param function aCallback
* Optional function you want to call when file is saved
*/
revertFile: function SP_revertFile(aCallback)
{
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath(this.filename);
if (!file.exists()) {
return;
}
this.importFromFile(file, false, function(aStatus, aContent) {
if (aCallback) {
aCallback(aStatus);
}
});
},
/**
* Prompt to revert scratchpad if it has unsaved changes.
*
* @param function aCallback
* Optional function you want to call when file is saved. The callback
* receives three arguments:
* - aRevert (boolean) - tells if the file has been reverted.
* - status (number) - the file revert status result (if the file was
* saved).
*/
promptRevert: function SP_promptRervert(aCallback)
{
if (this.filename) {
let ps = Services.prompt;
let flags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_REVERT +
ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL;
let button = ps.confirmEx(window,
this.strings.GetStringFromName("confirmRevert.title"),
this.strings.GetStringFromName("confirmRevert"),
flags, null, null, null, null, {});
if (button == BUTTON_POSITION_CANCEL) {
if (aCallback) {
aCallback(false);
}
return;
}
if (button == BUTTON_POSITION_REVERT) {
this.revertFile(function(aStatus) {
if(aCallback){
aCallback(true, aStatus);
}
});
return;
}
}
if (aCallback) {
aCallback(false);
}
},
/**
* Open the Error Console.
*/
@ -1107,6 +1174,14 @@ var Scratchpad = {
_onDirtyChanged: function SP__onDirtyChanged(aEvent)
{
Scratchpad._updateTitle();
if (Scratchpad.filename) {
if (Scratchpad.editor.dirty) {
document.getElementById("sp-cmd-revert").removeAttribute("disabled");
}
else {
document.getElementById("sp-cmd-revert").setAttribute("disabled", true);
}
}
},
/**

View File

@ -33,6 +33,7 @@
<command id="sp-cmd-clearRecentFiles" oncommand="Scratchpad.clearRecentFiles();"/>
<command id="sp-cmd-save" oncommand="Scratchpad.saveFile();"/>
<command id="sp-cmd-saveas" oncommand="Scratchpad.saveFileAs();"/>
<command id="sp-cmd-revert" oncommand="Scratchpad.promptRevert();" disabled="true"/>
<!-- TODO: bug 650340 - implement printFile()
<command id="sp-cmd-printFile" oncommand="Scratchpad.printFile();" disabled="true"/>
@ -132,6 +133,10 @@
label="&saveFileAsCmd.label;"
accesskey="&saveFileAsCmd.accesskey;"
command="sp-cmd-saveas"/>
<menuitem id="sp-menu-revert"
label="&revertCmd.label;"
accesskey="&revertCmd.accesskey;"
command="sp-cmd-revert"/>
<menuseparator/>
<!-- TODO: bug 650340 - implement printFile

View File

@ -33,6 +33,7 @@ MOCHITEST_BROWSER_FILES = \
browser_scratchpad_bug_650760_help_key.js \
browser_scratchpad_bug_651942_recent_files.js \
browser_scratchpad_bug756681_display_non_error_exceptions.js \
browser_scratchpad_bug_751744_revert_to_saved.js \
head.js \
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,137 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let tempScope = {};
Cu.import("resource://gre/modules/NetUtil.jsm", tempScope);
Cu.import("resource://gre/modules/FileUtils.jsm", tempScope);
let NetUtil = tempScope.NetUtil;
let FileUtils = tempScope.FileUtils;
// Reference to the Scratchpad object.
let gScratchpad;
// Reference to the temporary nsIFiles.
let gFile;
// Temporary file name.
let gFileName = "testFileForBug751744.tmp"
// Content for the temporary file.
let gFileContent = "/* this file is already saved */\n" +
"function foo() { alert('bar') }";
let gLength = gFileContent.length;
// Reference to the menu entry.
let menu;
function startTest()
{
gScratchpad = gScratchpadWindow.Scratchpad;
menu = gScratchpadWindow.document.getElementById("sp-menu-revert");
createAndLoadTemporaryFile();
}
function testAfterSaved() {
// Check if the revert menu is disabled as the file is at saved state.
ok(menu.hasAttribute("disabled"), "The revert menu entry is disabled.");
// chancging the text in the file
gScratchpad.setText("\nfoo();", gLength, gLength);
// Checking the text got changed
is(gScratchpad.getText(), gFileContent + "\nfoo();",
"The text changed the first time.");
// Revert menu now should be enabled.
ok(!menu.hasAttribute("disabled"),
"The revert menu entry is enabled after changing text first time");
// reverting back to last saved state.
gScratchpad.revertFile(testAfterRevert);
}
function testAfterRevert() {
// Check if the file's text got reverted
is(gScratchpad.getText(), gFileContent,
"The text reverted back to original text.");
// The revert menu should be disabled again.
ok(menu.hasAttribute("disabled"),
"The revert menu entry is disabled after reverting.");
// chancging the text in the file again
gScratchpad.setText("\nalert(foo.toSource());", gLength, gLength);
// Saving the file.
gScratchpad.saveFile(testAfterSecondSave);
}
function testAfterSecondSave() {
// revert menu entry should be disabled.
ok(menu.hasAttribute("disabled"),
"The revert menu entry is disabled after saving.");
// changing the text.
gScratchpad.setText("\nfoo();", gLength + 23, gLength + 23);
// revert menu entry should get enabled yet again.
ok(!menu.hasAttribute("disabled"),
"The revert menu entry is enabled after changing text third time");
// reverting back to last saved state.
gScratchpad.revertFile(testAfterSecondRevert);
}
function testAfterSecondRevert() {
// Check if the file's text got reverted
is(gScratchpad.getText(), gFileContent + "\nalert(foo.toSource());",
"The text reverted back to the changed saved text.");
// The revert menu should be disabled again.
ok(menu.hasAttribute("disabled"),
"Revert menu entry is disabled after reverting to changed saved state.");
gFile.remove(false);
gFile = null;
gScratchpad = null;
}
function createAndLoadTemporaryFile()
{
// Create a temporary file.
gFile = FileUtils.getFile("TmpD", [gFileName]);
gFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
// Write the temporary file.
let fout = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
fout.init(gFile.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
0644, fout.DEFER_OPEN);
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let fileContentStream = converter.convertToInputStream(gFileContent);
NetUtil.asyncCopy(fileContentStream, fout, tempFileSaved);
}
function tempFileSaved(aStatus)
{
ok(Components.isSuccessCode(aStatus),
"the temporary file was saved successfully");
// Import the file into Scratchpad.
gScratchpad.setFilename(gFile.path);
gScratchpad.importFromFile(gFile.QueryInterface(Ci.nsILocalFile), true,
testAfterSaved);
}
function test()
{
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
openScratchpad(startTest);
}, true);
content.location = "data:text/html,<p>test reverting to last saved state of" +
" a file </p>";
}

View File

@ -15,6 +15,8 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource:///modules/devtools/Commands.jsm");
const Node = Components.interfaces.nsIDOMNode;
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
@ -137,6 +139,28 @@ DeveloperToolbar.prototype.focus = function DT_focus()
}
};
/**
* Called from browser.xul in response to menu-click or keyboard shortcut to
* toggle the toolbar
*/
DeveloperToolbar.prototype.focusToggle = function DT_focusToggle()
{
if (this.visible) {
// If we have focus then the active element is the HTML input contained
// inside the xul input element
var active = this._chromeWindow.document.activeElement;
var position = this._input.compareDocumentPosition(active);
if (position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
this.hide();
}
else {
this._input.focus();
}
} else {
this.show(true);
}
};
/**
* Even if the user has not clicked on 'Got it' in the intro, we only show it
* once per session.

View File

@ -758,6 +758,87 @@ StyleEditor.prototype = {
}
},
/**
* Decode a CSS source string to unicode according to the character set rules
* defined in <http://www.w3.org/TR/CSS2/syndata.html#charset>.
*
* @param string aString
* Source of a CSS stylesheet, loaded from file or cache.
* @param string aChannelCharset
* Charset of the source string if set by the HTTP channel.
* @return string
* The CSS string, in unicode.
*/
_decodeCSSCharset: function SE__decodeCSSCharset(aString, aChannelCharset)
{
// StyleSheet's charset can be specified from multiple sources
if (aChannelCharset.length > 0) {
// step 1 of syndata.html: charset given in HTTP header.
return this._convertToUnicode(aString, aChannelCharset);
}
let sheet = this.styleSheet;
if (sheet) {
// Do we have a @charset rule in the stylesheet?
// step 2 of syndata.html (without the BOM check).
if (sheet.cssRules) {
let rules = sheet.cssRules;
if (rules.length
&& rules.item(0).type == Ci.nsIDOMCSSRule.CHARSET_RULE) {
return this._convertToUnicode(aString, rules.item(0).encoding);
}
}
if (sheet.ownerNode) {
// step 3: see <link charset="…">
let linkCharset = sheet.ownerNode.getAttribute("charset");
if (linkCharset != null) {
return this._convertToUnicode(aString, linkCharset);
}
}
// step 4 (1 of 2): charset of referring stylesheet.
let parentSheet = sheet.parentStyleSheet;
if (parentSheet && parentSheet.cssRules &&
parentSheet.cssRules[0].type == Ci.nsIDOMCSSRule.CHARSET_RULE) {
return this._convertToUnicode(aString,
parentSheet.cssRules[0].encoding);
}
// step 4 (2 of 2): charset of referring document.
if (sheet.ownerNode && sheet.ownerNode.ownerDocument.characterSet) {
return this._convertToUnicode(aString,
sheet.ownerNode.ownerDocument.characterSet);
}
}
// step 5: default to utf-8.
return this._convertToUnicode(aString, "UTF-8");
},
/**
* Convert a given string, encoded in a given character set, to unicode.
* @param string aString
* A string.
* @param string aCharset
* A character set.
* @return string
* A unicode string.
*/
_convertToUnicode: function SE__convertToUnicode(aString, aCharset) {
// Decoding primitives.
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
try {
converter.charset = aCharset;
return converter.ConvertToUnicode(aString);
} catch(e) {
return aString;
}
},
/**
* Load source from a file or file-like resource.
*
@ -790,6 +871,7 @@ StyleEditor.prototype = {
{
let channel = Services.io.newChannel(aHref, null, null);
let chunks = [];
let channelCharset = "";
let streamListener = { // nsIStreamListener inherits nsIRequestObserver
onStartRequest: function (aRequest, aContext, aStatusCode) {
if (!Components.isSuccessCode(aStatusCode)) {
@ -797,6 +879,10 @@ StyleEditor.prototype = {
}
}.bind(this),
onDataAvailable: function (aRequest, aContext, aStream, aOffset, aCount) {
let channel = aRequest.QueryInterface(Ci.nsIChannel);
if (!channelCharset) {
channelCharset = channel.contentCharset;
}
chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
},
onStopRequest: function (aRequest, aContext, aStatusCode) {
@ -804,7 +890,7 @@ StyleEditor.prototype = {
return this._signalError(LOAD_ERROR);
}
this._onSourceLoad(chunks.join(""));
this._onSourceLoad(chunks.join(""), channelCharset);
}.bind(this)
};
@ -816,9 +902,14 @@ StyleEditor.prototype = {
* Called when source has been loaded.
*
* @param string aSourceText
* @param string aCharset
* Optional. The character set to use. The default is to detect the
* character set following the standard (see
* <http://www.w3.org/TR/CSS2/syndata.html#charset>).
*/
_onSourceLoad: function SE__onSourceLoad(aSourceText)
_onSourceLoad: function SE__onSourceLoad(aSourceText, aCharset)
{
aSourceText = this._decodeCSSCharset(aSourceText, aCharset || "");
this._restoreExpando();
this._state.text = prettifyCSS(aSourceText);
this._loaded = true;

View File

@ -71,6 +71,10 @@ function testEditorAdded(aChrome, aEditor)
function testFirstStyleSheetEditor(aChrome, aEditor)
{
// Note: the html <link> contains charset="UTF-8".
ok(aEditor._state.text.indexOf("\u263a") >= 0,
"stylesheet is unicode-aware.");
//testing TESTCASE's simple.css stylesheet
is(aEditor.styleSheetIndex, 0,
"first stylesheet is at index 0");

View File

@ -1,6 +1,7 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* ☺ */
body {
margin: 0;

View File

@ -2,7 +2,7 @@
<html>
<head>
<title>simple testcase</title>
<link rel="stylesheet" type="text/css" media="screen" href="simple.css"/>
<link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="simple.css"/>
<style type="text/css">
body {
background: white;

View File

@ -7,7 +7,7 @@ let doc;
let contentWindow;
let tempScope = {};
Cu.import("resource:///modules/Services.jsm", tempScope);
Cu.import("resource://gre/modules/Services.jsm", tempScope);
let Services = tempScope.Services;
function createDocument()

View File

@ -6,7 +6,7 @@
let tempScope = {};
Cu.import("resource:///modules/devtools/CssLogic.jsm", tempScope);
Cu.import("resource:///modules/devtools/CssHtmlTree.jsm", tempScope);
Cu.import("resource://gre/modules/HUDService.jsm", tempScope);
Cu.import("resource:///modules/HUDService.jsm", tempScope);
let HUDService = tempScope.HUDService;
let ConsoleUtils = tempScope.ConsoleUtils;
let CssLogic = tempScope.CssLogic;

View File

@ -48,12 +48,14 @@ function testMenuFilterButton(aCategory) {
menuItem = firstMenuItem;
let prefKey;
while (menuItem) {
prefKey = menuItem.getAttribute("prefKey");
chooseMenuItem(menuItem);
ok(isChecked(menuItem), "menu item " + prefKey + " for category " +
aCategory + " is checked after clicking it");
ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
"on after clicking the appropriate menu item");
if (menuItem.hasAttribute("prefKey")) {
prefKey = menuItem.getAttribute("prefKey");
chooseMenuItem(menuItem);
ok(isChecked(menuItem), "menu item " + prefKey + " for category " +
aCategory + " is checked after clicking it");
ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
"on after clicking the appropriate menu item");
}
menuItem = menuItem.nextSibling;
}
ok(isChecked(button), "the button for category " + aCategory + " is " +
@ -103,11 +105,13 @@ function testMenuFilterButton(aCategory) {
menuItem = firstMenuItem;
while (menuItem) {
let prefKey = menuItem.getAttribute("prefKey");
ok(isChecked(menuItem), "menu item " + prefKey + " for category " +
aCategory + " is checked after clicking the button");
ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
"on after clicking the button");
if (menuItem.hasAttribute("prefKey")) {
let prefKey = menuItem.getAttribute("prefKey");
ok(isChecked(menuItem), "menu item " + prefKey + " for category " +
aCategory + " is checked after clicking the button");
ok(hud.ui.filterPrefs[prefKey], prefKey + " messages are " +
"on after clicking the button");
}
menuItem = menuItem.nextSibling;
}

View File

@ -8,7 +8,7 @@
*
* ***** END LICENSE BLOCK ***** */
let menuitems = [], menupopups = [], huds = [], tabs = [];
let menuitems = [], menupopups = [], huds = [], tabs = [], runCount = 0;
function test()
{
@ -43,13 +43,18 @@ function test()
function startTest()
{
// Find the relevant elements in the Web Console of tab 2.
let win2 = tabs[1].linkedBrowser.contentWindow;
let win2 = tabs[runCount*2 + 1].linkedBrowser.contentWindow;
let hudId2 = HUDService.getHudIdByWindow(win2);
huds[1] = HUDService.hudReferences[hudId2];
HUDService.disableAnimation(hudId2);
menuitems[1] = huds[1].ui.rootElement.querySelector("#saveBodies");
menupopups[1] = huds[1].ui.rootElement.querySelector("menupopup");
if (runCount == 0) {
menuitems[1] = huds[1].ui.rootElement.querySelector("#saveBodies");
}
else {
menuitems[1] = huds[1].ui.rootElement.querySelector("#saveBodiesContextMenu");
}
menupopups[1] = menuitems[1].parentNode;
// Open the context menu from tab 2.
menupopups[1].addEventListener("popupshown", onpopupshown2, false);
@ -95,10 +100,10 @@ function onpopupshown2b(aEvent)
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
// Switch to tab 1 and open the Web Console context menu from there.
gBrowser.selectedTab = tabs[0];
gBrowser.selectedTab = tabs[runCount*2];
waitForFocus(function() {
// Find the relevant elements in the Web Console of tab 1.
let win1 = tabs[0].linkedBrowser.contentWindow;
let win1 = tabs[runCount*2].linkedBrowser.contentWindow;
let hudId1 = HUDService.getHudIdByWindow(win1);
huds[0] = HUDService.hudReferences[hudId1];
HUDService.disableAnimation(hudId1);
@ -111,7 +116,7 @@ function onpopupshown2b(aEvent)
menupopups[0].addEventListener("popupshown", onpopupshown1, false);
menupopups[0].openPopup();
}, tabs[0].linkedBrowser.contentWindow);
}, tabs[runCount*2].linkedBrowser.contentWindow);
}, false);
executeSoon(function() {
@ -134,12 +139,12 @@ function onpopupshown1(aEvent)
menupopups[0].addEventListener("popuphidden", function _onhidden(aEvent) {
menupopups[0].removeEventListener(aEvent.type, _onhidden, false);
gBrowser.selectedTab = tabs[1];
gBrowser.selectedTab = tabs[runCount*2 + 1];
waitForFocus(function() {
// Reopen the context menu from tab 2.
menupopups[1].addEventListener("popupshown", onpopupshown2c, false);
menupopups[1].openPopup();
}, tabs[1].linkedBrowser.contentWindow);
}, tabs[runCount*2 + 1].linkedBrowser.contentWindow);
}, false);
executeSoon(function() {
@ -156,12 +161,25 @@ function onpopupshown2c(aEvent)
menupopups[1].addEventListener("popuphidden", function _onhidden(aEvent) {
menupopups[1].removeEventListener(aEvent.type, _onhidden, false);
// Done!
huds = menuitems = menupopups = tabs = null;
// Done if on second run
closeConsole(gBrowser.selectedTab, function() {
gBrowser.removeCurrentTab();
executeSoon(finishTest);
if (runCount == 0) {
runCount++;
executeSoon(test);
}
else {
gBrowser.removeCurrentTab();
gBrowser.selectedTab = tabs[2];
gBrowser.removeCurrentTab();
gBrowser.selectedTab = tabs[1];
gBrowser.removeCurrentTab();
gBrowser.selectedTab = tabs[0];
gBrowser.removeCurrentTab();
huds = menuitems = menupopups = tabs = null;
executeSoon(finishTest);
}
});
}, false);
executeSoon(function() {

View File

@ -343,11 +343,30 @@ WebConsoleFrame.prototype = {
this.saveRequestAndResponseBodies = !this.saveRequestAndResponseBodies;
}.bind(this));
saveBodies.setAttribute("checked", this.saveRequestAndResponseBodies);
saveBodies.disabled = !this.getFilterState("networkinfo") &&
!this.getFilterState("network");
let contextMenuId = this.outputNode.getAttribute("context");
let contextMenu = doc.getElementById(contextMenuId);
contextMenu.addEventListener("popupshowing", function() {
saveBodies.parentNode.addEventListener("popupshowing", function() {
saveBodies.setAttribute("checked", this.saveRequestAndResponseBodies);
saveBodies.disabled = !this.getFilterState("networkinfo") &&
!this.getFilterState("network");
}.bind(this));
// Remove this part when context menu entry is removed.
let saveBodiesContextMenu = doc.getElementById("saveBodiesContextMenu");
saveBodiesContextMenu.addEventListener("command", function() {
this.saveRequestAndResponseBodies = !this.saveRequestAndResponseBodies;
}.bind(this));
saveBodiesContextMenu.setAttribute("checked",
this.saveRequestAndResponseBodies);
saveBodiesContextMenu.disabled = !this.getFilterState("networkinfo") &&
!this.getFilterState("network");
saveBodiesContextMenu.parentNode.addEventListener("popupshowing", function() {
saveBodiesContextMenu.setAttribute("checked",
this.saveRequestAndResponseBodies);
saveBodiesContextMenu.disabled = !this.getFilterState("networkinfo") &&
!this.getFilterState("network");
}.bind(this));
this.closeButton = doc.getElementById("webconsole-close-button");
@ -686,13 +705,22 @@ WebConsoleFrame.prototype = {
let prefKey = target.getAttribute("prefKey");
this.setFilterState(prefKey, state);
// Disable the log response and request body if network logging is off.
if (prefKey == "networkinfo" || prefKey == "network") {
let checkState = !this.getFilterState("networkinfo") &&
!this.getFilterState("network");
this.document.getElementById("saveBodies").disabled = checkState;
this.document.getElementById("saveBodiesContextMenu").disabled = checkState;
}
// Adjust the state of the button appropriately.
let menuPopup = target.parentNode;
let someChecked = false;
let menuItem = menuPopup.firstChild;
while (menuItem) {
if (menuItem.getAttribute("checked") === "true") {
if (menuItem.hasAttribute("prefKey") &&
menuItem.getAttribute("checked") === "true") {
someChecked = true;
break;
}

View File

@ -39,7 +39,7 @@
<popupset id="mainPopupSet">
<menupopup id="output-contextmenu">
<menuitem id="saveBodies" type="checkbox" label="&saveBodies.label;"
<menuitem id="saveBodiesContextMenu" type="checkbox" label="&saveBodies.label;"
accesskey="&saveBodies.accesskey;"/>
<menuitem id="menu_copy"/>
<menuitem id="menu_selectAll"/>
@ -63,6 +63,9 @@
prefKey="network"/>
<menuitem label="&btnConsoleLog;" type="checkbox" autocheck="false"
prefKey="networkinfo"/>
<menuseparator id="saveBodiesSeparator" />
<menuitem id="saveBodies" type="checkbox" label="&saveBodies.label;"
accesskey="&saveBodies.accesskey;"/>
</menupopup>
</toolbarbutton>
<toolbarbutton label="&btnPageCSS.label;" type="menu-button"

View File

@ -36,6 +36,9 @@
<!ENTITY openRecentMenu.label "Open Recent">
<!ENTITY openRecentMenu.accesskey "R">
<!ENTITY revertCmd.label "Revert…">
<!ENTITY revertCmd.accesskey "t">
<!ENTITY saveFileCmd.label "Save">
<!ENTITY saveFileCmd.accesskey "S">
<!ENTITY saveFileCmd.commandkey "s">

View File

@ -54,6 +54,14 @@ confirmClose=Do you want to save the changes you made to this scratchpad?
# you try to close a scratchpad with unsaved changes.
confirmClose.title=Unsaved Changes
# LOCALIZATION NOTE (confirmRevert): This is message in the prompt dialog when
# you try to revert unsaved content of scratchpad.
confirmRevert=Do you want to revert the changes you made to this scratchpad?
# LOCALIZATION NOTE (confirmRevert.title): This is title of the prompt dialog when
# you try to revert unsaved content of scratchpad.
confirmRevert.title=Revert Changes
# LOCALIZATION NOTE (scratchpadIntro): This is a multi-line comment explaining
# how to use the Scratchpad. Note that this should be a valid JavaScript
# comment inside /* and */.

View File

@ -2488,8 +2488,7 @@ html|*#gcli-output-frame {
/* Responsive Mode */
.browserContainer[responsivemode] {
background: #2a3643 url("chrome://browser/skin/devtools/responsive-background.png");
box-shadow: 0 0 7px black inset;
background: #222 url("chrome://browser/skin/devtools/responsive-background.png");
padding: 0 20px 20px 20px;
}
@ -2714,6 +2713,10 @@ html|*#gcli-output-frame {
text-decoration: underline;
}
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
.chat-status-icon {
max-height: 16px;
max-width: 16px;
@ -2733,44 +2736,26 @@ html|*#gcli-output-frame {
}
.chat-close-button {
list-style-image: url("chrome://global/skin/icons/close.png");
-moz-image-region: rect(0, 16px, 16px, 0);
}
.chat-close-button:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
list-style-image: url('chrome://browser/skin/social/chat-close.png');
-moz-image-region: rect(0, 14px, 14px, 0);
}
.chat-close-button:hover:active {
-moz-image-region: rect(0, 48px, 16px, 32px);
-moz-image-region: rect(14px, 14px, 28px, 0);
}
.chat-toggle-button {
/* XXX get a real image for this */
list-style-image: url("chrome://global/skin/icons/checkbox.png");
-moz-image-region: rect(0, 32px, 16px, 16px);
}
.chat-toggle-button:hover {
-moz-image-region: rect(0, 16px, 16px, 0);
}
.chat-toggle-button[minimized="true"] {
-moz-image-region: rect(0, 16px, 16px, 0);
}
.chat-toggle-button[minimized="true"]:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
.chat-close-button:hover {
-moz-image-region: rect(28px, 14px, 42px, 0);
}
.chat-title {
font-weight: bold;
color: -moz-dialogtext;
cursor: inherit;
}
.chat-titlebar {
background-image: linear-gradient(white, #ddd);
background-color: #d9d9d9;
height: 20px;
min-height: 20px;
width: 100%;
@ -2778,12 +2763,17 @@ html|*#gcli-output-frame {
padding: 2px;
border: none;
border-bottom: 1px solid gray;
cursor: pointer;
}
.chat-titlebar[minimized="true"] {
border-bottom: none;
}
.chat-titlebar[selected] {
background-color: #f0f0f0;
}
.chat-frame {
padding: 0;
margin: 0;
@ -2791,7 +2781,7 @@ html|*#gcli-output-frame {
}
.chatbar-button {
/* XXX get a real image for this */
background-color: #d9d9d9;
list-style-image: url("chrome://browser/skin/social/social.png");
border: none;
margin: 0;
@ -2804,6 +2794,7 @@ html|*#gcli-output-frame {
.chatbar-button[open="true"],
.chatbar-button:active:hover {
background-color: #f0f0f0;
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
}

View File

@ -85,6 +85,8 @@ browser.jar:
skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
skin/classic/browser/preferences/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/social.png (social/social.png)
skin/classic/browser/social/chat-close.png (social/chat-close.png)
skin/classic/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png)
skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)
skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -3206,8 +3206,7 @@ html|*#gcli-output-frame {
/* Responsive Mode */
.browserContainer[responsivemode] {
background: #2a3643 url("chrome://browser/skin/devtools/responsive-background.png");
box-shadow: 0 0 7px black inset;
background: #222 url("chrome://browser/skin/devtools/responsive-background.png");
padding: 0 20px 20px 20px;
}
@ -3398,6 +3397,15 @@ html|*#gcli-output-frame {
text-decoration: underline;
}
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#social-notification-box,
.social-panel-frame {
border-radius: inherit;
}
/* === end of social toolbar provider menu === */
.chat-status-icon {
@ -3419,44 +3427,26 @@ html|*#gcli-output-frame {
}
.chat-close-button {
list-style-image: url("chrome://global/skin/icons/close.png");
-moz-image-region: rect(0, 16px, 16px, 0);
}
.chat-close-button:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
list-style-image: url('chrome://browser/skin/social/chat-close.png');
-moz-image-region: rect(0, 14px, 14px, 0);
}
.chat-close-button:hover:active {
-moz-image-region: rect(0, 48px, 16px, 32px);
-moz-image-region: rect(14px, 14px, 28px, 0);
}
.chat-toggle-button {
/* XXX get a real image for this */
list-style-image: url("chrome://global/skin/icons/checkbox.png");
-moz-image-region: rect(0, 32px, 16px, 16px);
}
.chat-toggle-button:hover {
-moz-image-region: rect(0, 16px, 16px, 0);
}
.chat-toggle-button[minimized="true"] {
-moz-image-region: rect(0, 16px, 16px, 0);
}
.chat-toggle-button[minimized="true"]:hover {
-moz-image-region: rect(0, 32px, 16px, 16px);
.chat-close-button:hover {
-moz-image-region: rect(28px, 14px, 42px, 0);
}
.chat-title {
font-weight: bold;
color: -moz-dialogtext;
cursor: inherit;
}
.chat-titlebar {
background-image: linear-gradient(white, #ddd);
background-color: #d9d9d9;
height: 20px;
min-height: 20px;
width: 100%;
@ -3464,12 +3454,17 @@ html|*#gcli-output-frame {
padding: 2px;
border: none;
border-bottom: 1px solid #404040;
cursor: pointer;
}
.chat-titlebar[minimized="true"] {
border-bottom: none;
}
.chat-titlebar[selected] {
background-color: #f0f0f0;
}
.chat-frame {
padding: 0;
margin: 0;
@ -3477,8 +3472,7 @@ html|*#gcli-output-frame {
}
.chatbar-button {
/* XXX get a real image for this */
background-image: linear-gradient(white, #ddd);
background-color: #d9d9d9;
list-style-image: url("chrome://browser/skin/social/social.png");
border: none;
margin: 0;
@ -3491,6 +3485,7 @@ html|*#gcli-output-frame {
.chatbar-button[open="true"],
.chatbar-button:active:hover {
background-color: #f0f0f0;
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
}

View File

@ -108,6 +108,7 @@ browser.jar:
skin/classic/browser/preferences/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/social.png (social/social.png)
skin/classic/browser/social/chat-close.png (social/chat-close.png)
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png (tabbrowser/alltabs-box-bkgnd-icon.png)
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

View File

@ -3168,8 +3168,7 @@ html|*#gcli-output-frame {
/* Responsive Mode */
.browserContainer[responsivemode] {
background: #2a3643 url("chrome://browser/skin/devtools/responsive-background.png");
box-shadow: 0 0 7px black inset;
background: #222 url("chrome://browser/skin/devtools/responsive-background.png");
padding: 0 20px 20px 20px;
}
@ -3417,6 +3416,15 @@ html|*#gcli-output-frame {
text-decoration: underline;
}
.social-panel > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
#social-notification-box,
.social-panel-frame {
border-radius: inherit;
}
.chat-status-icon {
max-height: 16px;
max-width: 16px;
@ -3436,43 +3444,26 @@ html|*#gcli-output-frame {
}
.chat-close-button {
list-style-image: url("chrome://global/skin/icons/Close.gif");
padding: 2px 4px;
}
.chat-close-button:hover {
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
list-style-image: url('chrome://browser/skin/social/chat-close.png');
-moz-image-region: rect(0, 14px, 14px, 0);
}
.chat-close-button:hover:active {
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
-moz-image-region: rect(14px, 14px, 28px, 0);
}
.chat-toggle-button {
/* XXX get a real image for this */
list-style-image: url("chrome://global/skin/icons/expand.png");
}
.chat-toggle-button:hover {
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
}
.chat-toggle-button[minimized="true"] {
list-style-image: url("chrome://global/skin/icons/collapse.png");
}
.chat-toggle-button[minimized="true"]:hover {
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
.chat-close-button:hover {
-moz-image-region: rect(28px, 14px, 42px, 0);
}
.chat-title {
font-weight: bold;
color: -moz-dialogtext;
cursor: inherit;
}
.chat-titlebar {
background-image: linear-gradient(white, #ddd);
background-color: #c4cfde;
height: 20px;
min-height: 20px;
width: 100%;
@ -3480,12 +3471,17 @@ html|*#gcli-output-frame {
padding: 2px;
border: none;
border-bottom: 1px solid gray;
cursor: pointer;
}
.chat-titlebar[minimized="true"] {
border-bottom: none;
}
.chat-titlebar[selected] {
background-color: #dae3f0;
}
.chat-frame {
padding: 0;
margin: 0;
@ -3496,7 +3492,7 @@ html|*#gcli-output-frame {
/* XXX get a real image for this */
-moz-appearance: none;
list-style-image: url("chrome://browser/skin/social/social.png");
background-image: linear-gradient(white, #ddd);
background-color: #c4cfde;
border: none;
margin: 0;
padding: 2px;
@ -3515,6 +3511,7 @@ html|*#gcli-output-frame {
.chatbar-button[open="true"],
.chatbar-button:hover,
.chatbar-button:active:hover {
background-color: #dae3f0;
box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
}

View File

@ -105,6 +105,7 @@ browser.jar:
skin/classic/browser/preferences/applications.css (preferences/applications.css)
skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/browser/social/social.png (social/social.png)
skin/classic/browser/social/chat-close.png (social/chat-close.png)
skin/classic/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png)
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
@ -307,6 +308,7 @@ browser.jar:
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)
skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
skin/classic/aero/browser/social/social.png (social/social.png)
skin/classic/aero/browser/social/chat-close.png (social/chat-close.png)
skin/classic/aero/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png)
skin/classic/aero/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
skin/classic/aero/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

View File

@ -34,17 +34,13 @@ case "$target" in
fi
;;
*-darwin*)
# we prefer gcc-4.2 over gcc on older darwin, so
# use that specific version if it's available.
# On newer versions of darwin, gcc is llvm-gcc while gcc-4.2 is the plain
# one, so we also try that first. If that fails, we fall back to clang
# as llvm-gcc is an unsupported dead end.
MOZ_PATH_PROGS(CC, $CC gcc-4.2 clang gcc)
MOZ_PATH_PROGS(CXX, $CXX g++-4.2 clang++ g++)
IS_LLVM_GCC=$($CC -v 2>&1 | grep llvm-gcc)
if test -n "$IS_LLVM_GCC"
# GCC on darwin is based on gcc 4.2 and we don't support it anymore.
MOZ_PATH_PROGS(CC, $CC clang)
MOZ_PATH_PROGS(CXX, $CXX clang++)
IS_GCC=$($CC -v 2>&1 | grep gcc)
if test -n "$IS_GCC"
then
echo llvm-gcc is known to be broken, please use gcc-4.2 or clang.
echo gcc is known to be broken on OS X, please use clang.
exit 1
fi
;;

View File

@ -1,56 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import devicemanager
import sys
import os
def copy(dm, gre_path):
file = sys.argv[2]
if len(sys.argv) >= 4:
path = sys.argv[3]
else:
path = gre_path
if os.path.isdir(file):
dm.pushDir(file, path.replace('\\','/'))
else:
dm.pushFile(file, path.replace('\\','/'))
def delete(dm, gre_path):
file = sys.argv[2]
dm.removeFile(file)
def main():
ip_addr = os.environ.get("DEVICE_IP")
port = os.environ.get("DEVICE_PORT")
gre_path = os.environ.get("REMOTE_GRE_PATH").replace('\\','/')
if ip_addr == None:
print "Error: please define the environment variable DEVICE_IP before running this test"
sys.exit(1)
if port == None:
print "Error: please define the environment variable DEVICE_PORT before running this test"
sys.exit(1)
if gre_path == None:
print "Error: please define the environment variable REMOTE_GRE_PATH before running this test"
sys.exit(1)
dm = devicemanager.DeviceManager(ip_addr, int(port))
dm.sendCMD(['cd '+ gre_path], sleep = 1)
dm.debug = 0
if len(sys.argv) < 3:
print "usage: python devicemanager-utils.py <cmd> <path> [arg]"
cmd = sys.argv[1]
if (cmd == 'copy'):
sys.exit(copy(dm, gre_path))
if (cmd == 'delete'):
sys.exit(delete(dm, gre_path))
print "unrecognized command. supported commands are copy and delete"
sys.exit(-1)
if __name__ == '__main__':
main()

View File

@ -17,8 +17,7 @@
</activity>
<receiver android:name=".SUTStartupIntentReceiver">
<intent-filter>
<action android:value="android.intent.action.BOOT_COMPLETED" android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:value="android.intent.category.HOME" android:name="android.intent.category.HOME"/>
<action android:name="android.intent.action.MEDIA_MOUNTED"></action>
</intent-filter>
</receiver>
<service android:name=".service.ASMozStub">
@ -58,4 +57,4 @@
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"></uses-permission>
</manifest>
</manifest>

View File

@ -191,9 +191,15 @@ public class WatcherService extends Service
private void handleCommand(Intent intent)
{
String sCmd = intent.getStringExtra("command");
// Note: intent can be null "if the service is being restarted after its process
// has gone away". In this case, we will consider that to be equivalent to a start
// http://developer.android.com/reference/android/app/Service.html#onStartCommand%28android.content.Intent,%20int,%20int%29
// Debug.waitForDebugger();
String sCmd = "start";
if (intent != null)
{
sCmd = intent.getStringExtra("command");
}
if (sCmd != null)
{

View File

@ -264,8 +264,8 @@ class PythonJob(Job):
pass # sys.exit(0) is not a failure
else:
print >>sys.stderr, e
print >>sys.stderr, traceback.print_exc()
return (e.code if isinstance(e.code, int) else 1)
traceback.print_exc()
return -127
finally:
os.environ.clear()
os.environ.update(oldenv)

View File

@ -0,0 +1,9 @@
#T gmake skip
#T returncode: 2
#T grep-for: "Exception: info-exception"
CMD = %pycmd asplode_raise
PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
all:
@$(CMD) info-exception

View File

@ -30,3 +30,6 @@ def asplode(args):
def asplode_return(args):
arg0 = convertasplode(args[0])
return arg0
def asplode_raise(args):
raise Exception(args[0])

View File

@ -392,7 +392,7 @@ private:
static JSBool
CheckObjectAccess(JSContext *cx, JSHandleObject obj,
JSHandleId id, JSAccessMode mode,
jsval *vp);
JSMutableHandleValue vp);
// Decides, based on CSP, whether or not eval() and stuff can be executed.
static JSBool

View File

@ -532,7 +532,7 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
JSBool
nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSHandleObject obj,
JSHandleId id, JSAccessMode mode,
jsval *vp)
JSMutableHandleValue vp)
{
// Get the security manager
nsScriptSecurityManager *ssm =
@ -548,9 +548,9 @@ nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSHandleObject obj,
// a different trust domain.
// 2. A user-defined getter or setter function accessible on another
// trust domain's window or document object.
// *vp can be a primitive, in that case, we use obj as the target
// vp can be a primitive, in that case, we use obj as the target
// object.
JSObject* target = JSVAL_IS_PRIMITIVE(*vp) ? obj : JSVAL_TO_OBJECT(*vp);
JSObject* target = JSVAL_IS_PRIMITIVE(vp) ? obj : JSVAL_TO_OBJECT(vp);
// Do the same-origin check -- this sets a JS exception if the check fails.
// Pass the parent object's class name, as we have no class-info for it.

View File

@ -86,9 +86,9 @@ nsChromeRegistry::LogMessageWithContext(nsIURI* aURL, uint32_t aLineNumber, uint
if (aURL)
aURL->GetSpec(spec);
rv = error->Init(NS_ConvertUTF8toUTF16(formatted).get(),
NS_ConvertUTF8toUTF16(spec).get(),
nullptr,
rv = error->Init(NS_ConvertUTF8toUTF16(formatted),
NS_ConvertUTF8toUTF16(spec),
EmptyString(),
aLineNumber, 0, flags, "chrome registration");
PR_smprintf_free(formatted);

View File

@ -152,6 +152,11 @@ if test -z "$PERL" -o "$PERL" = ":"; then
AC_MSG_ERROR([perl not found in \$PATH])
fi
AC_SUBST(GAIADIR)
if test -n "$GAIADIR" ; then
AC_DEFINE(PACKAGE_GAIA)
fi
MOZ_ARG_WITH_STRING(gonk,
[ --with-gonk=DIR
location of gonk dir],

View File

@ -688,7 +688,7 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
bool hasPrefetch = linkTypes & PREFETCH;
// prefetch href if relation is "next" or "prefetch"
if (hasPrefetch || (linkTypes & NEXT)) {
PrefetchHref(aHref, nullptr, hasPrefetch);
PrefetchHref(aHref, mDocument, hasPrefetch);
}
if (!aHref.IsEmpty() && (linkTypes & DNS_PREFETCH)) {
@ -795,7 +795,7 @@ nsContentSink::ProcessMETATag(nsIContent* aContent)
void
nsContentSink::PrefetchHref(const nsAString &aHref,
nsIContent *aSource,
nsINode *aSource,
bool aExplicit)
{
//

View File

@ -159,7 +159,7 @@ protected:
const nsSubstring& aType,
const nsSubstring& aMedia);
void PrefetchHref(const nsAString &aHref, nsIContent *aSource,
void PrefetchHref(const nsAString &aHref, nsINode *aSource,
bool aExplicit);
// aHref can either be the usual URI format or of the form "//www.hostname.com"

View File

@ -3260,9 +3260,9 @@ nsContentUtils::ReportToConsole(uint32_t aErrorFlags,
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = errorObject->InitWithWindowID(errorText.get(),
NS_ConvertUTF8toUTF16(spec).get(), // file name
aSourceLine.get(),
rv = errorObject->InitWithWindowID(errorText,
NS_ConvertUTF8toUTF16(spec), // file name
aSourceLine,
aLineNumber, aColumnNumber,
aErrorFlags, aCategory,
innerWindowID);

View File

@ -1093,9 +1093,9 @@ nsEventSource::PrintErrorOnConsole(const char *aBundleURI,
}
NS_ENSURE_SUCCESS(rv, rv);
rv = errObj->InitWithWindowID(message.get(),
mScriptFile.get(),
nullptr,
rv = errObj->InitWithWindowID(message,
mScriptFile,
EmptyString(),
mScriptLine, 0,
nsIScriptError::errorFlag,
"Event Source", mInnerWindowID);

View File

@ -683,10 +683,10 @@ ContentScriptErrorReporter(JSContext* aCx,
if (aReport) {
if (aReport->ucmessage) {
message.Assign(reinterpret_cast<const PRUnichar*>(aReport->ucmessage));
message.Assign(static_cast<const PRUnichar*>(aReport->ucmessage));
}
filename.AssignWithConversion(aReport->filename);
line.Assign(reinterpret_cast<const PRUnichar*>(aReport->uclinebuf));
line.Assign(static_cast<const PRUnichar*>(aReport->uclinebuf));
lineNumber = aReport->lineno;
columnNumber = aReport->uctokenptr - aReport->uclinebuf;
flags = aReport->flags;
@ -700,7 +700,7 @@ ContentScriptErrorReporter(JSContext* aCx,
message.AssignWithConversion(aMessage);
}
rv = scriptError->Init(message.get(), filename.get(), line.get(),
rv = scriptError->Init(message, filename, line,
lineNumber, columnNumber, flags,
"Message manager content script");
if (NS_FAILED(rv)) {
@ -731,7 +731,7 @@ ContentScriptErrorReporter(JSContext* aCx,
error.AppendInt(lineNumber, 10);
error.Append(": ");
if (aReport->ucmessage) {
AppendUTF16toUTF8(reinterpret_cast<const PRUnichar*>(aReport->ucmessage),
AppendUTF16toUTF8(static_cast<const PRUnichar*>(aReport->ucmessage),
error);
} else {
error.Append(aMessage);

View File

@ -1822,6 +1822,7 @@ GK_ATOM(svgTextFrame2, "SVGTextFrame2")
GK_ATOM(svgTextPathFrame, "SVGTextPathFrame")
GK_ATOM(svgTSpanFrame, "SVGTSpanFrame")
GK_ATOM(svgUseFrame, "SVGUseFrame")
GK_ATOM(svgViewFrame, "SVGViewFrame")
GK_ATOM(HTMLVideoFrame, "VideoFrame")
GK_ATOM(onloadend, "onloadend")
GK_ATOM(onloadstart, "onloadstart")

View File

@ -24,6 +24,7 @@
#define nsPropertyTable_h_
#include "nscore.h"
#include "prtypes.h"
class nsIAtom;
typedef PRUptrdiff PtrBits;

View File

@ -130,9 +130,9 @@ nsWebSocket::PrintErrorOnConsole(const char *aBundleURI,
}
NS_ENSURE_SUCCESS(rv, rv);
rv = errorObject->InitWithWindowID(message.get(),
NS_ConvertUTF8toUTF16(mScriptFile).get(),
nullptr, mScriptLine, 0,
rv = errorObject->InitWithWindowID(message,
NS_ConvertUTF8toUTF16(mScriptFile),
EmptyString(), mScriptLine, 0,
nsIScriptError::errorFlag, "Web Socket",
mInnerWindowID);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -350,7 +350,8 @@ nsXMLHttpRequest::nsXMLHttpRequest()
mFirstStartRequestSeen(false),
mInLoadProgressEvent(false),
mResultJSON(JSVAL_VOID),
mResultArrayBuffer(nullptr)
mResultArrayBuffer(nullptr),
mXPCOMifier(nullptr)
{
nsLayoutStatics::AddRef();
@ -3695,13 +3696,11 @@ nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
// need to see these notifications for proper functioning.
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
mChannelEventSink = do_GetInterface(mNotificationCallbacks);
*aResult = static_cast<nsIChannelEventSink*>(this);
NS_ADDREF_THIS();
*aResult = static_cast<nsIChannelEventSink*>(EnsureXPCOMifier().get());
return NS_OK;
} else if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
mProgressEventSink = do_GetInterface(mNotificationCallbacks);
*aResult = static_cast<nsIProgressEventSink*>(this);
NS_ADDREF_THIS();
*aResult = static_cast<nsIProgressEventSink*>(EnsureXPCOMifier().get());
return NS_OK;
}
@ -3742,7 +3741,21 @@ nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
return wwatch->GetPrompt(window, aIID,
reinterpret_cast<void**>(aResult));
}
// Now check for the various XHR non-DOM interfaces, except
// nsIProgressEventSink and nsIChannelEventSink which we already
// handled above.
else if (aIID.Equals(NS_GET_IID(nsIStreamListener))) {
*aResult = static_cast<nsIStreamListener*>(EnsureXPCOMifier().get());
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsIRequestObserver))) {
*aResult = static_cast<nsIRequestObserver*>(EnsureXPCOMifier().get());
return NS_OK;
}
else if (aIID.Equals(NS_GET_IID(nsITimerCallback))) {
*aResult = static_cast<nsITimerCallback*>(EnsureXPCOMifier().get());
return NS_OK;
}
return QueryInterface(aIID, aResult);
@ -3860,6 +3873,16 @@ nsXMLHttpRequest::StartProgressEventTimer()
}
}
already_AddRefed<nsXMLHttpRequestXPCOMifier>
nsXMLHttpRequest::EnsureXPCOMifier()
{
if (!mXPCOMifier) {
mXPCOMifier = new nsXMLHttpRequestXPCOMifier(this);
}
nsRefPtr<nsXMLHttpRequestXPCOMifier> newRef(mXPCOMifier);
return newRef.forget();
}
NS_IMPL_ISUPPORTS1(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
NS_IMETHODIMP nsXMLHttpRequest::
@ -3957,3 +3980,47 @@ NS_IMETHODIMP nsXMLHttpProgressEvent::GetTotalSize(uint32_t *aTotalSize)
LL_L2UI(*aTotalSize, mMaxProgress);
return NS_OK;
}
// nsXMLHttpRequestXPCOMifier implementation
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpRequestXPCOMifier)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXMLHttpRequestXPCOMifier)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXMLHttpRequestXPCOMifier)
// Can't NS_IMPL_CYCLE_COLLECTION_1 because mXHR has ambiguous
// inheritance from nsISupports.
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestXPCOMifier)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequestXPCOMifier)
if (tmp->mXHR) {
tmp->mXHR->mXPCOMifier = nullptr;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXHR)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequestXPCOMifier)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mXHR, nsIXMLHttpRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMETHODIMP
nsXMLHttpRequestXPCOMifier::GetInterface(const nsIID & aIID, void **aResult)
{
// Return ourselves for the things we implement (except
// nsIInterfaceRequestor) and the XHR for the rest.
if (!aIID.Equals(NS_GET_IID(nsIInterfaceRequestor))) {
nsresult rv = QueryInterface(aIID, aResult);
if (NS_SUCCEEDED(rv)) {
return rv;
}
}
return mXHR->GetInterface(aIID, aResult);
}

View File

@ -114,6 +114,10 @@ public:
}
};
class nsXMLHttpRequestXPCOMifier;
// Make sure that any non-DOM interfaces added here are also added to
// nsXMLHttpRequestXPCOMifier.
class nsXMLHttpRequest : public nsXHREventTarget,
public nsIXMLHttpRequest,
public nsIJSXMLHttpRequest,
@ -126,6 +130,8 @@ class nsXMLHttpRequest : public nsXHREventTarget,
public nsITimerCallback
{
friend class nsXHRParseEndListener;
friend class nsXMLHttpRequestXPCOMifier;
public:
nsXMLHttpRequest();
virtual ~nsXMLHttpRequest();
@ -140,7 +146,7 @@ public:
return GetOwner();
}
// The WebIDL constructor.
// The WebIDL constructors.
static already_AddRefed<nsXMLHttpRequest>
Constructor(JSContext* aCx,
nsISupports* aGlobal,
@ -160,6 +166,22 @@ public:
return req.forget();
}
static already_AddRefed<nsXMLHttpRequest>
Constructor(JSContext* aCx,
nsISupports* aGlobal,
const nsAString& ignored,
ErrorResult& aRv)
{
// Pretend like someone passed null, so we can pick up the default values
mozilla::dom::MozXMLHttpRequestParameters params;
if (!params.Init(aCx, JS::NullValue())) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
return Constructor(aCx, aGlobal, params, aRv);
}
void Construct(nsIPrincipal* aPrincipal,
nsPIDOMWindow* aOwnerWindow,
nsIURI* aBaseURI = NULL)
@ -502,6 +524,8 @@ protected:
const mozilla::dom::Optional<nsAString>& user,
const mozilla::dom::Optional<nsAString>& password);
already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIChannel> mChannel;
@ -657,10 +681,49 @@ protected:
nsCString value;
};
nsTArray<RequestHeader> mModifiedRequestHeaders;
// Helper object to manage our XPCOM scriptability bits
nsXMLHttpRequestXPCOMifier* mXPCOMifier;
};
#undef IMPL_EVENT_HANDLER
// A shim class designed to expose the non-DOM interfaces of
// XMLHttpRequest via XPCOM stuff.
class nsXMLHttpRequestXPCOMifier MOZ_FINAL : public nsIStreamListener,
public nsIChannelEventSink,
public nsIProgressEventSink,
public nsIInterfaceRequestor,
public nsITimerCallback,
public nsCycleCollectionParticipant
{
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestXPCOMifier,
nsIStreamListener)
nsXMLHttpRequestXPCOMifier(nsXMLHttpRequest* aXHR) :
mXHR(aXHR)
{
}
~nsXMLHttpRequestXPCOMifier() {
if (mXHR) {
mXHR->mXPCOMifier = nullptr;
}
}
NS_FORWARD_NSISTREAMLISTENER(mXHR->)
NS_FORWARD_NSIREQUESTOBSERVER(mXHR->)
NS_FORWARD_NSICHANNELEVENTSINK(mXHR->)
NS_FORWARD_NSIPROGRESSEVENTSINK(mXHR->)
NS_FORWARD_NSITIMERCALLBACK(mXHR->)
NS_DECL_NSIINTERFACEREQUESTOR
private:
nsRefPtr<nsXMLHttpRequest> mXHR;
};
// helper class to expose a progress DOM Event
class nsXMLHttpProgressEvent : public nsIDOMProgressEvent,

View File

@ -44,6 +44,7 @@ MOCHITEST_CHROME_FILES = \
test_bug752226-4.xul \
test_bug682305.html \
test_bug780199.xul \
test_bug780529.xul \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,40 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=780529
-->
<window title="Mozilla Bug 780529"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=780529"
target="_blank">Mozilla Bug 780529</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 780529 **/
var req = new XMLHttpRequest();
req.open("GET", "", true);
// Have to call send() to get the XHR hooked up as the notification callbacks
req.send();
var callbacks = req.channel.notificationCallbacks;
var sink = callbacks.getInterface(Components.interfaces.nsIChannelEventSink);
ok(sink instanceof Components.interfaces.nsIChannelEventSink,
"Should be a channel event sink")
ok("asyncOnChannelRedirect" in sink,
"Should have the right methods for an event sink");
is(callbacks.getInterface(Components.interfaces.nsIXMLHttpRequest), req,
"Should have the right object");
sinkReq = sink.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
isnot(sinkReq, callbacks, "Sink should not be the XHR object");
is(sinkReq.getInterface(Components.interfaces.nsIXMLHttpRequest), req,
"Should have the XHR object now");
]]>
</script>
</window>

View File

@ -29,15 +29,15 @@ function runTests() {
{mozAnon: 1},
{mozAnon: []},
{get mozAnon() { return true; }},
];
let invalidParameters = [
0,
7,
Math.PI,
"string",
true,
false,
];
let invalidParameters = [
{get mozSystem() { throw "Bla"; } },
];

View File

@ -385,8 +385,6 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
// Get some prefs for some preferred/overriden things
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
bool forceOSMesa =
Preferences::GetBool("webgl.force_osmesa", false);
#ifdef XP_WIN
bool preferEGL =
Preferences::GetBool("webgl.prefer-egl", false);
@ -507,16 +505,6 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
}
#endif
// if we're forcing osmesa, do it first
if (forceOSMesa) {
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
if (!gl || !InitAndValidateGL()) {
GenerateWarning("OSMesa forced, but creating context failed -- aborting!");
return NS_ERROR_FAILURE;
}
GenerateWarning("Using software rendering via OSMesa (THIS WILL BE SLOW)");
}
#ifdef XP_WIN
// if we want EGL, try it now
if (!gl && (preferEGL || useANGLE) && !preferOpenGL) {
@ -542,19 +530,6 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
}
}
// finally, try OSMesa
if (!gl) {
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
if (gl) {
if (!InitAndValidateGL()) {
GenerateWarning("Error during OSMesa initialization");
return NS_ERROR_FAILURE;
} else {
GenerateWarning("Using software rendering via OSMesa (THIS WILL BE SLOW)");
}
}
}
if (!gl) {
GenerateWarning("Can't get a usable WebGL context");
return NS_ERROR_FAILURE;

View File

@ -125,6 +125,7 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLSharedListElement)
NS_IMPL_BOOL_ATTR(nsHTMLSharedListElement, Compact, compact)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSharedListElement, Start, start, 1)
NS_IMPL_STRING_ATTR(nsHTMLSharedListElement, Type, type)
NS_IMPL_BOOL_ATTR(nsHTMLSharedListElement, Reversed, reversed)
// Shared with nsHTMLSharedElement.cpp
nsAttrValue::EnumTable kListTypeTable[] = {

View File

@ -15,8 +15,11 @@
/** Test for HTMLOLElement attributes reflection **/
// TODO: .reversed (boolean), bug 601912
todo("reversed" in document.createElement("ol"), "reversed is not yet implemented");
// .reversed (boolean)
reflectBoolean({
element: document.createElement("ol"),
attribute: "reversed",
})
// .start
reflectInt({

View File

@ -162,8 +162,6 @@ var gSnifferTests = [
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233, size:28942 },
{ name:"seek.webm", type:"video/webm", duration:3.966, size:215529 },
{ name:"short.mp4", type:"video/mp4", duration:0.2, size:29435},
// A mp3 file without id3 tags.
{ name:"notags.mp3", type:"audio/mpeg", duration:0.28, size:2506},
// A mp3 file with id3 tags.
{ name:"id3tags.mp3", type:"audio/mpeg", duration:0.28, size:3530},
{ name:"bogus.duh", type:"bogus/duh" }

View File

@ -11,6 +11,7 @@
#include "mozilla/dom/AudioContextBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(AudioContext, mWindow)
NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioContext)
@ -34,8 +35,7 @@ JSObject*
AudioContext::WrapObject(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap)
{
return dom::mozAudioContextBinding::Wrap(aCx, aScope, this,
aTriedToWrap);
return mozAudioContextBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
/* static */ already_AddRefed<AudioContext>
@ -53,4 +53,5 @@ AudioContext::Constructor(nsISupports* aGlobal, ErrorResult& aRv)
}
}
}

View File

@ -8,6 +8,7 @@
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
#include "nsCOMPtr.h"
#include "EnableWebAudioCheck.h"
class JSContext;
class nsIDOMWindow;
@ -16,8 +17,11 @@ namespace mozilla {
class ErrorResult;
namespace dom {
class AudioContext MOZ_FINAL : public nsISupports,
public nsWrapperCache
public nsWrapperCache,
public EnableWebAudioCheck
{
explicit AudioContext(nsIDOMWindow* aParentWindow);
@ -43,4 +47,5 @@ private:
};
}
}

View File

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "EnableWebAudioCheck.h"
#include "mozilla/Preferences.h"
namespace {
bool gPrefInitialized = false;
bool gWebAudioEnabled = false;
}
namespace mozilla {
namespace dom {
/* static */ bool
EnableWebAudioCheck::PrefEnabled()
{
if (!gPrefInitialized) {
Preferences::AddBoolVarCache(&gWebAudioEnabled, "media.webaudio.enabled");
gPrefInitialized = true;
}
return gWebAudioEnabled;
}
}
}

View File

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
namespace mozilla {
namespace dom {
// This is a helper class which enables Web Audio to be enabled or disabled
// as whole. Individual Web Audio object classes should inherit from this.
class EnableWebAudioCheck {
public:
static bool PrefEnabled();
};
}
}

View File

@ -15,7 +15,8 @@ LIBRARY_NAME := gkconwebaudio_s
LIBXUL_LIBRARY := 1
CPPSRCS := \
AudioContext.cpp
AudioContext.cpp \
EnableWebAudioCheck.cpp \
$(NULL)
PARALLEL_DIRS := test

View File

@ -11,8 +11,18 @@
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(!window.mozAudioContext, "mozAudioContext should be hidden behind a pref");
var accessThrows = false;
try {
new mozAudioContext();
} catch (e) {
accessThrows = true;
}
ok(accessThrows, "mozAudioContext should be hidden behind a pref");
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
var ac = new mozAudioContext();
ok(ac, "Create a mozAudioContext object");
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
});

View File

@ -211,28 +211,18 @@ SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument *aDocument,
const nsSVGViewElement *viewElement = GetViewElement(aDocument, aAnchorName);
if (viewElement) {
if (viewElement->mViewBox.IsExplicitlySet()) {
rootElement->mViewBox.SetBaseValue(
viewElement->mViewBox.GetBaseValue(), rootElement);
} else {
RestoreOldViewBox(rootElement);
}
if (viewElement->mPreserveAspectRatio.IsExplicitlySet()) {
rootElement->mPreserveAspectRatio.SetBaseValue(
viewElement->mPreserveAspectRatio.GetBaseValue(), rootElement);
} else {
RestoreOldPreserveAspectRatio(rootElement);
}
if (viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].IsExplicitlySet()) {
rootElement->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(
viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].GetBaseValue(), rootElement);
} else {
RestoreOldZoomAndPan(rootElement);
if (!rootElement->mCurrentViewID) {
rootElement->mCurrentViewID = new nsString();
}
*rootElement->mCurrentViewID = aAnchorName;
rootElement->mUseCurrentView = true;
rootElement->InvalidateTransformNotifyFrame();
return true;
}
bool wasOverridden = !!rootElement->mCurrentViewID;
rootElement->mCurrentViewID = nullptr;
rootElement->mUseCurrentView = ProcessSVGViewSpec(aAnchorName, rootElement);
if (rootElement->mUseCurrentView) {
return true;
@ -243,5 +233,8 @@ SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument *aDocument,
rootElement->ClearPreserveAspectRatioProperty();
RestoreOldZoomAndPan(rootElement);
rootElement->ClearZoomAndPanProperty();
if (wasOverridden) {
rootElement->InvalidateTransformNotifyFrame();
}
return false;
}

View File

@ -27,6 +27,7 @@
#include "nsGUIEvent.h"
#include "nsSVGUtils.h"
#include "nsSVGSVGElement.h"
#include "nsSVGViewElement.h"
#include "nsStyleUtil.h"
#include "nsEventDispatcher.h"
@ -159,7 +160,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGSVGElementBase)
nsSVGSVGElement::nsSVGSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo,
FromParser aFromParser)
: nsSVGSVGElementBase(aNodeInfo),
mCoordCtx(nullptr),
mViewportWidth(0),
mViewportHeight(0),
mCurrentTranslate(0.0f, 0.0f),
@ -719,7 +719,14 @@ nsSVGSVGElement::GetTransformToElement(nsIDOMSVGElement *element,
NS_IMETHODIMP
nsSVGSVGElement::GetZoomAndPan(uint16_t *aZoomAndPan)
{
*aZoomAndPan = mEnumAttributes[ZOOMANDPAN].GetAnimValue();
nsSVGViewElement* viewElement = GetCurrentViewElement();
if (viewElement && viewElement->mEnumAttributes[
nsSVGViewElement::ZOOMANDPAN].IsExplicitlySet()) {
*aZoomAndPan = viewElement->mEnumAttributes[
nsSVGViewElement::ZOOMANDPAN].GetAnimValue();
} else {
*aZoomAndPan = mEnumAttributes[ZOOMANDPAN].GetAnimValue();
}
return NS_OK;
}
@ -1069,11 +1076,31 @@ nsSVGSVGElement::HasPreserveAspectRatio()
mPreserveAspectRatio.IsAnimated();
}
nsSVGViewElement*
nsSVGSVGElement::GetCurrentViewElement() const
{
if (mCurrentViewID) {
nsIDocument* doc = GetCurrentDoc();
if (doc) {
Element *element = doc->GetElementById(*mCurrentViewID);
if (element && element->Tag() == nsGkAtoms::view) {
return static_cast<nsSVGViewElement*>(element);
}
}
}
return nullptr;
}
nsSVGViewBoxRect
nsSVGSVGElement::GetViewBoxWithSynthesis(
float aViewportWidth, float aViewportHeight) const
{
if (HasViewBox()) {
// The logic here should match HasViewBox().
nsSVGViewElement* viewElement = GetCurrentViewElement();
if (viewElement && viewElement->mViewBox.IsExplicitlySet()) {
return viewElement->mViewBox.GetAnimValue();
}
if (mViewBox.IsExplicitlySet()) {
return mViewBox.GetAnimValue();
}
@ -1104,13 +1131,23 @@ nsSVGSVGElement::GetPreserveAspectRatioWithOverride() const
}
}
if (!HasViewBox() && ShouldSynthesizeViewBox()) {
nsSVGViewElement* viewElement = GetCurrentViewElement();
// This check is equivalent to "!HasViewBox() && ShouldSynthesizeViewBox()".
// We're just holding onto the viewElement that HasViewBox() would look up,
// so that we don't have to look it up again later.
if (!((viewElement && viewElement->mViewBox.IsExplicitlySet()) ||
mViewBox.IsExplicitlySet()) &&
ShouldSynthesizeViewBox()) {
// If we're synthesizing a viewBox, use preserveAspectRatio="none";
return SVGPreserveAspectRatio(
nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE,
nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE);
}
if (viewElement && viewElement->mPreserveAspectRatio.IsExplicitlySet()) {
return viewElement->mPreserveAspectRatio.GetAnimValue();
}
return mPreserveAspectRatio.GetAnimValue();
}
@ -1122,10 +1159,19 @@ nsSVGSVGElement::GetLength(uint8_t aCtxType)
{
float h, w;
if (HasViewBox()) {
const nsSVGViewBoxRect& viewbox = mViewBox.GetAnimValue();
w = viewbox.width;
h = viewbox.height;
nsSVGViewElement* viewElement = GetCurrentViewElement();
const nsSVGViewBoxRect* viewbox = nullptr;
// The logic here should match HasViewBox().
if (viewElement && viewElement->mViewBox.IsExplicitlySet()) {
viewbox = &viewElement->mViewBox.GetAnimValue();
} else if (mViewBox.IsExplicitlySet()) {
viewbox = &mViewBox.GetAnimValue();
}
if (viewbox) {
w = viewbox->width;
h = viewbox->height;
} else if (IsInner()) {
nsSVGSVGElement *ctx = GetCtx();
w = mLengthAttributes[WIDTH].GetAnimValue(ctx);
@ -1230,6 +1276,16 @@ nsSVGSVGElement::GetPreserveAspectRatio()
return &mPreserveAspectRatio;
}
bool
nsSVGSVGElement::HasViewBox() const
{
nsSVGViewElement* viewElement = GetCurrentViewElement();
if (viewElement && viewElement->mViewBox.IsExplicitlySet()) {
return true;
}
return mViewBox.IsExplicitlySet();
}
bool
nsSVGSVGElement::ShouldSynthesizeViewBox() const
{
@ -1303,7 +1359,8 @@ nsSVGSVGElement::
"should only override preserveAspectRatio in images");
#endif
if (!HasViewBox() && ShouldSynthesizeViewBox()) {
bool hasViewBox = HasViewBox();
if (!hasViewBox && ShouldSynthesizeViewBox()) {
// My non-<svg:image> clients will have been painting me with a synthesized
// viewBox, but my <svg:image> client that's about to paint me now does NOT
// want that. Need to tell ourselves to flush our transform.
@ -1311,7 +1368,7 @@ nsSVGSVGElement::
}
mIsPaintingSVGImageElement = true;
if (!HasViewBox()) {
if (!hasViewBox) {
return; // preserveAspectRatio irrelevant (only matters if we have viewBox)
}

View File

@ -179,7 +179,9 @@ public:
/**
* Returns true if this element has a base/anim value for its "viewBox"
* attribute that defines a viewBox rectangle with finite values.
* attribute that defines a viewBox rectangle with finite values, or
* if there is a view element overriding this element's viewBox and it
* has a valid viewBox.
*
* Note that this does not check whether we need to synthesize a viewBox,
* so you must call ShouldSynthesizeViewBox() if you need to check that too.
@ -187,9 +189,7 @@ public:
* Note also that this method does not pay attention to whether the width or
* height values of the viewBox rect are positive!
*/
bool HasViewBox() const {
return mViewBox.IsExplicitlySet();
}
bool HasViewBox() const;
/**
* Returns true if we should synthesize a viewBox for ourselves (that is, if
@ -233,6 +233,12 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// Returns true IFF our attributes are currently overridden by a <view>
// element and that element's ID matches the passed-in string.
bool IsOverriddenBy(const nsAString &aViewID) const {
return mCurrentViewID && mCurrentViewID->Equals(aViewID);
}
svgFloatSize GetViewportSize() const {
return svgFloatSize(mViewportWidth, mViewportHeight);
}
@ -257,6 +263,8 @@ private:
// implementation helpers:
nsSVGViewElement* GetCurrentViewElement() const;
// Methods for <image> elements to override my "PreserveAspectRatio" value.
// These are private so that only our friends (nsSVGImageFrame in
// particular) have access.
@ -343,7 +351,7 @@ private:
nsSVGViewBox mViewBox;
SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
nsSVGSVGElement *mCoordCtx;
nsAutoPtr<nsString> mCurrentViewID;
// The size of the rectangular SVG viewport into which we render. This is
// not (necessarily) the same as the content area. See:

View File

@ -27,6 +27,8 @@ class nsSVGViewElement : public nsSVGViewElementBase,
public nsIDOMSVGZoomAndPan
{
friend class mozilla::SVGFragmentIdentifier;
friend class nsSVGSVGElement;
friend class nsSVGOuterSVGFrame;
friend nsresult NS_NewSVGViewElement(nsIContent **aResult,
already_AddRefed<nsINodeInfo> aNodeInfo);
nsSVGViewElement(already_AddRefed<nsINodeInfo> aNodeInfo);

View File

@ -35,7 +35,6 @@ function runTests()
var doc = svg.contentWindow.document;
var tests = [
new Test("view", true, "0 200 100 100", "none", null),
new Test("unknown", false, null, null, null),
new Test("svgView(viewBox(0,0,200,200))", true, "0 0 200 200", null, null),
new Test("svgView(preserveAspectRatio(xMaxYMin slice))", true, null, "xMaxYMin slice", null),

View File

@ -128,7 +128,7 @@ nsXBLDocGlobalObject_setProperty(JSContext *cx, JSHandleObject obj,
static JSBool
nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSHandleObject obj, JSHandleId id,
JSAccessMode mode, jsval *vp)
JSAccessMode mode, JSMutableHandleValue vp)
{
uint32_t translated;
if (mode & JSACC_WRITE) {
@ -218,10 +218,15 @@ XBL_ProtoErrorReporter(JSContext *cx,
if (errorObject && consoleService) {
uint32_t column = report->uctokenptr - report->uclinebuf;
const PRUnichar* ucmessage =
static_cast<const PRUnichar*>(report->ucmessage);
const PRUnichar* uclinebuf =
static_cast<const PRUnichar*>(report->uclinebuf);
errorObject->Init
(reinterpret_cast<const PRUnichar*>(report->ucmessage),
NS_ConvertUTF8toUTF16(report->filename).get(),
reinterpret_cast<const PRUnichar*>(report->uclinebuf),
(ucmessage ? nsDependentString(ucmessage) : EmptyString(),
NS_ConvertUTF8toUTF16(report->filename),
uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
report->lineno, column, report->flags,
"xbl javascript"
);

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