Merge mozilla-central into services-central

This commit is contained in:
Gregory Szorc 2012-01-26 17:11:45 -08:00
Родитель 145283f217 d5c4dc2b18
Коммит 9f7ac8b038
1106 изменённых файлов: 31585 добавлений и 21446 удалений

Просмотреть файл

@ -72,3 +72,4 @@ c0983049bcaa9551e5f276d5a77ce154c151e0b0 AURORA_BASE_20110927
462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R15
54bfd8bf682e295ffd7f22fa921ca343957b6c1c AURORA_BASE_20111108
a8506ab2c65480cf2f85f54e203ea746522c62bb AURORA_BASE_20111220
462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R16

Просмотреть файл

@ -616,6 +616,9 @@ nsAccessible::VisibilityState()
} while (accessible = accessible->Parent());
nsIFrame* frame = GetFrame();
if (!frame)
return vstates;
const nsCOMPtr<nsIPresShell> shell(GetPresShell());
// We need to know if at least a kMinPixels around the object is visible,

Просмотреть файл

@ -1345,7 +1345,7 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
if (foundItemContent->GetChildCount() > 1)
return true; // Treat multiple child nodes as non-empty
nsIContent *innerItemContent = foundItemContent->GetChildAt(0);
nsIContent *innerItemContent = foundItemContent->GetFirstChild();
if (innerItemContent && !innerItemContent->TextIsOnlyWhitespace())
return true;

Просмотреть файл

@ -56,6 +56,7 @@ CMMSRCS = nsAccessNodeWrap.mm \
mozDocAccessible.mm \
mozActionElements.mm \
mozTextAccessible.mm \
mozHTMLAccessible.mm \
$(NULL)

Просмотреть файл

@ -1,4 +1,6 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -15,11 +17,12 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Hub Figuière <hub@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -35,16 +38,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXMLEncodingCID_h__
#define nsXMLEncodingCID_h__
#import "mozAccessible.h"
#include "nscore.h"
@interface mozHeadingAccessible : mozAccessible
#define NS_XML_ENCODING_CONTRACTID "@mozilla.org/intl/xmlencoding;1"
// {12BB8F16-2389-11d3-B3BF-00805F8A6670}
#define NS_XML_ENCODING_CID \
{ 0x12bb8f16, 0x2389, 0x11d3, { 0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } }
#endif // nsXMLEncodingCID_h__
@end

Просмотреть файл

@ -1,4 +1,6 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -15,11 +17,12 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Hub Figuière <hub@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -35,25 +38,19 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDocumentCharsetInfo_h__
#define nsDocumentCharsetInfo_h__
#import "mozHTMLAccessible.h"
#include "nsIFactory.h"
#include "nsIDocumentCharsetInfo.h"
#import "nsHyperTextAccessible.h"
class nsDocumentCharsetInfo : public nsIDocumentCharsetInfo
@implementation mozHeadingAccessible
- (id)value
{
public:
nsDocumentCharsetInfo ();
virtual ~nsDocumentCharsetInfo ();
if (!mGeckoAccessible || !mGeckoAccessible->IsHyperText())
return nil;
NS_DECL_ISUPPORTS
NS_DECL_NSIDOCUMENTCHARSETINFO
PRUint32 level = mGeckoAccessible->AsHyperText()->GetLevelInternal();
return [NSNumber numberWithInt:level];
}
private:
nsCOMPtr<nsIAtom> mForcedCharset;
nsCOMPtr<nsIAtom> mParentCharset;
PRInt32 mParentCharsetSource;
};
#endif // nsDocumentCharsetInfo_h__
@end

Просмотреть файл

@ -1,4 +1,6 @@
#include "nsAccessibleWrap.h"
#include "nsCocoaUtils.h"
#include "nsObjCExceptions.h"
#import "mozTextAccessible.h"
@ -12,6 +14,7 @@ using namespace mozilla::a11y;
- (long)textLength;
- (BOOL)isReadOnly;
- (void)setText:(NSString*)newText;
- (NSString*)text;
@end
@implementation mozTextAccessible
@ -79,8 +82,9 @@ using namespace mozilla::a11y;
return [self selectedText];
// Apple's SpeechSynthesisServer expects AXValue to return an AXStaticText
// object's AXSelectedText attribute. See bug 674612.
// Also if there is no selected text, we return the full text.See bug 369710
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
return [self selectedText];
return [self selectedText] ? : [self text];
// let mozAccessible handle all other attributes
return [super accessibilityAttributeValue:attribute];
@ -158,6 +162,20 @@ using namespace mozilla::a11y;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (NSString*)text
{
if (!mGeckoTextAccessible)
return nil;
nsAutoString text;
nsresult rv =
mGeckoTextAccessible->GetText(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT,
text);
NS_ENSURE_SUCCESS(rv, nil);
return text.IsEmpty() ? nil : nsCocoaUtils::ToNSString(text);
}
- (long)textLength
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;

Просмотреть файл

@ -45,6 +45,7 @@
#import "mozAccessible.h"
#import "mozActionElements.h"
#import "mozHTMLAccessible.h"
#import "mozTextAccessible.h"
using namespace mozilla::a11y;
@ -108,10 +109,12 @@ nsAccessibleWrap::GetNativeType ()
case roles::AUTOCOMPLETE:
return [mozComboboxAccessible class];
case roles::HEADING:
return [mozHeadingAccessible class];
case roles::ENTRY:
case roles::STATICTEXT:
case roles::HEADING:
case roles::LABEL:
case roles::CAPTION:
case roles::ACCEL_LABEL:

Просмотреть файл

@ -147,7 +147,7 @@ static const NSString* AXRoles [] = {
NSAccessibilityTextFieldRole, // ROLE_ENTRY
NSAccessibilityStaticTextRole, // ROLE_CAPTION
@"AXWebArea", // ROLE_DOCUMENT_FRAME
NSAccessibilityStaticTextRole, // ROLE_HEADING
@"AXHeading", // ROLE_HEADING
NSAccessibilityGroupRole, // ROLE_PAGE
NSAccessibilityGroupRole, // ROLE_SECTION
NSAccessibilityUnknownRole, // ROLE_REDUNDANT_OBJECT

Просмотреть файл

@ -176,7 +176,8 @@
<menuseparator class="appmenu-menuseparator"/>
<menu id="appmenu_webDeveloper"
label="&appMenuWebDeveloper.label;">
<menupopup id="appmenu_webDeveloper_popup">
<menupopup id="appmenu_webDeveloper_popup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menuitem id="appmenu_webConsole"
label="&webConsoleCmd.label;"
type="checkbox"

Просмотреть файл

@ -531,7 +531,8 @@
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"
accesskey="&webDeveloperMenu.accesskey;">
<menupopup id="menuWebDeveloperPopup">
<menupopup id="menuWebDeveloperPopup"
onpopupshowing="onWebDeveloperMenuShowing();">
<menuitem id="webConsole"
type="checkbox"
label="&webConsoleCmd.label;"

Просмотреть файл

@ -0,0 +1,137 @@
#ifdef 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/. */
#endif
/**
* Keeps thumbnails of open web pages up-to-date.
*/
let gBrowserThumbnails = {
_captureDelayMS: 2000,
/**
* Map of capture() timeouts assigned to their browsers.
*/
_timeouts: null,
/**
* Cache for the PageThumbs module.
*/
_pageThumbs: null,
/**
* List of tab events we want to listen for.
*/
_tabEvents: ["TabClose", "TabSelect"],
init: function Thumbnails_init() {
gBrowser.addTabsProgressListener(this);
this._tabEvents.forEach(function (aEvent) {
gBrowser.tabContainer.addEventListener(aEvent, this, false);
}, this);
this._timeouts = new WeakMap();
XPCOMUtils.defineLazyModuleGetter(this, "_pageThumbs",
"resource:///modules/PageThumbs.jsm", "PageThumbs");
},
uninit: function Thumbnails_uninit() {
gBrowser.removeTabsProgressListener(this);
this._tabEvents.forEach(function (aEvent) {
gBrowser.tabContainer.removeEventListener(aEvent, this, false);
}, this);
this._timeouts = null;
this._pageThumbs = null;
},
handleEvent: function Thumbnails_handleEvent(aEvent) {
switch (aEvent.type) {
case "scroll":
let browser = aEvent.currentTarget;
if (this._timeouts.has(browser))
this._delayedCapture(browser);
break;
case "TabSelect":
this._delayedCapture(aEvent.target.linkedBrowser);
break;
case "TabClose": {
this._clearTimeout(aEvent.target.linkedBrowser);
break;
}
}
},
/**
* State change progress listener for all tabs.
*/
onStateChange: function Thumbnails_onStateChange(aBrowser, aWebProgress,
aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)
this._delayedCapture(aBrowser);
},
_capture: function Thumbnails_capture(aBrowser) {
if (this._shouldCapture(aBrowser)) {
let canvas = this._pageThumbs.capture(aBrowser.contentWindow);
this._pageThumbs.store(aBrowser.currentURI.spec, canvas);
}
},
_delayedCapture: function Thumbnails_delayedCapture(aBrowser) {
if (this._timeouts.has(aBrowser))
clearTimeout(this._timeouts.get(aBrowser));
else
aBrowser.addEventListener("scroll", this, true);
let timeout = setTimeout(function () {
this._clearTimeout(aBrowser);
this._capture(aBrowser);
}.bind(this), this._captureDelayMS);
this._timeouts.set(aBrowser, timeout);
},
_shouldCapture: function Thumbnails_shouldCapture(aBrowser) {
let doc = aBrowser.contentDocument;
// FIXME Bug 720575 - Don't capture thumbnails for SVG or XML documents as
// that currently regresses Talos SVG tests.
if (doc instanceof SVGDocument || doc instanceof XMLDocument)
return false;
// There's no point in taking screenshot of loading pages.
if (aBrowser.docShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
return false;
// Don't take screenshots of about: pages.
if (aBrowser.currentURI.schemeIs("about"))
return false;
let channel = aBrowser.docShell.currentDocumentChannel;
try {
// If the channel is a nsIHttpChannel get its http status code.
let httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
// Continue only if we have a 2xx status code.
return Math.floor(httpChannel.responseStatus / 100) == 2;
} catch (e) {
// Not a http channel, we just assume a success status code.
return true;
}
},
_clearTimeout: function Thumbnails_clearTimeout(aBrowser) {
if (this._timeouts.has(aBrowser)) {
aBrowser.removeEventListener("scroll", this, false);
clearTimeout(this._timeouts.get(aBrowser));
this._timeouts.delete(aBrowser);
}
}
};

Просмотреть файл

@ -196,6 +196,7 @@ let gInitialPages = [
#include browser-places.js
#include browser-tabPreviews.js
#include browser-tabview.js
#include browser-thumbnails.js
#ifdef MOZ_SERVICES_SYNC
#include browser-syncui.js
@ -1501,6 +1502,8 @@ function prepareForStartup() {
}
function delayedStartup(isLoadingBlank, mustLoadSidebar) {
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
TelemetryTimestamps.add("delayedStartupStarted");
gDelayedStartupTimeoutId = null;
Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
@ -1703,6 +1706,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
gSyncUI.init();
#endif
gBrowserThumbnails.init();
TabView.init();
setUrlAndSearchBarWidthForConditionalForwardButton();
@ -1765,6 +1769,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
window.addEventListener("dragover", MousePosTracker, false);
Services.obs.notifyObservers(window, "browser-delayed-startup-finished", "");
TelemetryTimestamps.add("delayedStartupFinished");
}
function BrowserShutdown() {
@ -1824,6 +1829,7 @@ function BrowserShutdown() {
gPrefService.removeObserver(allTabs.prefName, allTabs);
ctrlTab.uninit();
TabView.uninit();
gBrowserThumbnails.uninit();
try {
FullZoom.destroy();
@ -3109,20 +3115,13 @@ function FillInHTMLTooltip(tipElement)
[titleText, XLinkTitleText, SVGTitleText].forEach(function (t) {
if (t && /\S/.test(t)) {
// Per HTML 4.01 6.2 (CDATA section), literal CRs and tabs should be
// replaced with spaces, and LFs should be removed entirely.
// XXX Bug 322270: We don't preserve the result of entities like &#13;,
// which should result in a line break in the tooltip, because we can't
// distinguish that from a literal character in the source by this point.
t = t.replace(/[\r\t]/g, ' ');
t = t.replace(/\n/g, '');
// Make CRLF and CR render one line break each.
t = t.replace(/\r\n?/g, '\n');
tipNode.setAttribute("label", t);
retVal = true;
}
});
return retVal;
}
@ -4789,6 +4788,7 @@ var XULBrowserWindow = {
},
hideChromeForLocation: function(aLocation) {
aLocation = aLocation.toLowerCase();
return this.inContentWhitelist.some(function(aSpec) {
return aSpec == aLocation;
});
@ -5201,7 +5201,7 @@ nsBrowserAccess.prototype = {
let win, needToFocusWin;
// try the current window. if we're in a popup, fall back on the most recent browser window
if (!window.document.documentElement.getAttribute("chromehidden"))
if (window.toolbar.visible)
win = window;
else {
win = Cc["@mozilla.org/browser/browserglue;1"]
@ -5973,12 +5973,12 @@ function MultiplexHandler(event)
var name = node.getAttribute('name');
if (name == 'detectorGroup') {
SetForcedDetector(true);
BrowserCharsetReload();
SelectDetector(event, false);
} else if (name == 'charsetGroup') {
var charset = node.getAttribute('id');
charset = charset.substring('charset.'.length, charset.length)
SetForcedCharset(charset);
BrowserSetForcedCharacterSet(charset);
} else if (name == 'charsetCustomize') {
//do nothing - please remove this else statement, once the charset prefs moves to the pref window
} else {
@ -6009,30 +6009,17 @@ function SelectDetector(event, doReload)
}
}
function SetForcedDetector(doReload)
{
BrowserSetForcedDetector(doReload);
}
function SetForcedCharset(charset)
{
BrowserSetForcedCharacterSet(charset);
}
function BrowserSetForcedCharacterSet(aCharset)
{
var docCharset = gBrowser.docShell.QueryInterface(Ci.nsIDocCharset);
docCharset.charset = aCharset;
gBrowser.docShell.charset = aCharset;
// Save the forced character-set
PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, aCharset);
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
BrowserCharsetReload();
}
function BrowserSetForcedDetector(doReload)
function BrowserCharsetReload()
{
gBrowser.documentCharsetInfo.forcedDetector = true;
if (doReload)
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
}
function charsetMenuGetElement(parent, id) {
@ -8922,9 +8909,10 @@ var TabContextMenu = {
};
XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
Cu.import("resource:///modules/HUDService.jsm");
let tempScope = {};
Cu.import("resource:///modules/HUDService.jsm", tempScope);
try {
return HUDService.consoleUI;
return tempScope.HUDService.consoleUI;
}
catch (ex) {
Components.utils.reportError(ex);
@ -9076,6 +9064,11 @@ var StyleEditor = {
}
};
function onWebDeveloperMenuShowing() {
document.getElementById("Tools:WebConsole").setAttribute("checked", HUDConsoleUI.getOpenHUD() != null);
}
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
#ifdef XP_WIN
// Only show resizers on Windows 2000 and XP
@ -9150,6 +9143,7 @@ var MousePosTracker = {
}
}
};
function focusNextFrame(event) {
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC;

Просмотреть файл

@ -2375,10 +2375,6 @@
onget="return this.mCurrentBrowser.contentViewerFile;"
readonly="true"/>
<property name="documentCharsetInfo"
onget="return this.mCurrentBrowser.documentCharsetInfo;"
readonly="true"/>
<property name="contentDocument"
onget="return this.mCurrentBrowser.contentDocument;"
readonly="true"/>
@ -3811,49 +3807,34 @@
<binding id="tabbrowser-alltabs-popup"
extends="chrome://global/content/bindings/popup.xml#popup">
<implementation implements="nsIDOMEventListener">
<method name="_menuItemOnCommand">
<parameter name="aEvent"/>
<body><![CDATA[
gBrowser.selectedTab = aEvent.target.tab;
]]></body>
</method>
<method name="_tabOnAttrModified">
<parameter name="aEvent"/>
<body><![CDATA[
var tab = aEvent.target;
this._setMenuitemAttributes(tab.mCorrespondingMenuitem, tab);
if (tab.mCorrespondingMenuitem)
this._setMenuitemAttributes(tab.mCorrespondingMenuitem, tab);
]]></body>
</method>
<method name="_tabOnTabClose">
<parameter name="aEvent"/>
<body><![CDATA[
var menuItem = aEvent.target.mCorrespondingMenuitem;
if (menuItem)
this.removeChild(menuItem);
var tab = aEvent.target;
if (tab.mCorrespondingMenuitem)
this.removeChild(tab.mCorrespondingMenuitem);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (!aEvent.isTrusted)
return;
switch (aEvent.type) {
case "command":
this._menuItemOnCommand(aEvent);
break;
case "TabAttrModified":
this._tabOnAttrModified(aEvent);
break;
case "TabClose":
this._tabOnTabClose(aEvent);
break;
case "TabOpen":
this._createTabMenuItem(aEvent.originalTarget);
break;
case "scroll":
this._updateTabsVisibilityStatus();
break;
@ -3874,8 +3855,6 @@
if (!curTab) // "Tab Groups" menuitem and its menuseparator
continue;
let curTabBO = curTab.boxObject;
if (!curTabBO) // "Tabs From Other Computers" menuitem
continue;
if (curTabBO.screenX >= tabstripBO.screenX &&
curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width)
this.childNodes[i].setAttribute("tabIsVisible", "true");
@ -3896,14 +3875,10 @@
this._setMenuitemAttributes(menuItem, aTab);
// Keep some attributes of the menuitem in sync with its
// corresponding tab (e.g. the tab label)
aTab.mCorrespondingMenuitem = menuItem;
menuItem.tab = aTab;
menuItem.addEventListener("command", this, false);
this.appendChild(menuItem);
return menuItem;
]]></body>
</method>
@ -3938,18 +3913,17 @@
<handlers>
<handler event="popupshowing">
<![CDATA[
// set up the menu popup
var tabcontainer = gBrowser.tabContainer;
let tabs = gBrowser.visibleTabs;
// Listen for changes in the tab bar.
tabcontainer.addEventListener("TabOpen", this, false);
tabcontainer.addEventListener("TabAttrModified", this, false);
tabcontainer.addEventListener("TabClose", this, false);
tabcontainer.mTabstrip.addEventListener("scroll", this, false);
let tabs = gBrowser.visibleTabs;
for (var i = 0; i < tabs.length; i++) {
this._createTabMenuItem(tabs[i]);
if (!tabs[i].pinned)
this._createTabMenuItem(tabs[i]);
}
this._updateTabsVisibilityStatus();
]]></handler>
@ -3960,14 +3934,12 @@
for (let i = this.childNodes.length - 1; i > 0; i--) {
let menuItem = this.childNodes[i];
if (menuItem.tab) {
menuItem.removeEventListener("command", this, false);
menuItem.tab.mCorrespondingMenuitem = null;
this.removeChild(menuItem);
}
}
var tabcontainer = gBrowser.tabContainer;
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
tabcontainer.removeEventListener("TabOpen", this, false);
tabcontainer.removeEventListener("TabAttrModified", this, false);
tabcontainer.removeEventListener("TabClose", this, false);
]]></handler>
@ -3988,6 +3960,11 @@
XULBrowserWindow.setOverLink("", null);
]]></handler>
<handler event="command"><![CDATA[
if (event.target.tab)
gBrowser.selectedTab = event.target.tab;
]]></handler>
</handlers>
</binding>

Просмотреть файл

@ -11,16 +11,16 @@ function test () {
is(tooltip.getAttribute("label"), "This is a non-root SVG element title");
ok(FillInHTMLTooltip(doc.getElementById("text1"), "should get title"));
is(tooltip.getAttribute("label"), " This is a title ");
is(tooltip.getAttribute("label"), "\n\n\n This is a title\n\n ");
ok(!FillInHTMLTooltip(doc.getElementById("text2"), "should not get title"));
ok(!FillInHTMLTooltip(doc.getElementById("text3"), "should not get title"));
ok(FillInHTMLTooltip(doc.getElementById("link1"), "should get title"));
is(tooltip.getAttribute("label"), " This is a title ");
is(tooltip.getAttribute("label"), "\n This is a title\n ");
ok(FillInHTMLTooltip(doc.getElementById("text4"), "should get title"));
is(tooltip.getAttribute("label"), " This is a title ");
is(tooltip.getAttribute("label"), "\n This is a title\n ");
ok(!FillInHTMLTooltip(doc.getElementById("link2"), "should not get title"));

Просмотреть файл

@ -7,8 +7,10 @@
const testURL1 = "http://mochi.test:8888/browser/browser/base/content/test/browser_clearplugindata.html";
const testURL2 = "http://mochi.test:8888/browser/browser/base/content/test/browser_clearplugindata_noage.html";
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
const pluginHostIface = Ci.nsIPluginHost;
var pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);

Просмотреть файл

@ -104,7 +104,6 @@ function end_test() {
function test_url(aURL, aCanHide, aNextTest) {
is_chrome_visible();
info("Page load");
load_page(aURL, aCanHide, function() {
info("Switch away");
@ -163,5 +162,30 @@ function run_http_test_2() {
// Should not hide the chrome
function run_chrome_about_test_2() {
info("Chrome about: tests");
test_url("about:addons", true, end_test);
test_url("about:addons", true, run_http_test3);
}
function run_http_test3() {
info("HTTP tests");
test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_3);
}
// Should not hide the chrome
function run_chrome_about_test_3() {
info("Chrome about: tests");
test_url("about:Addons", true, function(){
info("Tabs on top");
TabsOnTop.enabled = true;
run_http_test4();
});
}
function run_http_test4() {
info("HTTP tests");
test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_4);
}
function run_chrome_about_test_4() {
info("Chrome about: tests");
test_url("about:Addons", true, end_test);
}

Просмотреть файл

@ -1,8 +1,10 @@
// Bug 474792 - Clear "Never remember passwords for this site" when
// clearing site-specific settings in Clear Recent History dialog
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
function test() {

Просмотреть файл

@ -1,7 +1,9 @@
// Bug 380852 - Delete permission manager entries in Clear Recent History
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
function test() {

Просмотреть файл

@ -5,8 +5,10 @@ const dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManage
const bhist = Cc["@mozilla.org/browser/global-history;2"].getService(Ci.nsIBrowserHistory);
const formhist = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js");
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
function test() {

Просмотреть файл

@ -50,9 +50,10 @@
* browser/base/content/test/browser_sanitize-timespans.js.
*/
Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader).
loadSubScript("chrome://browser/content/sanitize.js");
let tempScope = {};
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
let Sanitizer = tempScope.Sanitizer;
const dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);

Просмотреть файл

@ -56,7 +56,7 @@ function getTopWin(skipPopups) {
// whether it's the frontmost window, since commands can be executed in
// background windows (bug 626148).
if (top.document.documentElement.getAttribute("windowtype") == "navigator:browser" &&
(!skipPopups || !top.document.documentElement.getAttribute("chromehidden")))
(!skipPopups || top.toolbar.visible))
return top;
if (skipPopups) {
@ -206,7 +206,7 @@ function openLinkIn(url, where, params) {
var w = getTopWin();
if ((where == "tab" || where == "tabshifted") &&
w && w.document.documentElement.getAttribute("chromehidden")) {
w && !w.toolbar.visible) {
w = getTopWin(true);
aRelatedToCurrent = false;
}

Двоичные данные
browser/branding/aurora/dsstore

Двоичный файл не отображается.

Двоичные данные
browser/branding/nightly/dsstore

Двоичный файл не отображается.

Просмотреть файл

@ -71,6 +71,7 @@ PARALLEL_DIRS = \
shell \
sidebar \
tabview \
thumbnails \
migration \
$(NULL)

Просмотреть файл

@ -49,16 +49,15 @@ USE_STATIC_LIBS = 1
endif
CPPSRCS = nsBrowserProfileMigratorUtils.cpp \
$(NULL)
ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_)
CPPSRCS += nsIEProfileMigrator.cpp \
nsBrowserProfileMigratorUtils.cpp \
$(NULL)
endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += nsSafariProfileMigrator.cpp \
nsBrowserProfileMigratorUtils.cpp \
$(NULL)
endif

Просмотреть файл

@ -174,7 +174,7 @@ BrowserGlue.prototype = {
Services.obs.removeObserver(this, "browser-delayed-startup-finished");
break;
case "sessionstore-windows-restored":
this._onBrowserStartup();
this._onWindowsRestored();
break;
case "browser:purge-session-history":
// reset the console service's error buffer
@ -373,8 +373,8 @@ BrowserGlue.prototype = {
this._sanitizer.onShutdown();
},
// Browser startup complete. All initial windows have opened.
_onBrowserStartup: function BG__onBrowserStartup() {
// All initial windows have opened.
_onWindowsRestored: function BG__onWindowsRestored() {
// Show about:rights notification, if needed.
if (this._shouldShowRights()) {
this._showRightsNotification();
@ -1442,7 +1442,7 @@ BrowserGlue.prototype = {
getMostRecentBrowserWindow: function BG_getMostRecentBrowserWindow() {
function isFullBrowserWindow(win) {
return !win.closed &&
!win.document.documentElement.getAttribute("chromehidden");
win.toolbar.visible;
}
#ifdef BROKEN_WM_Z_ORDER

Просмотреть файл

@ -130,6 +130,8 @@ Cu.import("resource://gre/modules/Services.jsm");
// debug.js adds NS_ASSERT. cf. bug 669196
Cu.import("resource://gre/modules/debug.js");
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
Cu.import("resource://gre/modules/NetUtil.jsm");
return NetUtil;
@ -294,6 +296,7 @@ SessionStoreService.prototype = {
* Initialize the component
*/
initService: function() {
TelemetryTimestamps.add("sessionRestoreInitialized");
OBSERVING.forEach(function(aTopic) {
Services.obs.addObserver(this, aTopic, true);
}, this);
@ -833,7 +836,7 @@ SessionStoreService.prototype = {
this._windows[aWindow.__SSi]._restoring = true;
if (!aWindow.toolbar.visible)
this._windows[aWindow.__SSi].isPopup = true;
// perform additional initialization when the first window is loading
if (this._loadState == STATE_STOPPED) {
this._loadState = STATE_RUNNING;
@ -841,6 +844,7 @@ SessionStoreService.prototype = {
// restore a crashed session resp. resume the last session if requested
if (this._initialState) {
TelemetryTimestamps.add("sessionRestoreRestoring");
// make sure that the restored tabs are first in the window
this._initialState._firstTabs = true;
this._restoreCount = this._initialState.windows ? this._initialState.windows.length : 0;

Просмотреть файл

@ -48,7 +48,7 @@ function test() {
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("TmpD", Components.interfaces.nsIFile);
filePath = file.path;
var filePath = file.path;
let fieldList = {
"//input[@name='input']": Date.now().toString(),

Просмотреть файл

@ -42,13 +42,13 @@ function test() {
.get("TmpD", Components.interfaces.nsILocalFile);
file.append("346337_test1.file");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
filePath1 = file.path;
var filePath1 = file.path;
file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("TmpD", Components.interfaces.nsILocalFile);
file.append("346337_test2.file");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
filePath2 = file.path;
var filePath2 = file.path;
let fieldList = {
"//input[@name='input']": Date.now().toString(),

Просмотреть файл

@ -741,6 +741,11 @@ iQClass.prototype = {
if (pair.original == func) {
handler = pair.modified;
elem.iQEventData[type].splice(a, 1);
if (!elem.iQEventData[type].length) {
delete elem.iQEventData[type];
if (!Object.keys(elem.iQEventData).length)
delete elem.iQEventData;
}
break;
}
}
@ -765,10 +770,10 @@ iQClass.prototype = {
if (!elem.iQEventData)
continue;
for (let type in elem.iQEventData) {
while (elem.iQEventData[type].length)
Object.keys(elem.iQEventData).forEach(function (type) {
while (elem.iQEventData && elem.iQEventData[type])
this.unbind(type, elem.iQEventData[type][0].original);
}
}, this);
}
return this;

Просмотреть файл

@ -0,0 +1,2 @@
component {5a4ae9b5-f475-48ae-9dce-0b4c1d347884} PageThumbsProtocol.js
contract @mozilla.org/network/protocol;1?name=moz-page-thumb {5a4ae9b5-f475-48ae-9dce-0b4c1d347884}

Просмотреть файл

@ -0,0 +1,28 @@
# 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 = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
EXTRA_COMPONENTS = \
BrowserPageThumbs.manifest \
PageThumbsProtocol.js \
$(NULL)
EXTRA_PP_JS_MODULES = \
PageThumbs.jsm \
$(NULL)
# FIXME Bug 721422 - Re-enable tests and make them work with URI_DANGEROUS_TO_LOAD
#ifdef ENABLE_TESTS
# DIRS += test
#endif
include $(topsrcdir)/config/rules.mk
XPIDL_FLAGS += -I$(topsrcdir)/browser/components/

Просмотреть файл

@ -0,0 +1,259 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let EXPORTED_SYMBOLS = ["PageThumbs", "PageThumbsCache"];
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
/**
* The default width for page thumbnails.
*
* Hint: This is the default value because the 'New Tab Page' is the only
* client for now.
*/
const THUMBNAIL_WIDTH = 201;
/**
* The default height for page thumbnails.
*
* Hint: This is the default value because the 'New Tab Page' is the only
* client for now.
*/
const THUMBNAIL_HEIGHT = 127;
/**
* The default background color for page thumbnails.
*/
const THUMBNAIL_BG_COLOR = "#fff";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
/**
* Singleton providing functionality for capturing web page thumbnails and for
* accessing them if already cached.
*/
let PageThumbs = {
/**
* The scheme to use for thumbnail urls.
*/
get scheme() "moz-page-thumb",
/**
* The static host to use for thumbnail urls.
*/
get staticHost() "thumbnail",
/**
* The thumbnails' image type.
*/
get contentType() "image/png",
/**
* Gets the thumbnail image's url for a given web page's url.
* @param aUrl The web page's url that is depicted in the thumbnail.
* @return The thumbnail image's url.
*/
getThumbnailURL: function PageThumbs_getThumbnailURL(aUrl) {
return this.scheme + "://" + this.staticHost +
"?url=" + encodeURIComponent(aUrl);
},
/**
* Creates a canvas containing a thumbnail depicting the given window.
* @param aWindow The DOM window to capture a thumbnail from.
* @return The newly created canvas containing the image data.
*/
capture: function PageThumbs_capture(aWindow) {
let [sw, sh, scale] = this._determineCropSize(aWindow);
let canvas = this._createCanvas();
let ctx = canvas.getContext("2d");
// Scale the canvas accordingly.
ctx.scale(scale, scale);
try {
// Draw the window contents to the canvas.
ctx.drawWindow(aWindow, 0, 0, sw, sh, THUMBNAIL_BG_COLOR,
ctx.DRAWWINDOW_DO_NOT_FLUSH);
} catch (e) {
// We couldn't draw to the canvas for some reason.
}
return canvas;
},
/**
* Stores the image data contained in the given canvas to the underlying
* storage.
* @param aKey The key to use for the storage.
* @param aCanvas The canvas containing the thumbnail's image data.
* @param aCallback The function to be called when the canvas data has been
* stored (optional).
*/
store: function PageThumbs_store(aKey, aCanvas, aCallback) {
let self = this;
function finish(aSuccessful) {
if (aCallback)
aCallback(aSuccessful);
}
// Get a writeable cache entry.
PageThumbsCache.getWriteEntry(aKey, function (aEntry) {
if (!aEntry) {
finish(false);
return;
}
// Extract image data from the canvas.
self._readImageData(aCanvas, function (aData) {
let outputStream = aEntry.openOutputStream(0);
// Write the image data to the cache entry.
NetUtil.asyncCopy(aData, outputStream, function (aResult) {
let success = Components.isSuccessCode(aResult);
if (success)
aEntry.markValid();
aEntry.close();
finish(success);
});
});
});
},
/**
* Reads the image data from a given canvas and passes it to the callback.
* @param aCanvas The canvas to read the image data from.
* @param aCallback The function that the image data is passed to.
*/
_readImageData: function PageThumbs_readImageData(aCanvas, aCallback) {
let dataUri = aCanvas.toDataURL(PageThumbs.contentType, "");
let uri = Services.io.newURI(dataUri, "UTF8", null);
NetUtil.asyncFetch(uri, function (aData, aResult) {
if (Components.isSuccessCode(aResult) && aData && aData.available())
aCallback(aData);
});
},
/**
* Determines the crop size for a given content window.
* @param aWindow The content window.
* @return An array containing width, height and scale.
*/
_determineCropSize: function PageThumbs_determineCropSize(aWindow) {
let sw = aWindow.innerWidth;
let sh = aWindow.innerHeight;
let scale = Math.max(THUMBNAIL_WIDTH / sw, THUMBNAIL_HEIGHT / sh);
let scaledWidth = sw * scale;
let scaledHeight = sh * scale;
if (scaledHeight > THUMBNAIL_HEIGHT)
sh -= Math.floor(Math.abs(scaledHeight - THUMBNAIL_HEIGHT) * scale);
if (scaledWidth > THUMBNAIL_WIDTH)
sw -= Math.floor(Math.abs(scaledWidth - THUMBNAIL_WIDTH) * scale);
return [sw, sh, scale];
},
/**
* Creates a new hidden canvas element.
* @return The newly created canvas.
*/
_createCanvas: function PageThumbs_createCanvas() {
let doc = Services.appShell.hiddenDOMWindow.document;
let canvas = doc.createElementNS(HTML_NAMESPACE, "canvas");
canvas.mozOpaque = true;
canvas.mozImageSmoothingEnabled = true;
canvas.width = THUMBNAIL_WIDTH;
canvas.height = THUMBNAIL_HEIGHT;
return canvas;
}
};
/**
* 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);
},
/**
* Calls the given callback with a cache entry opened for writing.
* @param aKey The key identifying the desired cache entry.
* @param aCallback The callback that is called when the cache entry is ready.
*/
getWriteEntry: function Cache_getWriteEntry(aKey, aCallback) {
// Try to open the desired cache entry.
this._openCacheEntry(aKey, Ci.nsICache.ACCESS_WRITE, 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);
});

Просмотреть файл

@ -0,0 +1,448 @@
/* 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/. */
/**
* PageThumbsProtocol.js
*
* This file implements the moz-page-thumb:// protocol and the corresponding
* channel delivering cached thumbnails.
*
* URL structure:
*
* moz-page-thumb://thumbnail?url=http%3A%2F%2Fwww.mozilla.org%2F
*
* This URL requests an image for 'http://www.mozilla.org/'.
*/
"use strict";
const Cu = Components.utils;
const Cc = Components.classes;
const Cr = Components.results;
const Ci = Components.interfaces;
Cu.import("resource:///modules/PageThumbs.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
/**
* Implements the thumbnail protocol handler responsible for moz-page-thumb: URIs.
*/
function Protocol() {
}
Protocol.prototype = {
/**
* The scheme used by this protocol.
*/
get scheme() PageThumbs.scheme,
/**
* The default port for this protocol (we don't support ports).
*/
get defaultPort() -1,
/**
* The flags specific to this protocol implementation.
*/
get protocolFlags() {
return Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
Ci.nsIProtocolHandler.URI_NORELATIVE |
Ci.nsIProtocolHandler.URI_NOAUTH;
},
/**
* Creates a new URI object that is suitable for loading by this protocol.
* @param aSpec The URI string in UTF8 encoding.
* @param aOriginCharset The charset of the document from which the URI originated.
* @return The newly created URI.
*/
newURI: function Proto_newURI(aSpec, aOriginCharset) {
let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
uri.spec = aSpec;
return uri;
},
/**
* Constructs a new channel from the given URI for this protocol handler.
* @param aURI The URI for which to construct a channel.
* @return The newly created channel.
*/
newChannel: function Proto_newChannel(aURI) {
return new Channel(aURI);
},
/**
* Decides whether to allow a blacklisted port.
* @return Always false, we'll never allow ports.
*/
allowPort: function () false,
classID: Components.ID("{5a4ae9b5-f475-48ae-9dce-0b4c1d347884}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
};
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 = {
/**
* Tracks if the channel has been opened, yet.
*/
_wasOpened: false,
/**
* Opens this channel asynchronously.
* @param aListener The listener that receives the channel data when available.
* @param aContext A custom context passed to the listener's methods.
*/
asyncOpen: function Channel_asyncOpen(aListener, aContext) {
if (this._wasOpened)
throw Cr.NS_ERROR_ALREADY_OPENED;
if (this.canceled)
return;
this._listener = aListener;
this._context = aContext;
this._isPending = true;
this._wasOpened = true;
// Try to read the data from the thumbnail cache.
this._readCache(function (aData) {
// Update response if there's no data.
if (!aData) {
this._responseStatus = 404;
this._responseText = "Not Found";
}
this._startRequest();
if (!this.canceled) {
this._addToLoadGroup();
if (aData)
this._serveData(aData);
if (!this.canceled)
this._stopRequest();
}
}.bind(this));
},
/**
* Reads a data stream from the cache entry.
* @param aCallback The callback the data is passed to.
*/
_readCache: function Channel_readCache(aCallback) {
let {url} = parseURI(this._uri);
// Return early if there's no valid URL given.
if (!url) {
aCallback(null);
return;
}
// Try to get a cache entry.
PageThumbsCache.getReadEntry(url, function (aEntry) {
let inputStream = aEntry && aEntry.openInputStream(0);
function closeEntryAndFinish(aData) {
if (aEntry) {
aEntry.close();
}
aCallback(aData);
}
// Check if we have a valid entry and if it has any data.
if (!inputStream || !inputStream.available()) {
closeEntryAndFinish();
return;
}
try {
// Read the cache entry's data.
NetUtil.asyncFetch(inputStream, function (aData, aStatus) {
// We might have been canceled while waiting.
if (this.canceled)
return;
// Check if we have a valid data stream.
if (!Components.isSuccessCode(aStatus) || !aData.available())
aData = null;
closeEntryAndFinish(aData);
}.bind(this));
} catch (e) {
closeEntryAndFinish();
}
}.bind(this));
},
/**
* Calls onStartRequest on the channel listener.
*/
_startRequest: function Channel_startRequest() {
try {
this._listener.onStartRequest(this, this._context);
} catch (e) {
// The listener might throw if the request has been canceled.
this.cancel(Cr.NS_BINDING_ABORTED);
}
},
/**
* Calls onDataAvailable on the channel listener and passes the data stream.
* @param aData The data to be delivered.
*/
_serveData: function Channel_serveData(aData) {
try {
let available = aData.available();
this._listener.onDataAvailable(this, this._context, aData, 0, available);
} catch (e) {
// The listener might throw if the request has been canceled.
this.cancel(Cr.NS_BINDING_ABORTED);
}
},
/**
* Calls onStopRequest on the channel listener.
*/
_stopRequest: function Channel_stopRequest() {
try {
this._listener.onStopRequest(this, this._context, this.status);
} catch (e) {
// This might throw but is generally ignored.
}
// The request has finished, clean up after ourselves.
this._cleanup();
},
/**
* Adds this request to the load group, if any.
*/
_addToLoadGroup: function Channel_addToLoadGroup() {
if (this.loadGroup)
this.loadGroup.addRequest(this, this._context);
},
/**
* Removes this request from its load group, if any.
*/
_removeFromLoadGroup: function Channel_removeFromLoadGroup() {
if (!this.loadGroup)
return;
try {
this.loadGroup.removeRequest(this, this._context, this.status);
} catch (e) {
// This might throw but is ignored.
}
},
/**
* Cleans up the channel when the request has finished.
*/
_cleanup: function Channel_cleanup() {
this._removeFromLoadGroup();
this.loadGroup = null;
this._isPending = false;
delete this._listener;
delete this._context;
},
/* :::::::: nsIChannel ::::::::::::::: */
contentType: PageThumbs.contentType,
contentLength: -1,
owner: null,
contentCharset: null,
notificationCallbacks: null,
get URI() this._uri,
get securityInfo() null,
/**
* Opens this channel synchronously. Not supported.
*/
open: function Channel_open() {
// Synchronous data delivery is not implemented.
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
/* :::::::: nsIHttpChannel ::::::::::::::: */
redirectionLimit: 10,
requestMethod: "GET",
allowPipelining: true,
referrer: null,
get requestSucceeded() true,
_responseStatus: 200,
get responseStatus() this._responseStatus,
_responseText: "OK",
get responseStatusText() this._responseText,
/**
* Checks if the server sent the equivalent of a "Cache-control: no-cache"
* response header.
* @return Always false.
*/
isNoCacheResponse: function () false,
/**
* Checks if the server sent the equivalent of a "Cache-control: no-cache"
* response header.
* @return Always false.
*/
isNoStoreResponse: function () false,
/**
* Returns the value of a particular request header. Not implemented.
*/
getRequestHeader: function Channel_getRequestHeader() {
throw Cr.NS_ERROR_NOT_AVAILABLE;
},
/**
* This method is called to set the value of a particular request header.
* Not implemented.
*/
setRequestHeader: function Channel_setRequestHeader() {
if (this._wasOpened)
throw Cr.NS_ERROR_IN_PROGRESS;
},
/**
* Call this method to visit all request headers. Not implemented.
*/
visitRequestHeaders: function () {},
/**
* Gets the value of a particular response header.
* @param aHeader The case-insensitive name of the response header to query.
* @return The header value.
*/
getResponseHeader: function Channel_getResponseHeader(aHeader) {
let name = aHeader.toLowerCase();
if (name in this._responseHeaders)
return this._responseHeaders[name];
throw Cr.NS_ERROR_NOT_AVAILABLE;
},
/**
* This method is called to set the value of a particular response header.
* @param aHeader The case-insensitive name of the response header to query.
* @param aValue The response header value to set.
*/
setResponseHeader: function Channel_setResponseHeader(aHeader, aValue, aMerge) {
let name = aHeader.toLowerCase();
if (!aValue && !aMerge)
delete this._responseHeaders[name];
else
this._responseHeaders[name] = aValue;
},
/**
* Call this method to visit all response headers.
* @param aVisitor The header visitor.
*/
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;
}
}
},
/* :::::::: nsIRequest ::::::::::::::: */
loadFlags: Ci.nsIRequest.LOAD_NORMAL,
loadGroup: null,
get name() this._uri.spec,
_status: Cr.NS_OK,
get status() this._status,
_isPending: false,
isPending: function () this._isPending,
resume: function () {},
suspend: function () {},
/**
* Cancels this request.
* @param aStatus The reason for cancelling.
*/
cancel: function Channel_cancel(aStatus) {
if (this.canceled)
return;
this._isCanceled = true;
this._status = aStatus;
this._cleanup();
},
/* :::::::: nsIHttpChannelInternal ::::::::::::::: */
documentURI: null,
_isCanceled: false,
get canceled() this._isCanceled,
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.
* @return The parsed parameters.
*/
function parseURI(aURI) {
let {scheme, staticHost} = PageThumbs;
let re = new RegExp("^" + scheme + "://" + staticHost + ".*?\\?");
let query = aURI.spec.replace(re, "");
let params = {};
query.split("&").forEach(function (aParam) {
let [key, value] = aParam.split("=").map(decodeURIComponent);
params[key.toLowerCase()] = value;
});
return params;
}

Просмотреть файл

@ -0,0 +1,21 @@
# 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 = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = browser/components/thumbnails/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_thumbnails_cache.js \
browser_thumbnails_capture.js \
head.js \
$(NULL)
libs:: $(_BROWSER_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

Просмотреть файл

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* These tests ensure that saving a thumbnail to the cache works. They also
* retrieve the thumbnail and display it using an <img> element to compare
* its pixel colors.
*/
function runTests() {
// Create a new tab with a red background.
yield addTab("data:text/html,<body bgcolor=ff0000></body>");
let cw = gBrowser.selectedTab.linkedBrowser.contentWindow;
// Capture a thumbnail for the tab.
let canvas = PageThumbs.capture(cw);
// Store the tab into the thumbnail cache.
yield PageThumbs.store("key", canvas, next);
let {width, height} = canvas;
let thumb = PageThumbs.getThumbnailURL("key", width, height);
// Create a new tab with an image displaying the previously stored thumbnail.
yield addTab("data:text/html,<img src='" + thumb + "'/>" +
"<canvas width=" + width + " height=" + height + "/>");
cw = gBrowser.selectedTab.linkedBrowser.contentWindow;
let [img, canvas] = cw.document.querySelectorAll("img, canvas");
// Draw the image to a canvas and compare the pixel color values.
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
checkCanvasColor(ctx, 255, 0, 0, "we have a red image and canvas");
}

Просмотреть файл

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* These tests ensure that capturing a site's screenshot to a canvas actually
* works.
*/
function runTests() {
// Create a tab with a red background.
yield addTab("data:text/html,<body bgcolor=ff0000></body>");
checkCurrentThumbnailColor(255, 0, 0, "we have a red thumbnail");
// Load a page with a green background.
yield navigateTo("data:text/html,<body bgcolor=00ff00></body>");
checkCurrentThumbnailColor(0, 255, 0, "we have a green thumbnail");
// Load a page with a blue background.
yield navigateTo("data:text/html,<body bgcolor=0000ff></body>");
checkCurrentThumbnailColor(0, 0, 255, "we have a blue thumbnail");
}
/**
* Captures a thumbnail of the currently selected tab and checks the color of
* the resulting canvas.
* @param aRed The red component's intensity.
* @param aGreen The green component's intensity.
* @param aBlue The blue component's intensity.
* @param aMessage The info message to print when checking the pixel color.
*/
function checkCurrentThumbnailColor(aRed, aGreen, aBlue, aMessage) {
let tab = gBrowser.selectedTab;
let cw = tab.linkedBrowser.contentWindow;
let canvas = PageThumbs.capture(cw);
let ctx = canvas.getContext("2d");
checkCanvasColor(ctx, aRed, aGreen, aBlue, aMessage);
}

Просмотреть файл

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource:///modules/PageThumbs.jsm");
registerCleanupFunction(function () {
while (gBrowser.tabs.length > 1)
gBrowser.removeTab(gBrowser.tabs[1]);
});
/**
* Provide the default test function to start our test runner.
*/
function test() {
TestRunner.run();
}
/**
* The test runner that controls the execution flow of our tests.
*/
let TestRunner = {
/**
* Starts the test runner.
*/
run: function () {
waitForExplicitFinish();
this._iter = runTests();
this.next();
},
/**
* Runs the next available test or finishes if there's no test left.
*/
next: function () {
try {
TestRunner._iter.next();
} catch (e if e instanceof StopIteration) {
finish();
}
}
};
/**
* Continues the current test execution.
*/
function next() {
TestRunner.next();
}
/**
* Creates a new tab with the given URI.
* @param aURI The URI that's loaded in the tab.
*/
function addTab(aURI) {
let tab = gBrowser.selectedTab = gBrowser.addTab(aURI);
whenBrowserLoaded(tab.linkedBrowser);
}
/**
* Loads a new URI into the currently selected tab.
* @param aURI The URI to load.
*/
function navigateTo(aURI) {
let browser = gBrowser.selectedTab.linkedBrowser;
whenBrowserLoaded(browser);
browser.loadURI(aURI);
}
/**
* Continues the current test execution when a load event for the given browser
* has been received
* @param aBrowser The browser to listen on.
*/
function whenBrowserLoaded(aBrowser) {
aBrowser.addEventListener("load", function onLoad() {
aBrowser.removeEventListener("load", onLoad, true);
executeSoon(next);
}, true);
}
/**
* Checks the top-left pixel of a given canvas' 2d context for a given color.
* @param aContext The 2D context of a canvas.
* @param aRed The red component's intensity.
* @param aGreen The green component's intensity.
* @param aBlue The blue component's intensity.
* @param aMessage The info message to print when comparing the pixel color.
*/
function checkCanvasColor(aContext, aRed, aGreen, aBlue, aMessage) {
let [r, g, b] = aContext.getImageData(0, 0, 1, 1).data;
ok(r == aRed && g == aGreen && b == aBlue, aMessage);
}

Просмотреть файл

@ -141,7 +141,7 @@ TreePanel.prototype = {
this.treeLoaded = true;
this.treeIFrame.addEventListener("click", this.onTreeClick.bind(this), false);
this.treeIFrame.addEventListener("dblclick", this.onTreeDblClick.bind(this), false);
this.treeIFrame.addEventListener("keypress", this.IUI, false);
this.treeIFrame.focus();
delete this.initializingTreePanel;
Services.obs.notifyObservers(null,
this.IUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, null);
@ -233,7 +233,7 @@ TreePanel.prototype = {
} catch(e) {
treeBox.height = 112;
}
treeBox.minHeight = 64;
treeBox.flex = 1;
toolbarParent.insertBefore(treeBox, toolbar);
@ -466,9 +466,6 @@ TreePanel.prototype = {
editorInput.value = aAttrVal;
editorInput.select();
// remove tree key navigation events
this.treeIFrame.removeEventListener("keypress", this.IUI, false);
// listen for editor specific events
this.bindEditorEvent(editor, "click", function(aEvent) {
aEvent.stopPropagation();
@ -561,9 +558,6 @@ TreePanel.prototype = {
this.editingContext = null;
this.editingEvents = {};
// re-add navigation listener
this.treeIFrame.addEventListener("keypress", this.IUI, false);
// event notification
Services.obs.notifyObservers(null, this.IUI.INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED,
null);
@ -700,7 +694,6 @@ TreePanel.prototype = {
}
if (this.treeIFrame) {
this.treeIFrame.removeEventListener("keypress", this.IUI, false);
this.treeIFrame.removeEventListener("dblclick", this.onTreeDblClick, false);
this.treeIFrame.removeEventListener("click", this.onTreeClick, false);
let parent = this.treeIFrame.parentNode;

Просмотреть файл

@ -698,12 +698,14 @@ Highlighter.prototype = {
{
this.browser.addEventListener("resize", this, true);
this.browser.addEventListener("scroll", this, true);
this.browser.addEventListener("MozAfterPaint", this, true);
},
detachPageListeners: function Highlighter_detachPageListeners()
{
this.browser.removeEventListener("resize", this, true);
this.browser.removeEventListener("scroll", this, true);
this.browser.removeEventListener("MozAfterPaint", this, true);
},
attachKeysListeners: function Highlighter_attachKeysListeners()
@ -734,8 +736,10 @@ Highlighter.prototype = {
this.handleMouseMove(aEvent);
break;
case "resize":
case "scroll":
this.computeZoomFactor();
break;
case "MozAfterPaint":
case "scroll":
this.brieflyDisableTransitions();
this.invalidateSize();
break;
@ -745,7 +749,6 @@ Highlighter.prototype = {
aEvent.stopPropagation();
aEvent.preventDefault();
break;
break;
case "keypress":
switch (aEvent.keyCode) {
case this.chromeWin.KeyEvent.DOM_VK_RETURN:
@ -753,69 +756,6 @@ Highlighter.prototype = {
aEvent.preventDefault();
aEvent.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_LEFT:
let node;
if (this.node) {
node = this.node.parentNode;
} else {
node = this.defaultSelection;
}
if (node && this.isNodeHighlightable(node)) {
this.highlight(node);
}
aEvent.preventDefault();
aEvent.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_RIGHT:
if (this.node) {
// Find the first child that is highlightable.
for (let i = 0; i < this.node.childNodes.length; i++) {
node = this.node.childNodes[i];
if (node && this.isNodeHighlightable(node)) {
break;
}
}
} else {
node = this.defaultSelection;
}
if (node && this.isNodeHighlightable(node)) {
this.highlight(node, true);
}
aEvent.preventDefault();
aEvent.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_UP:
if (this.node) {
// Find a previous sibling that is highlightable.
node = this.node.previousSibling;
while (node && !this.isNodeHighlightable(node)) {
node = node.previousSibling;
}
} else {
node = this.defaultSelection;
}
if (node && this.isNodeHighlightable(node)) {
this.highlight(node, true);
}
aEvent.preventDefault();
aEvent.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_DOWN:
if (this.node) {
// Find a next sibling that is highlightable.
node = this.node.nextSibling;
while (node && !this.isNodeHighlightable(node)) {
node = node.nextSibling;
}
} else {
node = this.defaultSelection;
}
if (node && this.isNodeHighlightable(node)) {
this.highlight(node, true);
}
aEvent.preventDefault();
aEvent.stopPropagation();
break;
}
}
},

Просмотреть файл

@ -286,6 +286,8 @@ InspectorUI.prototype = {
// initialize the highlighter
this.highlighter = new Highlighter(this.chromeWin);
this.setupNavigationKeys();
this.highlighterReady();
},
@ -349,6 +351,36 @@ InspectorUI.prototype = {
}
},
/**
* Browse nodes according to the breadcrumbs layout, only for some specific
* elements of the UI.
*/
setupNavigationKeys: function IUI_setupNavigationKeys()
{
// UI elements that are arrow keys sensitive:
// - highlighter veil;
// - content window (when the highlighter `veil is pointer-events:none`;
// - the Inspector toolbar.
this.onKeypress = this.onKeypress.bind(this);
this.highlighter.highlighterContainer.addEventListener("keypress",
this.onKeypress, true);
this.win.addEventListener("keypress", this.onKeypress, true);
this.toolbar.addEventListener("keypress", this.onKeypress, true);
},
/**
* Remove the event listeners for the arrowkeys.
*/
removeNavigationKeys: function IUI_removeNavigationKeys()
{
this.highlighter.highlighterContainer.removeEventListener("keypress",
this.onKeypress, true);
this.win.removeEventListener("keypress", this.onKeypress, true);
this.toolbar.removeEventListener("keypress", this.onKeypress, true);
},
/**
* Close inspector UI and associated panels. Unhighlight and stop inspecting.
* Remove event listeners for document scrolling, resize,
@ -375,6 +407,8 @@ InspectorUI.prototype = {
this.closing = true;
this.toolbar.hidden = true;
this.removeNavigationKeys();
this.progressListener.destroy();
delete this.progressListener;
@ -592,6 +626,14 @@ InspectorUI.prototype = {
false);
}
break;
case "keypress":
switch (event.keyCode) {
case this.chromeWin.KeyEvent.DOM_VK_ESCAPE:
this.closeInspectorUI(false);
event.preventDefault();
event.stopPropagation();
break;
}
case "pagehide":
win = event.originalTarget.defaultView;
// Skip iframes/frames.
@ -611,18 +653,66 @@ InspectorUI.prototype = {
false);
}
break;
case "keypress":
switch (event.keyCode) {
case this.chromeWin.KeyEvent.DOM_VK_ESCAPE:
this.closeInspectorUI(false);
event.preventDefault();
event.stopPropagation();
break;
}
},
/*
* handles "keypress" events.
*/
onKeypress: function IUI_onKeypress(event)
{
let node = null;
let bc = this.breadcrumbs;
switch (event.keyCode) {
case this.chromeWin.KeyEvent.DOM_VK_LEFT:
if (bc.currentIndex != 0)
node = bc.nodeHierarchy[bc.currentIndex - 1].node;
if (node && this.highlighter.isNodeHighlightable(node))
this.highlighter.highlight(node);
event.preventDefault();
event.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_RIGHT:
if (bc.currentIndex < bc.nodeHierarchy.length - 1)
node = bc.nodeHierarchy[bc.currentIndex + 1].node;
if (node && this.highlighter.isNodeHighlightable(node)) {
this.highlighter.highlight(node);
}
event.preventDefault();
event.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_UP:
if (this.selection) {
// Find a previous sibling that is highlightable.
node = this.selection.previousSibling;
while (node && !this.highlighter.isNodeHighlightable(node)) {
node = node.previousSibling;
}
}
if (node && this.highlighter.isNodeHighlightable(node)) {
this.highlighter.highlight(node, true);
}
event.preventDefault();
event.stopPropagation();
break;
case this.chromeWin.KeyEvent.DOM_VK_DOWN:
if (this.selection) {
// Find a next sibling that is highlightable.
node = this.selection.nextSibling;
while (node && !this.highlighter.isNodeHighlightable(node)) {
node = node.nextSibling;
}
}
if (node && this.highlighter.isNodeHighlightable(node)) {
this.highlighter.highlight(node, true);
}
event.preventDefault();
event.stopPropagation();
break;
}
},
/////////////////////////////////////////////////////////////////////////
//// CssRuleView methods
@ -1720,6 +1810,8 @@ HTMLBreadcrumbs.prototype = {
}
if (aIdx > -1) {
this.nodeHierarchy[aIdx].button.setAttribute("checked", "true");
if (this.hadFocus)
this.nodeHierarchy[aIdx].button.focus();
}
this.currentIndex = aIdx;
},
@ -1895,6 +1987,10 @@ HTMLBreadcrumbs.prototype = {
{
this.menu.hidePopup();
let cmdDispatcher = this.IUI.chromeDoc.commandDispatcher;
this.hadFocus = (cmdDispatcher.focusedElement &&
cmdDispatcher.focusedElement.parentNode == this.container);
let selection = this.IUI.selection;
let idx = this.indexOf(selection);
@ -1924,7 +2020,8 @@ HTMLBreadcrumbs.prototype = {
// Make sure the selected node and its neighbours are visible.
this.scroll();
}
},
}
/////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -69,6 +69,7 @@ _BROWSER_FILES = \
browser_inspector_changes.js \
browser_inspector_ruleviewstore.js \
browser_inspector_duplicate_ruleview.js \
browser_inspector_invalidate.js \
head.js \
$(NULL)

Просмотреть файл

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let doc;
let div;
function createDocument()
{
div = doc.createElement("div");
div.setAttribute("style", "width: 100px; height: 100px;");
doc.body.appendChild(div);
Services.obs.addObserver(runTest,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
InspectorUI.toggleInspectorUI();
}
function runTest(subject)
{
Services.obs.removeObserver(runTest,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
InspectorUI.highlighter.highlight(div);
executeSoon(function() {
let veilBoxDims = InspectorUI.highlighter.veilTransparentBox;
is(veilBoxDims.style.width, "100px", "selection has the right width");
div.style.width = "200px";
setTimeout(function () {
let veilBoxDims = InspectorUI.highlighter.veilTransparentBox;
is(veilBoxDims.style.width, "200px", "selection updated");
InspectorUI.closeInspectorUI();
gBrowser.removeCurrentTab();
finish();
}, 1000);
});
}
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html,basic tests for inspector";
}

Просмотреть файл

@ -92,8 +92,7 @@ function ruleViewOpened1()
prop.setEnabled(false);
// Open second tab and switch to it
tab2 = gBrowser.addTab();
gBrowser.selectedTab = tab2;
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,

Просмотреть файл

@ -37,7 +37,9 @@
* ***** END LICENSE BLOCK ***** */
const Cu = Components.utils;
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
let tempScope = {};
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tempScope);
let LayoutHelpers = tempScope.LayoutHelpers;
function isHighlighting()
{

Просмотреть файл

@ -2,8 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
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 chrome window object.
let gScratchpadWindow;

Просмотреть файл

@ -2,9 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
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;
// only finish() when correct number of tests are done
const expected = 5;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
function test()
{

Просмотреть файл

@ -75,6 +75,7 @@ function runTests()
sp.run();
is(window.foobarBug636725, "aloha2", "window.foobarBug636725 has been set");
delete window.foobarBug636725;
sp.setText("gBrowser", 7);

Просмотреть файл

@ -2,8 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
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;

Просмотреть файл

@ -69,11 +69,6 @@ function SplitView(aRoot)
this._mql = aRoot.ownerDocument.defaultView.matchMedia(LANDSCAPE_MEDIA_QUERY);
this._filter = aRoot.querySelector(".splitview-filter");
if (this._filter) {
this._setupFilterBox();
}
// items list focus and search-on-type handling
this._nav.addEventListener("keydown", function onKeyCatchAll(aEvent) {
function getFocusedItemWithin(nav) {
@ -116,13 +111,6 @@ function SplitView(aRoot)
}
return false;
}
// search-on-type when any non-whitespace character is pressed while list
// has the focus
if (this._filter &&
!/\s/.test(String.fromCharCode(aEvent.which))) {
this._filter.focus();
}
}.bind(this), false);
}
@ -227,10 +215,6 @@ SplitView.prototype = {
* Called when the item is hidden/inactive.
* - function(summary, details, data) onDestroy
* Called when the item has been removed.
* - function(summary, details, data, query) onFilterBy
* Called when the user performs a filtering search.
* If the function returns false, the item does not match query
* string and will be hidden.
* - object data
* Object to pass to the callbacks above.
* - number ordinal
@ -327,71 +311,6 @@ SplitView.prototype = {
}
},
/**
* Filter items by given string.
* Matching is performed on every item by calling onFilterBy when defined
* and then by searching aQuery in the summary element's text item.
* Non-matching item is hidden.
*
* If no item matches, 'splitview-all-filtered' class is set on the filter
* input element and the splitview-nav element.
*
* @param string aQuery
* The query string. Use null to reset (no filter).
* @return number
* The number of filtered (non-matching) item.
*/
filterItemsBy: function ASV_filterItemsBy(aQuery)
{
if (!this._nav.hasChildNodes()) {
return 0;
}
if (aQuery) {
aQuery = aQuery.trim();
}
if (!aQuery) {
for (let i = 0; i < this._nav.childNodes.length; ++i) {
this._nav.childNodes[i].classList.remove("splitview-filtered");
}
this._filter.classList.remove("splitview-all-filtered");
this._nav.classList.remove("splitview-all-filtered");
return 0;
}
let count = 0;
let filteredCount = 0;
for (let i = 0; i < this._nav.childNodes.length; ++i) {
let summary = this._nav.childNodes[i];
let matches = false;
let binding = summary.getUserData(BINDING_USERDATA);
if (binding.onFilterBy) {
matches = binding.onFilterBy(summary, binding._details, binding.data, aQuery);
}
if (!matches) { // try text content
let content = summary.textContent.toUpperCase();
matches = (content.indexOf(aQuery.toUpperCase()) > -1);
}
count++;
if (!matches) {
summary.classList.add("splitview-filtered");
filteredCount++;
} else {
summary.classList.remove("splitview-filtered");
}
}
if (count > 0 && filteredCount == count) {
this._filter.classList.add("splitview-all-filtered");
this._nav.classList.add("splitview-all-filtered");
} else {
this._filter.classList.remove("splitview-all-filtered");
this._nav.classList.remove("splitview-all-filtered");
}
return filteredCount;
},
/**
* Set the item's CSS class name.
* This sets the class on both the summary and details elements, retaining
@ -415,39 +334,4 @@ SplitView.prototype = {
viewSpecific = viewSpecific ? viewSpecific.join(" ") : "";
binding._details.className = viewSpecific + " " + aClassName;
},
/**
* Set up filter search box.
*/
_setupFilterBox: function ASV__setupFilterBox()
{
let clearFilter = function clearFilter(aEvent) {
this._filter.value = "";
this.filterItemsBy("");
return false;
}.bind(this);
this._filter.addEventListener("command", function onFilterInput(aEvent) {
this.filterItemsBy(this._filter.value);
}.bind(this), false);
this._filter.addEventListener("keyup", function onFilterKeyUp(aEvent) {
if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
clearFilter();
}
if (aEvent.keyCode == aEvent.DOM_VK_ENTER ||
aEvent.keyCode == aEvent.DOM_VK_RETURN) {
// autofocus matching item if there is only one
let matches = this._nav.querySelectorAll("* > li:not(.splitview-filtered)");
if (matches.length == 1) {
this.activeSummary = matches[0];
}
}
}.bind(this), false);
let clearButtons = this._root.querySelectorAll(".splitview-filter-clearButton");
for (let i = 0; i < clearButtons.length; ++i) {
clearButtons[i].addEventListener("click", clearFilter, false);
}
}
};

Просмотреть файл

@ -58,6 +58,7 @@ box,
.splitview-controller {
min-height: 3em;
max-height: 14em;
max-width: 400px;
}
.splitview-nav {
@ -123,4 +124,8 @@ ol.splitview-nav > li.splitview-filtered {
.splitview-portrait-resizer {
display: -moz-box;
}
.splitview-controller {
max-width: none;
}
}

Просмотреть файл

@ -3,7 +3,9 @@
// Tests that our Promise implementation works properly
Cu.import("resource:///modules/devtools/Promise.jsm");
let tempScope = {};
Cu.import("resource:///modules/devtools/Promise.jsm", tempScope);
let Promise = tempScope.Promise;
function test() {
addTab("about:blank", function() {

Просмотреть файл

@ -3,8 +3,11 @@
// Tests that the DOM Template engine works properly
Cu.import("resource:///modules/devtools/Templater.jsm");
Cu.import("resource:///modules/devtools/Promise.jsm");
let tempScope = {};
Cu.import("resource:///modules/devtools/Templater.jsm", tempScope);
Cu.import("resource:///modules/devtools/Promise.jsm", tempScope);
let template = tempScope.template;
let Promise = tempScope.Promise;
function test() {
addTab("http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html", function() {

Просмотреть файл

@ -15,6 +15,8 @@ Orion version: git clone from 2011-12-09
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=366312
+ patch for Mozilla Bug 711737 - Orion should support all the CSS properties from CSS1, CSS2, CSS2.1 and CSS3
https://bugzilla.mozilla.org/show_bug.cgi?id=711737
+ patch for Mozilla Bug 719028 - Style Editor does not highlight a few CSS2.0 and CSS3 properties
https://bugzilla.mozilla.org/show_bug.cgi?id=719028
# License

Просмотреть файл

@ -10,6 +10,7 @@
* Felipe Heidrich (IBM Corporation) - initial API and implementation
* Silenio Quarti (IBM Corporation) - initial API and implementation
* Mihai Sucan (Mozilla Foundation) - fix for Bug#364214
* Alex Lakatos (Mozilla Contributor) - fix for Mozilla Bug#719028
*/
/*global window */
@ -10488,13 +10489,14 @@ define(['orion/textview/annotations'], function(mAnnotations) {
"column-rule-color", "column-rule-style", "column-rule-width", "column-span", "column-width", "columns", "content", "counter-increment",
"counter-reset", "crop", "cue", "cue-after", "cue-before", "cursor", "direction", "display", "dominant-baseline",
"drop-initial-after-adjust", "drop-initial-after-align", "drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size",
"drop-initial-value", "elevation", "empty-cells", "fit", "fit-position", "float", "float-offset", "font", "font-family", "font-size",
"font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "grid-columns", "grid-rows", "hanging-punctuation",
"height", "hyphenate-after", "hyphenate-before", "hyphenate-character", "hyphenate-lines", "hyphenate-resource", "hyphens", "icon",
"image-orientation", "image-rendering", "image-resolution", "inline-box-align", "left", "letter-spacing", "line-height",
"line-stacking", "line-stacking-ruby", "line-stacking-shift", "line-stacking-strategy", "list-style", "list-style-image",
"list-style-position", "list-style-type", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "mark", "mark-after",
"mark-before", "marks", "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"drop-initial-value", "elevation", "empty-cells", "fit", "fit-position", "flex-align", "flex-flow", "flex-inline-pack", "flex-order",
"flex-pack", "float", "float-offset", "font", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style",
"font-variant", "font-weight", "grid-columns", "grid-rows", "hanging-punctuation", "height", "hyphenate-after",
"hyphenate-before", "hyphenate-character", "hyphenate-lines", "hyphenate-resource", "hyphens", "icon", "image-orientation",
"image-rendering", "image-resolution", "inline-box-align", "left", "letter-spacing", "line-height", "line-stacking",
"line-stacking-ruby", "line-stacking-shift", "line-stacking-strategy", "list-style", "list-style-image", "list-style-position",
"list-style-type", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "mark", "mark-after", "mark-before",
"marker-offset", "marks", "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", "nav-left", "nav-right", "nav-up", "opacity", "orphans",
"outline", "outline-color", "outline-offset", "outline-style", "outline-width", "overflow", "overflow-style", "overflow-x",
"overflow-y", "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", "page", "page-break-after", "page-break-before",

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;

Просмотреть файл

@ -4,7 +4,9 @@
"use strict";
Cu.import("resource:///modules/source-editor.jsm");
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let testDoc;

Просмотреть файл

@ -229,6 +229,8 @@ StyleEditor.prototype = {
};
sourceEditor.init(aElement, config, function onSourceEditorReady() {
setupBracketCompletion(sourceEditor);
sourceEditor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onTextChanged(aEvent) {
this.updateStyleSheet();
@ -1132,3 +1134,48 @@ function repeat(aText, aCount)
{
return (new Array(aCount + 1)).join(aText);
}
/**
* Set up bracket completion on a given SourceEditor.
* This automatically closes the following CSS brackets: "{", "(", "["
*
* @param SourceEditor aSourceEditor
*/
function setupBracketCompletion(aSourceEditor)
{
let editorElement = aSourceEditor.editorElement;
let pairs = {
123: { // {
closeString: "}",
closeKeyCode: Ci.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET
},
40: { // (
closeString: ")",
closeKeyCode: Ci.nsIDOMKeyEvent.DOM_VK_0
},
91: { // [
closeString: "]",
closeKeyCode: Ci.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET
},
};
editorElement.addEventListener("keypress", function onKeyPress(aEvent) {
let pair = pairs[aEvent.charCode];
if (!pair) {
return true;
}
// We detected an open bracket, sending closing character
let keyCode = pair.closeKeyCode;
let charCode = pair.closeString.charCodeAt(0);
let modifiers = 0;
let utils = editorElement.ownerDocument.defaultView.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
let handled = utils.sendKeyEvent("keydown", keyCode, 0, modifiers);
utils.sendKeyEvent("keypress", 0, charCode, modifiers, !handled);
utils.sendKeyEvent("keyup", keyCode, 0, modifiers);
// and rewind caret
aSourceEditor.setCaretOffset(aSourceEditor.getCaretOffset() - 1);
}, false);
}

Просмотреть файл

@ -402,7 +402,9 @@ StyleEditorChrome.prototype = {
this._view.setItemClassName(summary, aEditor.flags);
text(summary, ".stylesheet-name", aEditor.getFriendlyName());
let label = summary.querySelector(".stylesheet-name > label");
label.setAttribute("value", aEditor.getFriendlyName());
text(summary, ".stylesheet-title", aEditor.styleSheet.title || "");
text(summary, ".stylesheet-rule-count",
PluralForm.get(ruleCount, _("ruleCount.label")).replace("#1", ruleCount));

Просмотреть файл

@ -20,6 +20,7 @@
*
* Contributor(s):
* Cedric Vivier <cedricv@neonux.com> (original author)
* Paul Rouget <paul@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -64,22 +65,17 @@ li.error > .stylesheet-info > .stylesheet-more > .stylesheet-error-message {
}
.stylesheet-name {
/* clip the text at the beginning */
display: -moz-box;
direction: rtl;
text-align: left;
overflow: hidden;
outline: none;
}
.stylesheet-name > label {
cursor: pointer;
}
.splitview-nav > li > hgroup.stylesheet-info {
-moz-box-pack: center;
}
.splitview-nav:-moz-locale-dir(ltr) > li.unsaved > hgroup .stylesheet-name:before,
.splitview-nav:-moz-locale-dir(rtl) > li.unsaved > hgroup .stylesheet-name:after {
content: "* ";
}
.stylesheet-enabled {
display: -moz-box;
}
@ -107,7 +103,7 @@ li:hover > hgroup > .stylesheet-more > h3 > .stylesheet-saveButton {
.stylesheet-more {
-moz-box-flex: 1;
-moz-box-direction: reverse;
-moz-box-pack: end;
}
.splitview-nav > li > hgroup.stylesheet-info {

Просмотреть файл

@ -54,8 +54,19 @@
persist="screenX screenY width height sizemode">
<xul:script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
<xul:commandset id="style-editor-commandset">
<xul:command id="style-editor-cmd-close" oncommand="window.close();"/>
</xul:commandset>
<xul:keyset id="style-editor-keyset">
<xul:key id="style-editor-key-close"
key="&closeCmd.key;"
command="style-editor-cmd-close"
modifiers="accel"/>
</xul:keyset>
<xul:box id="style-editor-chrome" class="splitview-root loading">
<xul:box class="splitview-controller" id="stylesheets-controller" persist="width height">
<xul:box class="splitview-controller">
<xul:box class="splitview-main">
<xul:toolbar class="devtools-toolbar">
<xul:toolbarbutton class="style-editor-newButton devtools-toolbarbutton"
@ -68,14 +79,10 @@
tooltiptext="&importButton.tooltip;"
label="&importButton.label;"
disabled="true"/>
<xul:spacer flex="1"/>
<xul:textbox class="splitview-filter devtools-searchinput"
type="search" flex="1"
tooltiptext="&searchInput.tooltip;"
placeholder="&searchInput.placeholder;"/>
</xul:toolbar>
</xul:box>
<xul:box class="splitview-nav-container">
<xul:box id="splitview-resizer-target" class="splitview-nav-container"
persist="width height">
<ol class="splitview-nav" tabindex="0"></ol>
<div class="splitview-nav placeholder empty">
<p><strong>&noStyleSheet.label;</strong></p>
@ -84,13 +91,6 @@
class="style-editor-newButton">&noStyleSheet-tip-action.label;</a>
&noStyleSheet-tip-end.label;</p>
</div>
<div class="splitview-nav placeholder all-filtered">
<p><strong>&searchNoResults.label;</strong></p>
<p>
<a href="#"
class="splitview-filter-clearButton">&searchClearButton.label;</a>
</p>
</div>
</xul:box> <!-- .splitview-nav-container -->
</xul:box> <!-- .splitview-controller -->
<xul:box class="splitview-side-details"/>
@ -101,7 +101,7 @@
title="&visibilityToggle.tooltip;"
accesskey="&saveButton.accesskey;"></a>
<hgroup class="stylesheet-info">
<h1><a class="stylesheet-name" href="#"></a></h1>
<h1><a class="stylesheet-name" href="#"><xul:label crop="start"/></a></h1>
<div class="stylesheet-more">
<h3 class="stylesheet-title"></h3>
<h3 class="stylesheet-rule-count"></h3>
@ -116,12 +116,12 @@
<xul:box id="splitview-tpl-details-stylesheet" class="splitview-details">
<xul:resizer class="splitview-portrait-resizer"
dir="bottom"
element="stylesheets-controller"/>
dir="bottom"
element="splitview-resizer-target"/>
<xul:toolbar id="splitview-details-toolbar" class="devtools-toolbar">
<xul:resizer class="splitview-landscape-resizer"
dir="bottomend"
element="stylesheets-controller"/>
element="splitview-resizer-target"/>
</xul:toolbar>
<xul:box class="stylesheet-editor-input textbox"
data-placeholder="&editorTextbox.placeholder;"/>

Просмотреть файл

@ -53,7 +53,6 @@ _BROWSER_TEST_FILES = \
browser_styleeditor_pretty.js \
browser_styleeditor_readonly.js \
browser_styleeditor_reopen.js \
browser_styleeditor_sv_filter.js \
browser_styleeditor_sv_keynav.js \
browser_styleeditor_sv_resize.js \
four.html \

Просмотреть файл

@ -5,7 +5,10 @@
// http rather than chrome to improve coverage
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
Components.utils.import("resource://gre/modules/FileUtils.jsm");
let tempScope = {};
Components.utils.import("resource://gre/modules/FileUtils.jsm", tempScope);
let FileUtils = tempScope.FileUtils;
const FILENAME = "styleeditor-import-test.css";
const SOURCE = "body{background:red;}";

Просмотреть файл

@ -85,7 +85,7 @@ function testFirstStyleSheetEditor(aChrome, aEditor)
ok(!summary.classList.contains("inline"),
"first stylesheet UI does not have INLINE class");
let name = summary.querySelector(".stylesheet-name").textContent;
let name = summary.querySelector(".stylesheet-name > label").getAttribute("value");
is(name, "simple.css",
"first stylesheet's name is `simple.css`");
@ -113,7 +113,7 @@ function testSecondStyleSheetEditor(aChrome, aEditor)
ok(summary.classList.contains("inline"),
"second stylesheet UI has INLINE class");
let name = summary.querySelector(".stylesheet-name").textContent;
let name = summary.querySelector(".stylesheet-name > label").getAttribute("value");
ok(/^<.*>$/.test(name),
"second stylesheet's name is surrounded by `<>`");

Просмотреть файл

@ -5,7 +5,7 @@
const TESTCASE_URI = TEST_BASE + "simple.html";
const TRANSITION_CLASS = "moz-styleeditor-transitioning";
const TESTCASE_CSS_SOURCE = "body{background-color:red;";
function test()
{
@ -79,9 +79,13 @@ function testEditorAdded(aChrome, aEditor)
is(computedStyle.backgroundColor, "rgb(255, 255, 255)",
"content's background color is initially white");
for each (let c in "body{background-color:red;}") {
for each (let c in TESTCASE_CSS_SOURCE) {
EventUtils.synthesizeKey(c, {}, gChromeWindow);
}
is(aEditor.sourceEditor.getText(), TESTCASE_CSS_SOURCE + "}",
"rule bracket has been auto-closed");
}, gChromeWindow) ;
},

Просмотреть файл

@ -7,7 +7,10 @@ const TESTCASE_URI = TEST_BASE_HTTP + "simple.gz.html";
const Cc = Components.classes;
const Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/FileUtils.jsm");
let tempScope = {};
Components.utils.import("resource://gre/modules/FileUtils.jsm", tempScope);
let FileUtils = tempScope.FileUtils;
function test()

Просмотреть файл

@ -1,101 +0,0 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TESTCASE_URI = TEST_BASE + "simple.html";
function test()
{
waitForExplicitFinish();
addTabAndLaunchStyleEditorChromeWhenLoaded(function (aChrome) {
aChrome.addChromeListener({
onContentAttach: run
});
if (aChrome.isContentAttached) {
run(aChrome);
}
});
content.location = TESTCASE_URI;
}
function getFilteredItemsCount(nav)
{
let matches = nav.querySelectorAll("*.splitview-filtered");
return matches ? matches.length : 0;
}
function run(aChrome)
{
aChrome.editors[0].addActionListener({onAttach: onFirstEditorAttach});
aChrome.editors[1].addActionListener({onAttach: onSecondEditorAttach});
}
function onFirstEditorAttach(aEditor)
{
let filter = gChromeWindow.document.querySelector(".splitview-filter");
// force the command event on input since it is not possible to disable
// the search textbox's timeout.
let forceCommandEvent = function forceCommandEvent() {
let evt = gChromeWindow.document.createEvent("XULCommandEvent");
evt.initCommandEvent("command", true, true, gChromeWindow, 0, false, false,
false, false, null);
filter.dispatchEvent(evt);
}
filter.addEventListener("input", forceCommandEvent, false);
let nav = gChromeWindow.document.querySelector(".splitview-nav");
nav.focus();
is(getFilteredItemsCount(nav), 0,
"there is 0 filtered item initially");
waitForFocus(function () {
// Search [s] (type-on-search since we focused nav above - not filter directly)
EventUtils.synthesizeKey("s", {}, gChromeWindow);
// the search space is "simple.css" and "inline stylesheet #1" (2 sheets)
is(getFilteredItemsCount(nav), 0,
"there is 0 filtered item if searching for 's'");
EventUtils.synthesizeKey("i", {}, gChromeWindow); // Search [si]
is(getFilteredItemsCount(nav), 1, // inline stylesheet is filtered
"there is 1 filtered item if searching for 's'");
// use uppercase to check that filtering is case-insensitive
EventUtils.synthesizeKey("X", {}, gChromeWindow); // Search [siX]
is(getFilteredItemsCount(nav), 2,
"there is 2 filtered items if searching for 's'"); // no match
// clear the search
EventUtils.synthesizeKey("VK_ESCAPE", {}, gChromeWindow);
is(filter.value, "",
"filter is back to empty");
is(getFilteredItemsCount(nav), 0,
"there is 0 filtered item when filter is empty again");
for each (let c in "inline") {
EventUtils.synthesizeKey(c, {}, gChromeWindow);
}
is(getFilteredItemsCount(nav), 1, // simple.css is filtered
"there is 1 filtered item if searching for 'inline'");
// auto-select the only result (enter the editor)
EventUtils.synthesizeKey("VK_ENTER", {}, gChromeWindow);
filter.removeEventListener("input", forceCommandEvent, false);
}, gChromeWindow);
}
function onSecondEditorAttach(aEditor)
{
ok(aEditor.sourceEditor.hasFocus(),
"second editor has been selected and focused automatically.");
finish();
}

Просмотреть файл

@ -1310,6 +1310,7 @@ InplaceEditor.prototype = {
prevent = true;
this.cancelled = true;
this.input.blur();
aEvent.stopPropagation();
} else if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_SPACE) {
// No need for leading spaces here. This is particularly
// noticable when adding a property: it's very natural to type

Просмотреть файл

@ -14,7 +14,6 @@ function createDocument()
'<span class="matches">Some styled text</span>' +
'</div>';
doc.title = "Style Inspector key binding test";
ok(window.StyleInspector, "StyleInspector exists");
stylePanel = new StyleInspector(window);
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
stylePanel.createPanel(false, function() {

Просмотреть файл

@ -9,7 +9,10 @@ let stylePanel;
const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/test/browser_bug683672.html";
Cu.import("resource:///modules/devtools/CssHtmlTree.jsm");
let tempScope = {};
Cu.import("resource:///modules/devtools/CssHtmlTree.jsm", tempScope);
let CssHtmlTree = tempScope.CssHtmlTree;
let PropertyView = tempScope.PropertyView;
function test()
{
@ -22,7 +25,6 @@ function tabLoaded()
{
browser.removeEventListener("load", tabLoaded, true);
doc = content.document;
ok(window.StyleInspector, "StyleInspector exists");
// ok(StyleInspector.isEnabled, "style inspector preference is enabled");
stylePanel = new StyleInspector(window);
Services.obs.addObserver(runTests, "StyleInspector-opened", false);

Просмотреть файл

@ -12,7 +12,6 @@ function createDocument()
doc.body.innerHTML = "<div style='color:blue;'></div>";
doc.title = "Style Inspector Selector Text Test";
ok(window.StyleInspector, "StyleInspector exists");
stylePanel = new StyleInspector(window);

Просмотреть файл

@ -4,7 +4,9 @@
// Test that inherited properties are treated correctly.
Cu.import("resource:///modules/devtools/CssLogic.jsm");
let tempScope = {};
Cu.import("resource:///modules/devtools/CssLogic.jsm", tempScope);
let CssLogic = tempScope.CssLogic;
let doc;

Просмотреть файл

@ -2,7 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource:///modules/devtools/CssRuleView.jsm");
let tempScope = {}
Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let doc = content.document;
@ -118,4 +122,4 @@ function test()
}, true);
content.location = "data:text/html,inline editor tests";
}
}

Просмотреть файл

@ -2,7 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource:///modules/devtools/CssRuleView.jsm");
let tempScope = {}
Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let doc;

Просмотреть файл

@ -2,7 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource:///modules/devtools/CssRuleView.jsm");
let tempScope = {}
Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let doc;

Просмотреть файл

@ -2,7 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource:///modules/devtools/CssRuleView.jsm");
let tempScope = {}
Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let doc;

Просмотреть файл

@ -2,7 +2,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource:///modules/devtools/CssRuleView.jsm");
let tempScope = {}
Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
let CssRuleView = tempScope.CssRuleView;
let _ElementStyle = tempScope._ElementStyle;
let _editableField = tempScope._editableField;
let doc;
let ruleDialog;

Просмотреть файл

@ -26,7 +26,6 @@ function createDocument()
'<p>Inspect using inspectstyle(document.querySelectorAll("span")[0])</p>' +
'</div>';
doc.title = "Style Inspector Test";
ok(window.StyleInspector, "StyleInspector exists");
stylePanel = new StyleInspector(window);
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
stylePanel.createPanel(false, function() {

Просмотреть файл

@ -14,7 +14,6 @@ function createDocument()
'<span id="matches" class="matches">Some styled text</span>' +
'</div>';
doc.title = "Style Inspector Search Filter Test";
ok(window.StyleInspector, "StyleInspector exists");
// ok(StyleInspector.isEnabled, "style inspector preference is enabled");
stylePanel = new StyleInspector(window);
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);

Просмотреть файл

@ -14,7 +14,6 @@ function createDocument()
'<span id="matches" class="matches">Some styled text</span>' +
'</div>';
doc.title = "Style Inspector Default Styles Test";
ok(window.StyleInspector, "StyleInspector exists");
// ok(StyleInspector.isEnabled, "style inspector preference is enabled");
stylePanel = new StyleInspector(window);
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);

Просмотреть файл

@ -13,7 +13,6 @@ function createDocument()
'.matches {color: #F00;}</style>' +
'<span id="matches" class="matches">Some styled text</span>';
doc.title = "Tests that the no results placeholder works properly";
ok(window.StyleInspector, "StyleInspector exists");
stylePanel = new StyleInspector(window);
Services.obs.addObserver(runStyleInspectorTests, "StyleInspector-opened", false);
stylePanel.createPanel(false, function() {

Просмотреть файл

@ -35,8 +35,12 @@
*
* ***** END LICENSE BLOCK ***** */
Cu.import("resource:///modules/devtools/StyleInspector.jsm");
Cu.import("resource://gre/modules/HUDService.jsm");
let tempScope = {};
Cu.import("resource:///modules/devtools/StyleInspector.jsm", tempScope);
Cu.import("resource://gre/modules/HUDService.jsm", tempScope);
let StyleInspector = tempScope.StyleInspector;
let HUDService = tempScope.HUDService;
let ConsoleUtils = tempScope.ConsoleUtils;
function log(aMsg)
{

Просмотреть файл

@ -156,10 +156,15 @@ Tilt.prototype = {
let controller = this.visualizers[aId].controller;
let presenter = this.visualizers[aId].presenter;
TiltUtils.setDocumentZoom(presenter.transforms.zoom);
let content = presenter.contentWindow;
let pageXOffset = content.pageXOffset * TiltUtils.getDocumentZoom();
let pageYOffset = content.pageYOffset * TiltUtils.getDocumentZoom();
controller.removeEventListeners();
controller.arcball.reset([-content.pageXOffset, -content.pageYOffset]);
controller.arcball.reset([-pageXOffset, -pageYOffset]);
presenter.executeDestruction(finalize.bind(this, aId));
}
},

Просмотреть файл

@ -672,6 +672,16 @@ TiltUtils.getDocumentZoom = function TU_getDocumentZoom() {
.gBrowser.selectedBrowser.markupDocumentViewer.fullZoom;
};
/**
* Sets the markup document viewer zoom for the currently selected browser.
*
* @param {Number} the zoom ammount
*/
TiltUtils.setDocumentZoom = function TU_getDocumentZoom(aZoom) {
TiltUtils.getBrowserWindow()
.gBrowser.selectedBrowser.markupDocumentViewer.fullZoom = aZoom;
};
/**
* Performs a garbage collection.
*/

Просмотреть файл

@ -60,11 +60,12 @@ const INVISIBLE_ELEMENTS = {
const STACK_THICKNESS = 15;
const WIREFRAME_COLOR = [0, 0, 0, 0.25];
const INTRO_TRANSITION_DURATION = 80;
const OUTRO_TRANSITION_DURATION = 50;
const INTRO_TRANSITION_DURATION = 50;
const OUTRO_TRANSITION_DURATION = 40;
const INITIAL_Z_TRANSLATION = 400;
const MOUSE_CLICK_THRESHOLD = 10;
const MOUSE_INTRO_DELAY = 10;
const ARCBALL_SENSITIVITY = 0.5;
const ARCBALL_ROTATION_STEP = 0.15;
const ARCBALL_TRANSLATION_STEP = 35;
@ -296,7 +297,7 @@ TiltVisualizer.Presenter = function TV_Presenter(
// call the attached ondraw event handler if specified (by the controller)
if ("function" === typeof this.ondraw) {
this.ondraw();
this.ondraw(this.frames);
}
if (!TiltVisualizer.Prefs.introTransition && !this.isExecutingDestruction) {
@ -480,6 +481,11 @@ TiltVisualizer.Presenter.prototype = {
this.maxTextureSize),
format: "RGB"
});
if ("function" === typeof this.onSetupTexture) {
this.onSetupTexture();
this.onSetupTexture = null;
}
},
/**
@ -502,6 +508,9 @@ TiltVisualizer.Presenter.prototype = {
return;
}
// save the mesh data for future use
this.meshData = aData;
// create the visualization mesh using the vertices, texture coordinates
// and indices computed when traversing the document object model
this.meshStacks = {
@ -524,19 +533,28 @@ TiltVisualizer.Presenter.prototype = {
this.highlightNode(this.inspectorUI.selection);
}
let zoom = TiltUtils.getDocumentZoom();
let width = Math.min(aData.meshWidth * zoom, renderer.width);
let height = Math.min(aData.meshHeight * zoom, renderer.height);
if (!this._initialMeshConfiguration) {
this._initialMeshConfiguration = true;
// set the necessary mesh offsets
this.transforms.offset[0] = -width * 0.5;
this.transforms.offset[1] = -height * 0.5;
let zoom = TiltUtils.getDocumentZoom();
let width = Math.min(aData.meshWidth * zoom, renderer.width);
let height = Math.min(aData.meshHeight * zoom, renderer.height);
// make sure the canvas is opaque now that the initialization is finished
this.canvas.style.background = TiltVisualizerStyle.canvas.background;
// set the necessary mesh offsets
this.transforms.offset[0] = -width * 0.5;
this.transforms.offset[1] = -height * 0.5;
this.drawVisualization();
this.redraw = true;
// make sure the canvas is opaque now that the initialization is finished
this.canvas.style.background = TiltVisualizerStyle.canvas.background;
this.drawVisualization();
this.redraw = true;
}
if ("function" === typeof this.onSetupMesh) {
this.onSetupMesh();
this.onSetupMesh = null;
}
},
/**
@ -626,9 +644,16 @@ TiltVisualizer.Presenter.prototype = {
* the current horizontal coordinate of the mouse
* @param {Number} y
* the current vertical coordinate of the mouse
* @param {Object} aProperties
* an object containing the following properties:
* {Function} onpick: function to be called after picking succeeded
* {Function} onfail: function to be called after picking failed
*/
highlightNodeAt: function TVP_highlightNodeAt(x, y)
highlightNodeAt: function TVP_highlightNodeAt(x, y, aProperties)
{
// make sure the properties parameter is a valid object
aProperties = aProperties || {};
// try to pick a mesh node using the current x, y coordinates
this.pickNode(x, y, {
@ -638,6 +663,10 @@ TiltVisualizer.Presenter.prototype = {
onfail: function TVP_onHighlightFail()
{
this.highlightNodeFor(-1);
if ("function" === typeof aProperties.onfail) {
aProperties.onfail();
}
}.bind(this),
/**
@ -649,6 +678,10 @@ TiltVisualizer.Presenter.prototype = {
onpick: function TVP_onHighlightPick(aIntersection)
{
this.highlightNodeFor(aIntersection.index);
if ("function" === typeof aProperties.onpick) {
aProperties.onpick();
}
}.bind(this)
});
},
@ -701,6 +734,32 @@ TiltVisualizer.Presenter.prototype = {
this.contentWindow.pageYOffset > 0);
},
/**
* Deletes a node from the visualization mesh.
*
* @param {Number} aNodeIndex
* the index of the node in the this.traverseData array;
* if not specified, it will default to the current selection
*/
deleteNode: function TVP_deleteNode(aNodeIndex)
{
// we probably don't want to delete the html or body node.. just sayin'
if ((aNodeIndex = aNodeIndex || this._currentSelection) < 1) {
return;
}
let renderer = this.renderer;
let meshData = this.meshData;
for (let i = 0, k = 36 * aNodeIndex; i < 36; i++) {
meshData.vertices[i + k] = 0;
}
this.meshStacks.vertices = new renderer.VertexBuffer(meshData.vertices, 3);
this.highlight.disabled = true;
this.redraw = true;
},
/**
* Picks a stacked dom node at the x and y screen coordinates and issues
* a callback function with the found intersection.
@ -887,6 +946,9 @@ TiltVisualizer.Controller = function TV_Controller(aCanvas, aPresenter)
this.width = aCanvas.width;
this.height = aCanvas.height;
this.left *= TiltUtils.getDocumentZoom();
this.top *= TiltUtils.getDocumentZoom();
/**
* Arcball used to control the visualization using the mouse.
*/
@ -923,7 +985,6 @@ TiltVisualizer.Controller.prototype = {
// bind commonly used mouse and keyboard events with the controller
canvas.addEventListener("mousedown", this.onMouseDown, false);
canvas.addEventListener("mouseup", this.onMouseUp, false);
canvas.addEventListener("click", this.onMouseClick, false);
canvas.addEventListener("mousemove", this.onMouseMove, false);
canvas.addEventListener("mouseover", this.onMouseOver, false);
canvas.addEventListener("mouseout", this.onMouseOut, false);
@ -946,7 +1007,6 @@ TiltVisualizer.Controller.prototype = {
canvas.removeEventListener("mousedown", this.onMouseDown, false);
canvas.removeEventListener("mouseup", this.onMouseUp, false);
canvas.removeEventListener("click", this.onMouseClick, false);
canvas.removeEventListener("mousemove", this.onMouseMove, false);
canvas.removeEventListener("mouseover", this.onMouseOver, false);
canvas.removeEventListener("mouseout", this.onMouseOut, false);
@ -960,9 +1020,13 @@ TiltVisualizer.Controller.prototype = {
/**
* Function called each frame, updating the visualization camera transforms.
*
* @param {Number} aFrames
* the current animation frame count
*/
update: function TVC_update()
update: function TVC_update(aFrames)
{
this.frames = aFrames;
this.coordinates = this.arcball.update();
this.presenter.setRotation(this.coordinates.rotation);
@ -978,11 +1042,16 @@ TiltVisualizer.Controller.prototype = {
e.preventDefault();
e.stopPropagation();
if (this.frames < MOUSE_INTRO_DELAY) {
return;
}
// calculate x and y coordinates using using the client and target offset
let button = e.which;
this._downX = e.clientX - e.target.offsetLeft;
this._downY = e.clientY - e.target.offsetTop;
this.arcball.mouseDown(this._downX, this._downY, e.which);
this.arcball.mouseDown(this._downX, this._downY, button);
},
/**
@ -993,34 +1062,24 @@ TiltVisualizer.Controller.prototype = {
e.preventDefault();
e.stopPropagation();
if (this.frames < MOUSE_INTRO_DELAY) {
return;
}
// calculate x and y coordinates using using the client and target offset
let button = e.which;
let upX = e.clientX - e.target.offsetLeft;
let upY = e.clientY - e.target.offsetTop;
this.arcball.mouseUp(upX, upY, button);
},
/**
* Called every time a mouse button is clicked.
*/
onMouseClick: function TVC_onMouseClick(e)
{
e.preventDefault();
e.stopPropagation();
// calculate x and y coordinates using using the client and target offset
let button = e.which;
let clickX = e.clientX - e.target.offsetLeft;
let clickY = e.clientY - e.target.offsetTop;
// a click in Tilt is issued only when the mouse pointer stays in
// relatively the same position
if (Math.abs(this._downX - clickX) < MOUSE_CLICK_THRESHOLD &&
Math.abs(this._downY - clickY) < MOUSE_CLICK_THRESHOLD) {
if (Math.abs(this._downX - upX) < MOUSE_CLICK_THRESHOLD &&
Math.abs(this._downY - upY) < MOUSE_CLICK_THRESHOLD) {
this.presenter.highlightNodeAt(clickX, clickY);
this.presenter.highlightNodeAt(upX, upY);
}
this.arcball.mouseUp(upX, upY, button);
},
/**
@ -1031,6 +1090,10 @@ TiltVisualizer.Controller.prototype = {
e.preventDefault();
e.stopPropagation();
if (this.frames < MOUSE_INTRO_DELAY) {
return;
}
// calculate x and y coordinates using using the client and target offset
let moveX = e.clientX - e.target.offsetLeft;
let moveY = e.clientY - e.target.offsetTop;
@ -1098,6 +1161,9 @@ TiltVisualizer.Controller.prototype = {
this.presenter.tiltUI.destroy(this.presenter.tiltUI.currentWindowId, 1);
return;
}
if (code === e.DOM_VK_X) {
this.presenter.deleteNode();
}
if (!e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
e.preventDefault();
@ -1195,21 +1261,21 @@ TiltVisualizer.Arcball = function TV_Arcball(
*/
this._lastRot = quat4.create();
this._deltaRot = quat4.create();
this._currentRot = quat4.create();
this._currentRot = quat4.create(aInitialRot);
/**
* The current camera translation coordinates.
*/
this._lastTrans = vec3.create();
this._deltaTrans = vec3.create();
this._currentTrans = vec3.create();
this._currentTrans = vec3.create(aInitialTrans);
this._zoomAmount = 0;
/**
* Additional rotation and translation vectors.
*/
this._additionalRot = vec3.create(aInitialRot);
this._additionalTrans = vec3.create(aInitialTrans);
this._additionalRot = vec3.create();
this._additionalTrans = vec3.create();
this._deltaAdditionalRot = quat4.create();
this._deltaAdditionalTrans = vec3.create();
@ -1617,21 +1683,22 @@ TiltVisualizer.Arcball.prototype = {
*/
reset: function TVA_reset(aFinalTranslation, aFinalRotation)
{
if ("function" === typeof this.onResetStart) {
this.onResetStart();
this.onResetStart = null;
}
this.cancelMouseEvents();
this.cancelKeyEvents();
this._cancelResetInterval();
if (!this._resetInterval) {
let window = TiltUtils.getBrowserWindow();
let func = this._nextResetIntervalStep.bind(this);
let window = TiltUtils.getBrowserWindow();
let func = this._nextResetIntervalStep.bind(this);
vec3.zero(this._additionalTrans);
vec3.zero(this._additionalRot);
this._save();
this._resetFinalTranslation = vec3.create(aFinalTranslation);
this._resetFinalRotation = quat4.create(aFinalRotation);
this._resetInterval = window.setInterval(func, ARCBALL_RESET_INTERVAL);
}
this._save();
this._resetFinalTranslation = vec3.create(aFinalTranslation);
this._resetFinalRotation = quat4.create(aFinalRotation);
this._resetInterval = window.setInterval(func, ARCBALL_RESET_INTERVAL);
},
/**
@ -1666,10 +1733,12 @@ TiltVisualizer.Arcball.prototype = {
let r = quat4.multiply(quat4.inverse(quat4.create(this._currentRot)), fRot);
// reset the rotation quaternion and translation vector
vec3.lerp(this._currentTrans, t, ARCBALL_RESET_FACTOR);
vec3.lerp(this._currentTrans, t, ARCBALL_RESET_FACTOR / 4);
quat4.slerp(this._currentRot, r, 1 - ARCBALL_RESET_FACTOR);
// also reset any additional transforms by the keyboard or mouse
vec3.scale(this._additionalTrans, ARCBALL_RESET_FACTOR);
vec3.scale(this._additionalRot, ARCBALL_RESET_FACTOR);
this._zoomAmount *= ARCBALL_RESET_FACTOR;
// clear the loop if the all values are very close to zero
@ -1678,7 +1747,9 @@ TiltVisualizer.Arcball.prototype = {
vec3.length(vec3.subtract(this._currentRot, fRot, [])) < fDelta &&
vec3.length(vec3.subtract(this._lastTrans, fTran, [])) < fDelta &&
vec3.length(vec3.subtract(this._deltaTrans, fTran, [])) < fDelta &&
vec3.length(vec3.subtract(this._currentTrans, fTran, [])) < fDelta) {
vec3.length(vec3.subtract(this._currentTrans, fTran, [])) < fDelta &&
vec3.length(this._additionalRot) < fDelta &&
vec3.length(this._additionalTrans) < fDelta) {
this._cancelResetInterval();
}

Просмотреть файл

@ -81,6 +81,11 @@ self.onmessage = function TWP_onMessage(event)
let v2b = [v2f[0], v2f[1], v2f[2] - thickness];
let v3b = [v3f[0], v3f[1], v3f[2] - thickness];
// don't do anything with degenerate quads
if (!v0f[0] && !v1f[0] && !v2f[0] && !v3f[0]) {
continue;
}
// for each triangle in the stack box, check for the intersections
if (self.intersect(v0f, v1f, v2f, ray, hit) || // front left
self.intersect(v0f, v2f, v3f, ray, hit) || // front right

Просмотреть файл

@ -73,6 +73,11 @@ _BROWSER_TEST_FILES = \
browser_tilt_math05.js \
browser_tilt_math06.js \
browser_tilt_math07.js \
browser_tilt_picking.js \
browser_tilt_picking_delete.js \
browser_tilt_picking_highlight01.js \
browser_tilt_picking_highlight02.js \
browser_tilt_picking_highlight03.js \
browser_tilt_utils01.js \
browser_tilt_utils02.js \
browser_tilt_utils03.js \

Просмотреть файл

@ -16,6 +16,7 @@ function test() {
return;
}
requestLongerTimeout(10);
waitForExplicitFinish();
Services.prefs.setBoolPref("accessibility.typeaheadfind", true);
@ -65,6 +66,10 @@ function performTest(canvas, arcball, callback) {
executeSoon(function() {
info("Synthesizing arcball reset key press.");
arcball.onResetStart = function() {
info("Starting arcball reset animation.");
};
arcball.onResetFinish = function() {
ok(isApproxVec(arcball._lastRot, [0, 0, 0, 1]),
"The arcball _lastRot field wasn't reset correctly.");

Просмотреть файл

@ -16,6 +16,7 @@ function test() {
return;
}
requestLongerTimeout(10);
waitForExplicitFinish();
createTab(function() {
@ -63,6 +64,10 @@ function performTest(canvas, arcball, callback) {
executeSoon(function() {
info("Synthesizing arcball reset key press.");
arcball.onResetStart = function() {
info("Starting arcball reset animation.");
};
arcball.onResetFinish = function() {
ok(isApproxVec(arcball._lastRot, [0, 0, 0, 1]),
"The arcball _lastRot field wasn't reset correctly.");

Просмотреть файл

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*global ok, is, info, waitForExplicitFinish, finish, gBrowser */
/*global isTiltEnabled, isWebGLSupported, createTab, createTilt */
/*global Services, InspectorUI, TILT_DESTROYED */
"use strict";
function test() {
if (!isTiltEnabled()) {
info("Skipping picking test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping picking test because WebGL isn't supported.");
return;
}
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
let presenter = instance.presenter;
let canvas = presenter.canvas;
presenter.onSetupMesh = function() {
presenter.pickNode(canvas.width / 2, canvas.height / 2, {
onpick: function(data)
{
ok(data.index > 0,
"Simply picking a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After only picking a node, it shouldn't be highlighted.");
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
InspectorUI.closeInspectorUI();
}
});
};
}
});
});
}
function cleanup() {
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -0,0 +1,67 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*global ok, is, info, waitForExplicitFinish, finish, gBrowser */
/*global isTiltEnabled, isWebGLSupported, createTab, createTilt */
/*global Services, InspectorUI, TILT_DESTROYED */
"use strict";
function test() {
if (!isTiltEnabled()) {
info("Skipping picking delete test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping picking delete test because WebGL isn't supported.");
return;
}
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
let presenter = instance.presenter;
let canvas = presenter.canvas;
presenter.onSetupMesh = function() {
presenter.highlightNodeAt(canvas.width / 2, canvas.height / 2, {
onpick: function()
{
ok(presenter._currentSelection > 0,
"Highlighting a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After highlighting a node, it should be highlighted. D'oh.");
presenter.deleteNode();
ok(presenter._currentSelection > 0,
"Deleting a node shouldn't change the current selection.");
ok(presenter.highlight.disabled,
"After deleting a node, it shouldn't be highlighted.");
let nodeIndex = presenter._currentSelection;
let meshData = presenter.meshData;
for (let i = 0, k = 36 * nodeIndex; i < 36; i++) {
is(meshData.vertices[i + k], 0,
"The stack vertices weren't degenerated properly.");
}
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
InspectorUI.closeInspectorUI();
}
});
};
}
});
});
}
function cleanup() {
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
gBrowser.removeCurrentTab();
finish();
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше