Merge branch 'mozilla-central'

This commit is contained in:
Jacek Caban 2016-03-01 06:21:23 +01:00
commit fb4fc2cfb1
1404 changed files with 12431 additions and 15729 deletions

View File

@ -64,7 +64,6 @@ browser/base/content/test/**
browser/base/content/newtab/**
browser/components/downloads/**
browser/components/feeds/**
browser/components/pocket/**
browser/components/preferences/**
browser/components/privatebrowsing/**
browser/components/sessionstore/**
@ -105,7 +104,6 @@ devtools/client/scratchpad/**
devtools/client/shadereditor/**
devtools/client/shared/**
devtools/client/sourceeditor/**
devtools/client/storage/**
devtools/client/tilt/**
devtools/client/webaudioeditor/**
devtools/client/webconsole/**
@ -182,7 +180,6 @@ toolkit/modules/tests/xpcshell/test_task.js
# Not yet updated
toolkit/components/osfile/**
toolkit/components/passwordmgr/**
# Uses preprocessing
toolkit/content/widgets/videocontrols.xml

View File

@ -21,18 +21,38 @@ using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
TreeWalker::
TreeWalker(Accessible* aContext, nsIContent* aContent, uint32_t aFlags) :
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(aContent),
mFlags(aFlags)
TreeWalker(Accessible* aContext) :
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(nullptr),
mARIAOwnsIdx(0),
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(0)
{
NS_ASSERTION(aContent, "No node for the accessible tree walker!");
mChildFilter = mContext->NoXBLKids() ?
mChildFilter |= mContext->NoXBLKids() ?
nsIContent::eAllButXBL : nsIContent::eAllChildren;
mChildFilter |= nsIContent::eSkipPlaceholderContent;
if (aContent)
PushState(aContent);
mAnchorNode = mContext->IsDoc() ?
mDoc->DocumentNode()->GetRootElement() : mContext->GetContent();
if (mAnchorNode) {
PushState(mAnchorNode);
}
MOZ_COUNT_CTOR(TreeWalker);
}
TreeWalker::
TreeWalker(Accessible* aContext, nsIContent* aAnchorNode, uint32_t aFlags) :
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(aAnchorNode),
mARIAOwnsIdx(0),
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(aFlags)
{
MOZ_ASSERT(aAnchorNode, "No anchor node for the accessible tree walker");
MOZ_ASSERT(mDoc->GetAccessibleOrContainer(aAnchorNode) == mContext,
"Unexpected anchor node was given");
mChildFilter |= mContext->NoXBLKids() ?
nsIContent::eAllButXBL : nsIContent::eAllChildren;
PushState(aAnchorNode);
MOZ_COUNT_CTOR(TreeWalker);
}
@ -48,29 +68,44 @@ TreeWalker::~TreeWalker()
Accessible*
TreeWalker::Next()
{
if (mStateStack.IsEmpty())
return nullptr;
if (mStateStack.IsEmpty()) {
return mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx++);
}
ChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
while (top) {
Accessible* child = nullptr;
bool skipSubtree = false;
while (nsIContent* childNode = Next(top, &child, &skipSubtree)) {
if (child)
while (nsIContent* childNode = top->GetNextChild()) {
bool skipSubtree = false;
Accessible* child = nullptr;
if (mFlags & eWalkCache) {
child = mDoc->GetAccessible(childNode);
}
else if (mContext->IsAcceptableChild(childNode)) {
child = GetAccService()->
GetOrCreateAccessible(childNode, mContext, &skipSubtree);
}
// Ignore the accessible and its subtree if it was repositioned by means
// of aria-owns.
if (child) {
if (child->IsRelocated()) {
continue;
}
return child;
}
// Walk down into subtree to find accessibles.
if (!skipSubtree && childNode->IsElement())
if (!skipSubtree && childNode->IsElement()) {
top = PushState(childNode);
}
}
top = PopState();
}
// If we traversed the whole subtree of the anchor node. Move to next node
// relative anchor node within the context subtree if possible.
if (mFlags != eWalkContextTree)
return nullptr;
return Next();
nsINode* contextNode = mContext->GetNode();
while (mAnchorNode != contextNode) {
@ -80,7 +115,7 @@ TreeWalker::Next()
nsIContent* parent = parentNode->AsElement();
top = PushState(parent);
if (top->mDOMIter.Seek(mAnchorNode)) {
if (top->Seek(mAnchorNode)) {
mAnchorNode = parent;
return Next();
}
@ -92,55 +127,10 @@ TreeWalker::Next()
mAnchorNode = parent;
}
return nullptr;
return Next();
}
nsIContent*
TreeWalker::Next(ChildrenIterator* aIter, Accessible** aAccesible,
bool* aSkipSubtree)
{
nsIContent* childEl = aIter->mDOMIter.GetNextChild();
if (!aAccesible)
return childEl;
*aAccesible = nullptr;
*aSkipSubtree = false;
if (childEl) {
Accessible* accessible = nullptr;
if (mFlags & eWalkCache) {
accessible = mDoc->GetAccessible(childEl);
}
else if (mContext->IsAcceptableChild(childEl)) {
accessible = GetAccService()->
GetOrCreateAccessible(childEl, mContext, aSkipSubtree);
}
// Ignore the accessible and its subtree if it was repositioned by means of
// aria-owns.
if (accessible) {
if (accessible->IsRelocated()) {
*aSkipSubtree = true;
} else {
*aAccesible = accessible;
}
}
return childEl;
}
// At last iterate over ARIA owned children.
Accessible* parent = mDoc->GetAccessible(aIter->mDOMIter.Parent());
if (parent) {
Accessible* child = mDoc->ARIAOwnedAt(parent, aIter->mARIAOwnsIdx++);
if (child) {
*aAccesible = child;
return child->GetContent();
}
}
return nullptr;
}
TreeWalker::ChildrenIterator*
dom::AllChildrenIterator*
TreeWalker::PopState()
{
size_t length = mStateStack.Length();

View File

@ -33,14 +33,20 @@ public:
};
/**
* Constructor
* Used to navigate and create if needed the accessible children.
*/
explicit TreeWalker(Accessible* aContext);
/**
* Used to navigate the accessible children relative to the anchor.
*
* @param aContext [in] container accessible for the given node, used to
* define accessible context
* @param aNode [in] the node the search will be prepared relative to
* @param aAnchorNode [in] the node the search will be prepared relative to
* @param aFlags [in] flags (see enum above)
*/
TreeWalker(Accessible* aContext, nsIContent* aNode, uint32_t aFlags = 0);
TreeWalker(Accessible* aContext, nsIContent* aAnchorNode, uint32_t aFlags = 0);
~TreeWalker();
/**
@ -57,37 +63,30 @@ private:
TreeWalker(const TreeWalker&);
TreeWalker& operator =(const TreeWalker&);
struct ChildrenIterator {
ChildrenIterator(nsIContent* aNode, uint32_t aFilter) :
mDOMIter(aNode, aFilter), mARIAOwnsIdx(0) { }
dom::AllChildrenIterator mDOMIter;
uint32_t mARIAOwnsIdx;
};
nsIContent* Next(ChildrenIterator* aIter, Accessible** aAccessible = nullptr,
bool* aSkipSubtree = nullptr);
/**
* Create new state for the given node and push it on top of stack.
*
* @note State stack is used to navigate up/down the DOM subtree during
* accessible children search.
*/
ChildrenIterator* PushState(nsIContent* aContent)
dom::AllChildrenIterator* PushState(nsIContent* aContent)
{
return mStateStack.AppendElement(ChildrenIterator(aContent, mChildFilter));
return mStateStack.AppendElement(
dom::AllChildrenIterator(aContent, mChildFilter));
}
/**
* Pop state from stack.
*/
ChildrenIterator* PopState();
dom::AllChildrenIterator* PopState();
DocAccessible* mDoc;
Accessible* mContext;
nsIContent* mAnchorNode;
AutoTArray<ChildrenIterator, 20> mStateStack;
AutoTArray<dom::AllChildrenIterator, 20> mStateStack;
uint32_t mARIAOwnsIdx;
int32_t mChildFilter;
uint32_t mFlags;
};

View File

@ -2541,10 +2541,9 @@ Accessible::LastRelease()
void
Accessible::CacheChildren()
{
DocAccessible* doc = Document();
NS_ENSURE_TRUE_VOID(doc);
NS_ENSURE_TRUE_VOID(Document());
TreeWalker walker(this, mContent);
TreeWalker walker(this);
Accessible* child = nullptr;
while ((child = walker.Next()) && AppendChild(child));

View File

@ -1248,6 +1248,12 @@ DocAccessible::GetAccessibleOrContainer(nsINode* aNode) const
if (!(currNode = parent)) break;
}
// HTML comboboxes have no-content list accessible as an intermediate
// containing all options.
if (accessible && accessible->IsHTMLCombobox()) {
return accessible->FirstChild();
}
return accessible;
}
@ -1418,25 +1424,6 @@ if (!aNode->IsContent() || !aNode->AsContent()->IsHTMLElement(nsGkAtoms::area))
return GetAccessible(aNode);
}
////////////////////////////////////////////////////////////////////////////////
// Accessible protected
void
DocAccessible::CacheChildren()
{
// Search for accessible children starting from the document element since
// some web pages tend to insert elements under it rather than document body.
dom::Element* rootElm = mDocumentNode->GetRootElement();
if (!rootElm)
return;
TreeWalker walker(this, rootElm);
Accessible* child = nullptr;
while ((child = walker.Next())) {
AppendChild(child);
}
}
////////////////////////////////////////////////////////////////////////////////
// Protected members
@ -1725,11 +1712,6 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
// there is no HTML body element.
}
// HTML comboboxes have no-content list accessible as an intermidiate
// containing all options.
if (container->IsHTMLCombobox())
container = container->FirstChild();
// We have a DOM/layout change under the container accessible, and its tree
// might need an update. Since DOM/layout change of the element may affect
// on the accessibleness of adjacent elements (for example, insertion of

View File

@ -359,9 +359,6 @@ protected:
void LastRelease();
// Accessible
virtual void CacheChildren() override;
// DocAccessible
virtual nsresult AddEventListeners();
virtual nsresult RemoveEventListeners();

View File

@ -114,35 +114,12 @@ HTMLSelectListAccessible::SetCurrentItem(Accessible* aItem)
true);
}
////////////////////////////////////////////////////////////////////////////////
// HTMLSelectListAccessible: Accessible protected
void
HTMLSelectListAccessible::CacheChildren()
bool
HTMLSelectListAccessible::IsAcceptableChild(nsIContent* aEl) const
{
// Cache accessibles for <optgroup> and <option> DOM decendents as children,
// as well as the accessibles for them. Avoid whitespace text nodes. We want
// to count all the <optgroup>s and <option>s as children because we want
// a flat tree under the Select List.
for (nsIContent* childContent = mContent->GetFirstChild(); childContent;
childContent = childContent->GetNextSibling()) {
if (!childContent->IsHTMLElement()) {
continue;
}
if (childContent->IsAnyOfHTMLElements(nsGkAtoms::option,
nsGkAtoms::optgroup)) {
// Get an accessible for option or optgroup and cache it.
RefPtr<Accessible> accessible =
GetAccService()->GetOrCreateAccessible(childContent, this);
if (accessible)
AppendChild(accessible);
}
}
return aEl->IsAnyOfHTMLElements(nsGkAtoms::option, nsGkAtoms::optgroup);
}
////////////////////////////////////////////////////////////////////////////////
// HTMLSelectOptionAccessible
////////////////////////////////////////////////////////////////////////////////

View File

@ -51,10 +51,7 @@ public:
virtual Accessible* CurrentItem() override;
virtual void SetCurrentItem(Accessible* aItem) override;
protected:
// Accessible
virtual void CacheChildren() override;
virtual bool IsAcceptableChild(nsIContent* aEl) const override;
};
/*

View File

@ -251,11 +251,13 @@ enum CheckboxValue {
{
mozAccessible* nativeAcc = nil;
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
Accessible* accTab = accWrap->GetSelectedItem(0);
accTab->GetNativeInterface((void**)&nativeAcc);
if (Accessible* accTab = accWrap->GetSelectedItem(0)) {
accTab->GetNativeInterface((void**)&nativeAcc);
}
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
ProxyAccessible* proxyTab = proxy->GetSelectedItem(0);
nativeAcc = GetNativeFromProxy(proxyTab);
if (ProxyAccessible* proxyTab = proxy->GetSelectedItem(0)) {
nativeAcc = GetNativeFromProxy(proxyTab);
}
}
return nativeAcc;

View File

@ -102,7 +102,7 @@
}
}
// gA11yEventDumpToConsole = true;
//gA11yEventDumpToConsole = true;
function doTest()
{

View File

@ -42,5 +42,4 @@ skip-if = true
[tab-close-on-startup.xpi]
[toolkit-require-reload.xpi]
[translators.xpi]
[unpacked.xpi]
[unsafe-content-script.xpi]

View File

@ -17,7 +17,9 @@ exports.main = function main(options, callbacks) {
assert.ok('loadReason' in options, 'loadReason is in options provided by main');
assert.equal(typeof callbacks.print, 'function', 'callbacks.print is a function');
assert.equal(typeof callbacks.quit, 'function', 'callbacks.quit is a function');
assert.equal(options.loadReason, 'install', 'options.loadReason is install');
// Re-enable when bug 1251664 is fixed
//assert.equal(options.loadReason, 'install', 'options.loadReason is install');
}
require('sdk/test/runner').runTestsFromModule({exports: tests});

View File

@ -1,18 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { packed } = require("sdk/self");
const url = require("sdk/url");
exports["test self.packed"] = function (assert) {
assert.ok(!packed, "require('sdk/self').packed is correct");
}
exports["test url.toFilename"] = function (assert) {
assert.ok(/.*main\.js$/.test(url.toFilename(module.uri)),
"url.toFilename() on resource: URIs should work");
}
require("sdk/test/runner").runTestsFromModule(module);

View File

@ -1,6 +0,0 @@
{
"id": "test-url@jetpack",
"unpack": true,
"main": "./main.js",
"version": "0.0.1"
}

View File

@ -31,7 +31,7 @@ externalProtocolChkMsg=Remember my choice for all links of this type.
externalProtocolLaunchBtn=Launch application
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences.
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.

View File

@ -1201,10 +1201,6 @@ pref("security.sandbox.content.level", 2);
pref("security.sandbox.content.level", 0);
#endif
// ID (a UUID when set by gecko) that is used as a per profile suffix to a low
// integrity temp directory.
pref("security.sandbox.content.tempDirSuffix", "");
#if defined(MOZ_STACKWALKING)
// This controls the depth of stack trace that is logged when Windows sandbox
// logging is turned on. This is only currently available for the content
@ -1227,6 +1223,15 @@ pref("security.sandbox.windows.log.stackTraceDepth", 0);
pref("security.sandbox.content.level", 1);
#endif
#if defined(XP_MACOSX) || defined(XP_WIN)
#if defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
// ID (a UUID when set by gecko) that is used to form the name of a
// sandbox-writable temporary directory to be used by content processes
// when a temporary writable file is required in a level 1 sandbox.
pref("security.sandbox.content.tempDirSuffix", "");
#endif
#endif
// This pref governs whether we attempt to work around problems caused by
// plugins using OS calls to manipulate the cursor while running out-of-
// process. These workarounds all involve intercepting (hooking) certain

View File

@ -414,9 +414,6 @@
<h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
<h1 id="et_nssFailure2">&nssFailure2.title;</h1>
<h1 id="et_nssBadCert">&nssBadCert.title;</h1>
<h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
<h1 id="et_unwantedBlocked">&unwantedBlocked.title;</h1>
<h1 id="et_forbiddenBlocked">&forbiddenBlocked.title;</h1>
<h1 id="et_cspBlocked">&cspBlocked.title;</h1>
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
@ -444,9 +441,6 @@
<div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
<div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
<div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
<div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
<div id="ed_unwantedBlocked">&unwantedBlocked.longDesc;</div>
<div id="ed_forbiddenBlocked">&forbiddenBlocked.longDesc;</div>
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>

View File

@ -88,7 +88,7 @@
case "malwareBlocked" :
error = "malware";
break;
case "phishingBlocked" :
case "deceptiveBlocked" :
error = "phishing";
break;
case "unwantedBlocked" :
@ -200,7 +200,7 @@
<!-- Error Title -->
<div id="errorTitle">
<h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title;</h1>
<h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title2;</h1>
<h1 id="errorTitleText_malware">&safeb.blocked.malwarePage.title;</h1>
<h1 id="errorTitleText_unwanted">&safeb.blocked.unwantedPage.title;</h1>
<h1 id="errorTitleText_forbidden">&safeb.blocked.forbiddenPage.title2;</h1>
@ -210,7 +210,7 @@
<!-- Short Description -->
<div id="errorShortDesc">
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc;</p>
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc2;</p>
<p id="errorShortDescText_malware">&safeb.blocked.malwarePage.shortDesc;</p>
<p id="errorShortDescText_unwanted">&safeb.blocked.unwantedPage.shortDesc;</p>
<p id="errorShortDescText_forbidden">&safeb.blocked.forbiddenPage.shortDesc2;</p>
@ -218,7 +218,7 @@
<!-- Long Description -->
<div id="errorLongDesc">
<p id="errorLongDescText_phishing">&safeb.blocked.phishingPage.longDesc;</p>
<p id="errorLongDescText_phishing">&safeb.blocked.phishingPage.longDesc2;</p>
<p id="errorLongDescText_malware">&safeb.blocked.malwarePage.longDesc;</p>
<p id="errorLongDescText_unwanted">&safeb.blocked.unwantedPage.longDesc;</p>
</div>

View File

@ -4,15 +4,9 @@
<menu id="charsetMenu"
label="&charsetMenu2.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenu2.accesskey;"
#endif
oncommand="BrowserSetForcedCharacterSet(event.target.getAttribute('charset'));"
#ifdef OMIT_ACCESSKEYS
onpopupshowing="CharsetMenu.build(event.target, false);"
#else
onpopupshowing="CharsetMenu.build(event.target);"
#endif
onpopupshown="UpdateCurrentCharset(this);">
<menupopup>
</menupopup>

View File

@ -15,7 +15,7 @@ var gSafeBrowsing = {
// will point to the internal error page we loaded instead.
var docURI = gBrowser.selectedBrowser.documentURI;
var isPhishingPage =
docURI && docURI.spec.startsWith("about:blocked?e=phishingBlocked");
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
// Show/hide the appropriate menu item.
document.getElementById("menu_HelpPopup_reportPhishingtoolmenu")

View File

@ -160,7 +160,7 @@ XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
XPCOMUtils.defineLazyGetter(this, "DeveloperToolbar", function() {
let { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
let { DeveloperToolbar } = require("devtools/client/shared/developer-toolbar");
return new DeveloperToolbar(window, document.getElementById("developer-toolbar"));
return new DeveloperToolbar(window);
});
XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function() {
@ -2915,10 +2915,10 @@ var BrowserOnClick = {
}
};
} else if (reason === 'phishing') {
title = gNavigatorBundle.getString("safebrowsing.reportedWebForgery");
title = gNavigatorBundle.getString("safebrowsing.deceptiveSite");
buttons[1] = {
label: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.label"),
accessKey: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.accessKey"),
label: gNavigatorBundle.getString("safebrowsing.notADeceptiveSiteButton.label"),
accessKey: gNavigatorBundle.getString("safebrowsing.notADeceptiveSiteButton.accessKey"),
callback: function() {
openUILinkIn(gSafeBrowsing.getReportURL('PhishMistake'), 'tab');
}
@ -5492,9 +5492,9 @@ function BrowserCharsetReload()
}
function UpdateCurrentCharset(target) {
let selectedCharset = CharsetMenu.foldCharset(gBrowser.selectedBrowser.characterSet);
for (let menuItem of target.getElementsByTagName("menuitem")) {
let isSelected = menuItem.getAttribute("charset") ===
CharsetMenu.foldCharset(gBrowser.selectedBrowser.characterSet);
let isSelected = menuItem.getAttribute("charset") === selectedCharset;
menuItem.setAttribute("checked", isSelected);
}
}

View File

@ -1109,29 +1109,6 @@
<vbox id="browser-bottombox" layer="true">
<notificationbox id="global-notificationbox" notificationside="bottom"/>
<toolbar id="developer-toolbar"
hidden="true">
#ifdef XP_MACOSX
<toolbarbutton id="developer-toolbar-closebutton"
class="devtools-closebutton"
oncommand="DeveloperToolbar.hide();"
tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
#endif
<stack class="gclitoolbar-stack-node" flex="1">
<textbox class="gclitoolbar-input-node" rows="1"/>
<hbox class="gclitoolbar-complete-node"/>
</stack>
<toolbarbutton id="developer-toolbar-toolbox-button"
class="developer-toolbar-button"
observes="devtoolsMenuBroadcaster_DevToolbox"
tooltiptext="&devToolbarToolsButton.tooltip;"/>
#ifndef XP_MACOSX
<toolbarbutton id="developer-toolbar-closebutton"
class="devtools-closebutton"
oncommand="DeveloperToolbar.hide();"
tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
#endif
</toolbar>
</vbox>
<svg:svg height="0">

View File

@ -18,15 +18,15 @@
</broadcasterset>
<menupopup id="menu_HelpPopup">
<menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
label="&reportPhishSiteMenu.title2;"
accesskey="&reportPhishSiteMenu.accesskey;"
label="&reportDeceptiveSiteMenu.title;"
accesskey="&reportDeceptiveSiteMenu.accesskey;"
insertbefore="aboutSeparator"
observes="reportPhishingBroadcaster"
oncommand="openUILink(gSafeBrowsing.getReportURL('Phish'), event);"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
label="&safeb.palm.notforgery.label2;"
accesskey="&reportPhishSiteMenu.accesskey;"
label="&safeb.palm.notdeceptive.label;"
accesskey="&reportDeceptiveSiteMenu.accesskey;"
insertbefore="aboutSeparator"
observes="reportPhishingErrorBroadcaster"
oncommand="openUILinkIn(gSafeBrowsing.getReportURL('PhishMistake'), 'tab');"

View File

@ -288,9 +288,8 @@ Sanitizer.prototype = {
}),
promiseClearPluginCookies: Task.async(function* (range) {
const phInterface = Ci.nsIPluginHost;
const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
let ph = Cc["@mozilla.org/plugin/host;1"].getService(phInterface);
const FLAG_CLEAR_ALL = Ci.nsIPluginHost.FLAG_CLEAR_ALL;
let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
// Determine age range in seconds. (-1 means clear all.) We don't know
// that range[1] is actually now, so we compute age range based
@ -299,6 +298,13 @@ Sanitizer.prototype = {
if (!range || age >= 0) {
let tags = ph.getPluginTags();
for (let tag of tags) {
let refObj = {};
let probe = "";
if (/\bFlash\b/.test(tag.name)) {
probe = tag.loaded ? "FX_SANITIZE_LOADED_FLASH"
: "FX_SANITIZE_UNLOADED_FLASH";
TelemetryStopwatch.start(probe, refObj);
}
try {
let rv = yield new Promise(resolve =>
ph.clearSiteData(tag, null, FLAG_CLEAR_ALL, age, resolve)
@ -309,8 +315,14 @@ Sanitizer.prototype = {
ph.clearSiteData(tag, null, FLAG_CLEAR_ALL, -1, resolve)
);
}
if (probe) {
TelemetryStopwatch.finish(probe, refObj);
}
} catch (ex) {
// Ignore errors from plug-ins
if (probe) {
TelemetryStopwatch.cancel(probe, refObj);
}
}
}
}

View File

@ -1,11 +1,28 @@
"use strict";
const {PlacesTestUtils} =
Cu.import("resource://testing-common/PlacesTestUtils.jsm", {});
let tab;
let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
let oldShowFavicons;
add_task(function* test_notificationClose() {
let pm = Services.perms;
pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
let notificationURI = makeURI(notificationURL);
pm.add(notificationURI, "desktop-notification", pm.ALLOW_ACTION);
oldShowFavicons = Services.prefs.getBoolPref("alerts.showFavicons");
Services.prefs.setBoolPref("alerts.showFavicons", true);
yield PlacesTestUtils.addVisits(notificationURI);
let faviconURI = yield new Promise(resolve => {
let faviconURI = makeURI("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC");
PlacesUtils.favicons.setAndFetchFaviconForPage(notificationURI, faviconURI,
true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
(faviconURI, iconSize, iconData, mimeType) => resolve(faviconURI),
Services.scriptSecurityManager.getSystemPrincipal());
});
yield BrowserTestUtils.withNewTab({
gBrowser,
@ -26,6 +43,8 @@ add_task(function* test_notificationClose() {
is(alertTitleLabel.value, "Test title", "Title text of notification should be present");
let alertTextLabel = alertWindow.document.getElementById("alertTextLabel");
is(alertTextLabel.textContent, "Test body 2", "Body text of notification should be present");
let alertIcon = alertWindow.document.getElementById("alertIcon");
is(alertIcon.src, faviconURI.spec, "Icon of notification should be present");
let alertCloseButton = alertWindow.document.querySelector(".alertCloseButton");
is(alertCloseButton.localName, "toolbarbutton", "close button found");
@ -47,4 +66,7 @@ add_task(function* test_notificationClose() {
add_task(function* cleanup() {
Services.perms.remove(makeURI(notificationURL), "desktop-notification");
if (typeof oldShowFavicons == "boolean") {
Services.prefs.setBoolPref("alerts.showFavicons", oldShowFavicons);
}
});

View File

@ -142,7 +142,6 @@ skip-if = e10s # Bug 1093153 - no about:home support yet
[browser_alltabslistener.js]
[browser_audioTabIcon.js]
[browser_autocomplete_a11y_label.js]
skip-if = e10s # Bug 1101993 - times out for unknown reasons when run in the dir (works on its own)
[browser_autocomplete_cursor.js]
[browser_autocomplete_edit_completed.js]
[browser_autocomplete_enter_race.js]
@ -367,7 +366,7 @@ skip-if = buildapp == 'mulet'
[browser_popup_blocker.js]
skip-if = (os == 'linux') || (e10s && debug) # Frequent bug 1081925 and bug 1125520 failures
[browser_printpreview.js]
skip-if = buildapp == 'mulet' || e10s # Bug 1101973 - breaks the next test in e10s, and may be responsible for later timeout after logging "Error: Channel closing: too late to send/recv, messages will be lost"
skip-if = buildapp == 'mulet'
[browser_private_browsing_window.js]
skip-if = buildapp == 'mulet'
[browser_private_no_prompt.js]
@ -393,11 +392,11 @@ skip-if = buildapp == 'mulet'
[browser_sanitizeDialog.js]
skip-if = buildapp == 'mulet'
[browser_save_link-perwindowpb.js]
skip-if = buildapp == 'mulet' || e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly
skip-if = buildapp == 'mulet'
[browser_save_private_link_perwindowpb.js]
skip-if = buildapp == 'mulet' || e10s # e10s: Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly
skip-if = buildapp == 'mulet'
[browser_save_link_when_window_navigates.js]
skip-if = buildapp == 'mulet' || e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly
skip-if = buildapp == 'mulet'
[browser_save_video.js]
skip-if = buildapp == 'mulet'
[browser_save_video_frame.js]

View File

@ -51,6 +51,7 @@ function* test_bookmarks_popup({isNewBookmark, popupShowFn, popupEditFn,
if (!shouldAutoClose) {
yield new Promise(resolve => setTimeout(resolve, 400));
is(bookmarkPanel.state, "open", "Panel should still be 'open' for non-autoclose");
}
let hiddenPromise = promisePopupHidden(bookmarkPanel);
@ -144,7 +145,8 @@ add_task(function* panel_shown_for_new_bookmarks_mouseover_mouseout() {
yield new Promise(resolve => setTimeout(resolve, 400));
is(bookmarkPanel.state, "open", "Panel should still be open on mouseover");
},
*popupHideFn() {
let mouseOutPromise = new Promise(resolve => {
bookmarkPanel.addEventListener("mouseout", function onmouseout() {
bookmarkPanel.removeEventListener("mouseout", onmouseout);
@ -158,7 +160,7 @@ add_task(function* panel_shown_for_new_bookmarks_mouseover_mouseout() {
yield mouseOutPromise;
info("Got mouseout event, should autoclose now");
},
shouldAutoClose: true,
shouldAutoClose: false,
isBookmarkRemoved: false,
});
});
@ -208,7 +210,7 @@ add_task(function* panel_shown_for_new_bookmark_keypress_no_autoclose() {
});
});
add_task(function* contextmenu_new_bookmark_click_no_autoclose() {
add_task(function* contextmenu_new_bookmark_keypress_no_autoclose() {
yield test_bookmarks_popup({
isNewBookmark: true,
*popupShowFn(browser) {
@ -227,7 +229,7 @@ add_task(function* contextmenu_new_bookmark_click_no_autoclose() {
yield awaitPopupHidden;
},
popupEditFn() {
bookmarkPanelTitle.click();
EventUtils.sendChar("VK_TAB", window);
},
shouldAutoClose: false,
popupHideFn() {

View File

@ -1,14 +1,23 @@
let ourTab;
function test() {
waitForExplicitFinish();
ok(!gInPrintPreviewMode,
"Should NOT be in print preview mode at starting this tests");
// Skip access key test on platforms which don't support access key.
if (!/Win|Linux/.test(navigator.platform)) {
openPrintPreview(testClosePrintPreviewWithEscKey);
} else {
openPrintPreview(testClosePrintPreviewWithAccessKey);
}
BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home", true).then(function(tab) {
ourTab = tab;
ok(!gInPrintPreviewMode,
"Should NOT be in print preview mode at starting this tests");
// Skip access key test on platforms which don't support access key.
if (!/Win|Linux/.test(navigator.platform)) {
openPrintPreview(testClosePrintPreviewWithEscKey);
} else {
openPrintPreview(testClosePrintPreviewWithAccessKey);
}
});
}
function tidyUp() {
BrowserTestUtils.removeTab(ourTab).then(finish);
}
function testClosePrintPreviewWithAccessKey() {
@ -34,7 +43,7 @@ function testClosePrintPreviewWithClosingWindowShortcutKey() {
checkPrintPreviewClosed(function (aSucceeded) {
ok(aSucceeded,
"print preview mode should be finished by closing window shortcut key");
finish();
tidyUp();
});
}

View File

@ -35,7 +35,7 @@ function triggerSave(aWindow, aCallback) {
{ type: "contextmenu", button: 2 },
testBrowser.contentWindow);
info("right clicked!");
}, testBrowser.contentWindow);
}, testBrowser);
}, false);
function contextMenuOpened(event) {

View File

@ -106,7 +106,7 @@ function test() {
EventUtils.synthesizeMouseAtCenter(img,
{ type: "contextmenu", button: 2 },
aWindow.gBrowser.contentWindow);
}, aWindow.gBrowser.selectedBrowser.contentWindow);
}, aWindow.gBrowser.selectedBrowser);
});
}

View File

@ -99,7 +99,6 @@ skip-if = os == "linux" # Intermittent failures
[browser_962884_opt_in_disable_hyphens.js]
[browser_963639_customizing_attribute_non_customizable_toolbar.js]
[browser_967000_button_charEncoding.js]
skip-if = e10s # Bug 1088710
[browser_967000_button_feeds.js]
[browser_967000_button_sync.js]
[browser_968447_bookmarks_toolbar_items_in_panel.js]
@ -127,7 +126,6 @@ skip-if = os == "linux"
[browser_987185_syncButton.js]
[browser_987492_window_api.js]
[browser_987640_charEncoding.js]
skip-if = e10s # Bug 1088710
[browser_988072_sidebar_events.js]
[browser_989338_saved_placements_not_resaved.js]
[browser_989751_subviewbutton_class.js]

View File

@ -6,9 +6,6 @@
const TEST_PAGE = "http://mochi.test:8888/browser/browser/components/customizableui/test/support/test_967000_charEncoding_page.html";
var newTab;
var initialLocation = gBrowser.currentURI.spec;
add_task(function*() {
info("Check Character Encoding button functionality");
@ -28,14 +25,15 @@ add_task(function*() {
PanelUI.hide();
yield panelHidePromise;
newTab = gBrowser.selectedTab;
yield promiseTabLoadEvent(newTab, TEST_PAGE)
let newTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE, true, true);
yield PanelUI.show();
ok(!charEncodingButton.hasAttribute("disabled"), "The Character encoding button gets enabled");
charEncodingButton.click();
let characterEncodingView = document.getElementById("PanelUI-characterEncodingView");
let subviewShownPromise = subviewShown(characterEncodingView);
charEncodingButton.click();
yield subviewShownPromise;
ok(characterEncodingView.hasAttribute("current"), "The Character encoding panel is displayed");
let pinnedEncodings = document.getElementById("PanelUI-characterEncodingView-pinned");
@ -53,14 +51,12 @@ add_task(function*() {
panelHidePromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHidePromise;
yield BrowserTestUtils.removeTab(newTab);
});
add_task(function* asyncCleanup() {
// reset the panel to the default state
yield resetCustomization();
ok(CustomizableUI.inDefaultState, "The UI is in default state again.");
// restore the initial location
gBrowser.addTab(initialLocation);
gBrowser.removeTab(newTab);
});

View File

@ -5,7 +5,6 @@
"use strict";
const TEST_PAGE = "http://mochi.test:8888/browser/browser/components/customizableui/test/support/test_967000_charEncoding_page.html";
var newTab = null;
add_task(function*() {
info("Check Character Encoding panel functionality");
@ -14,14 +13,15 @@ add_task(function*() {
CustomizableUI.addWidgetToArea("characterencoding-button",
CustomizableUI.AREA_PANEL);
newTab = gBrowser.addTab(TEST_PAGE);
yield promiseTabLoadEvent(gBrowser.selectedTab, TEST_PAGE);
let newTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE, true, true);
yield PanelUI.show();
let charEncodingButton = document.getElementById("characterencoding-button");
charEncodingButton.click();
let characterEncodingView = document.getElementById("PanelUI-characterEncodingView");
let subviewShownPromise = subviewShown(characterEncodingView);
charEncodingButton.click();
yield subviewShownPromise;
let checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
let initialEncoding = checkedButtons[0];
is(initialEncoding.getAttribute("label"), "Unicode", "The unicode encoding is initially selected");
@ -50,13 +50,11 @@ add_task(function*() {
charEncodingButton.click();
checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
is(checkedButtons[0].getAttribute("label"), "Unicode", "The encoding was reset to Unicode");
yield BrowserTestUtils.removeTab(newTab);
});
add_task(function* asyncCleanup() {
// reset the panel to the default state
yield resetCustomization();
ok(CustomizableUI.inDefaultState, "The UI is in default state again.");
// remove the added tab
gBrowser.removeTab(newTab);
});

View File

@ -377,34 +377,50 @@ DistributionCustomizer.prototype = {
let localizedStr = Cc["@mozilla.org/pref-localizedstring;1"].
createInstance(Ci.nsIPrefLocalizedString);
if (sections["LocalizablePreferences"]) {
for (let key of enumerate(this._ini.getKeys("LocalizablePreferences"))) {
var usedLocalizablePreferences = [];
if (sections["LocalizablePreferences-" + this._locale]) {
for (let key of enumerate(this._ini.getKeys("LocalizablePreferences-" + this._locale))) {
try {
let value = eval(this._ini.getString("LocalizablePreferences", key));
value = value.replace(/%LOCALE%/g, this._locale);
value = value.replace(/%LANGUAGE%/g, this._language);
localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
let value = eval(this._ini.getString("LocalizablePreferences-" + this._locale, key));
if (value !== undefined) {
localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
}
usedLocalizablePreferences.push(key);
} catch (e) { /* ignore bad prefs and move on */ }
}
}
if (sections["LocalizablePreferences-" + this._language]) {
for (let key of enumerate(this._ini.getKeys("LocalizablePreferences-" + this._language))) {
if (usedLocalizablePreferences.indexOf(key) > -1) {
continue;
}
try {
let value = eval(this._ini.getString("LocalizablePreferences-" + this._language, key));
localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
if (value !== undefined) {
localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
}
usedLocalizablePreferences.push(key);
} catch (e) { /* ignore bad prefs and move on */ }
}
}
if (sections["LocalizablePreferences-" + this._locale]) {
for (let key of enumerate(this._ini.getKeys("LocalizablePreferences-" + this._locale))) {
if (sections["LocalizablePreferences"]) {
for (let key of enumerate(this._ini.getKeys("LocalizablePreferences"))) {
if (usedLocalizablePreferences.indexOf(key) > -1) {
continue;
}
try {
let value = eval(this._ini.getString("LocalizablePreferences-" + this._locale, key));
localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
let value = eval(this._ini.getString("LocalizablePreferences", key));
if (value !== undefined) {
value = value.replace(/%LOCALE%/g, this._locale);
value = value.replace(/%LANGUAGE%/g, this._language);
localizedStr.data = "data:text/plain," + key + "=" + value;
defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
}
} catch (e) { /* ignore bad prefs and move on */ }
}
}

View File

@ -397,16 +397,20 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
}).api(),
create: function(createProperties) {
return new Promise(resolve => {
return new Promise((resolve, reject) => {
function createInWindow(window) {
let url;
if (createProperties.url !== null) {
url = context.uri.resolve(createProperties.url);
} else {
url = window.BROWSER_NEW_TAB_URL;
if (!context.checkLoadURL(url, {dontReportErrors: true})) {
reject({message: `URL not allowed: ${url}`});
return;
}
}
let tab = window.gBrowser.addTab(url);
let tab = window.gBrowser.addTab(url || window.BROWSER_NEW_TAB_URL);
let active = true;
if (createProperties.active !== null) {
@ -460,10 +464,23 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
update: function(tabId, updateProperties) {
let tab = tabId !== null ? TabManager.getTab(tabId) : TabManager.activeTab;
let tabbrowser = tab.ownerDocument.defaultView.gBrowser;
if (updateProperties.url !== null) {
tab.linkedBrowser.loadURI(updateProperties.url);
if (!tab) {
return Promise.reject({message: `No tab found with tabId: ${tabId}`});
}
let tabbrowser = tab.ownerDocument.defaultView.gBrowser;
if (updateProperties.url !== null) {
let url = context.uri.resolve(updateProperties.url);
if (!context.checkLoadURL(url, {dontReportErrors: true})) {
return Promise.reject({message: `URL not allowed: ${url}`});
}
tab.linkedBrowser.loadURI(url);
}
if (updateProperties.active !== null) {
if (updateProperties.active) {
tabbrowser.selectedTab = tab;
@ -626,7 +643,7 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
message, recipient);
},
_execute: function(tabId, details, kind) {
_execute: function(tabId, details, kind, method) {
let tab = tabId !== null ? TabManager.getTab(tabId) : TabManager.activeTab;
let mm = tab.linkedBrowser.messageManager;
@ -635,6 +652,15 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
css: [],
};
// We require a `code` or a `file` property, but we can't accept both.
if ((details.code === null) == (details.file === null)) {
return Promise.reject({message: `${method} requires either a 'code' or a 'file' property, but not both`});
}
if (details.frameId !== null && details.allFrames) {
return Promise.reject({message: `'frameId' and 'allFrames' are mutually exclusive`});
}
let recipient = {
innerWindowID: tab.linkedBrowser.innerWindowID,
};
@ -660,22 +686,27 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
if (details.allFrames) {
options.all_frames = details.allFrames;
}
if (details.frameId !== null) {
options.frame_id = details.frameId;
}
if (details.matchAboutBlank) {
options.match_about_blank = details.matchAboutBlank;
}
if (details.runAt !== null) {
options.run_at = details.runAt;
} else {
options.run_at = "document_idle";
}
return context.sendMessage(mm, "Extension:Execute", {options}, recipient);
},
executeScript: function(tabId, details) {
return self.tabs._execute(tabId, details, "js");
return self.tabs._execute(tabId, details, "js", "executeScript");
},
insertCSS: function(tabId, details) {
return self.tabs._execute(tabId, details, "css");
return self.tabs._execute(tabId, details, "css", "insertCSS");
},
connect: function(tabId, connectInfo) {

View File

@ -7,6 +7,8 @@ support-files =
context_tabs_onUpdated_iframe.html
file_popup_api_injection_a.html
file_popup_api_injection_b.html
file_iframe_document.html
file_iframe_document.sjs
[browser_ext_simple.js]
[browser_ext_commands.js]
@ -29,12 +31,15 @@ support-files =
[browser_ext_tabs_executeScript.js]
[browser_ext_tabs_executeScript_good.js]
[browser_ext_tabs_executeScript_bad.js]
[browser_ext_tabs_executeScript_runAt.js]
[browser_ext_tabs_insertCSS.js]
[browser_ext_tabs_query.js]
[browser_ext_tabs_getCurrent.js]
[browser_ext_tabs_create.js]
[browser_ext_tabs_create_invalid_url.js]
[browser_ext_tabs_duplicate.js]
[browser_ext_tabs_update.js]
[browser_ext_tabs_update_url.js]
[browser_ext_tabs_onUpdated.js]
[browser_ext_tabs_sendMessage.js]
[browser_ext_tabs_move.js]
@ -43,4 +48,4 @@ support-files =
[browser_ext_windows_update.js]
[browser_ext_contentscript_connect.js]
[browser_ext_tab_runtimeConnect.js]
[browser_ext_webNavigation_getFrames.js]
[browser_ext_webNavigation_getFrames.js]

View File

@ -0,0 +1,66 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
function* testTabsCreateInvalidURL(tabsCreateURL) {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
},
background: function() {
browser.test.sendMessage("ready");
browser.test.onMessage.addListener((msg, tabsCreateURL) => {
browser.tabs.create({url: tabsCreateURL}, (tab) => {
browser.test.assertEq(undefined, tab, "on error tab should be undefined");
browser.test.assertTrue(/URL not allowed/.test(browser.runtime.lastError.message),
"runtime.lastError should report the expected error message");
// Remove the opened tab is any.
if (tab) {
browser.tabs.remove(tab.id);
}
browser.test.sendMessage("done");
});
});
},
});
yield extension.startup();
yield extension.awaitMessage("ready");
info(`test tab.create on invalid URL "${tabsCreateURL}"`);
extension.sendMessage("start", tabsCreateURL);
yield extension.awaitMessage("done");
yield extension.unload();
}
add_task(function* () {
info("Start testing tabs.create on invalid URLs");
let dataURLPage = `data:text/html,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>data url page</h1>
</body>
</html>`;
let testCases = [
{tabsCreateURL: "about:addons"},
{tabsCreateURL: "javascript:console.log('tabs.update execute javascript')"},
{tabsCreateURL: dataURLPage},
];
for (let {tabsCreateURL} of testCases) {
yield* testTabsCreateInvalidURL(tabsCreateURL);
}
info("done");
});

View File

@ -8,33 +8,134 @@ add_task(function* testExecuteScript() {
let messageManagersSize = MessageChannel.messageManagers.size;
let responseManagersSize = MessageChannel.responseManagers.size;
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
const BASE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/";
const URL = BASE + "file_iframe_document.html";
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL, true);
function background() {
browser.tabs.executeScript({
file: "script.js",
code: "42",
}, result => {
browser.test.assertEq(42, result, "Expected callback result");
browser.test.sendMessage("got result", result);
});
browser.tabs.query({active: true, currentWindow: true}).then(tabs => {
return browser.webNavigation.getAllFrames({tabId: tabs[0].id});
}).then(frames => {
browser.test.log(`FRAMES: ${frames[1].frameId} ${JSON.stringify(frames)}\n`);
return Promise.all([
browser.tabs.executeScript({
code: "42",
}).then(result => {
browser.test.assertEq(42, result, "Expected callback result");
}),
browser.tabs.executeScript({
file: "script2.js",
}, result => {
browser.test.assertEq(27, result, "Expected callback result");
browser.test.sendMessage("got callback", result);
});
browser.tabs.executeScript({
file: "script.js",
code: "42",
}).then(result => {
browser.test.fail("Expected not to be able to execute a script with both file and code");
}, error => {
browser.test.assertTrue(/a 'code' or a 'file' property, but not both/.test(error.message),
"Got expected error");
}),
browser.runtime.onMessage.addListener(message => {
browser.test.assertEq("script ran", message, "Expected runtime message");
browser.test.sendMessage("got message", message);
browser.tabs.executeScript({
file: "script.js",
}).then(result => {
browser.test.assertEq(undefined, result, "Expected callback result");
}),
browser.tabs.executeScript({
file: "script2.js",
}).then(result => {
browser.test.assertEq(27, result, "Expected callback result");
}),
browser.tabs.executeScript({
code: "location.href;",
allFrames: true,
}).then(result => {
browser.test.assertTrue(Array.isArray(result), "Result is an array");
browser.test.assertEq(2, result.length, "Result has correct length");
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result[0]), "First result is correct");
browser.test.assertEq("http://mochi.test:8888/", result[1], "Second result is correct");
}),
browser.tabs.executeScript({
code: "location.href;",
runAt: "document_end",
}).then(result => {
browser.test.assertTrue(typeof(result) == "string", "Result is a string");
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result), "Result is correct");
}),
browser.tabs.executeScript({
code: "window",
}).then(result => {
browser.test.fail("Expected error when returning non-structured-clonable object");
}, error => {
browser.test.assertEq("Script returned non-structured-clonable data",
error.message, "Got expected error");
}),
browser.tabs.executeScript({
code: "Promise.resolve(window)",
}).then(result => {
browser.test.fail("Expected error when returning non-structured-clonable object");
}, error => {
browser.test.assertEq("Script returned non-structured-clonable data",
error.message, "Got expected error");
}),
browser.tabs.executeScript({
code: "Promise.resolve(42)",
}).then(result => {
browser.test.assertEq(42, result, "Got expected promise resolution value as result");
}),
browser.tabs.executeScript({
code: "location.href;",
runAt: "document_end",
allFrames: true,
}).then(result => {
browser.test.assertTrue(Array.isArray(result), "Result is an array");
browser.test.assertEq(2, result.length, "Result has correct length");
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result[0]), "First result is correct");
browser.test.assertEq("http://mochi.test:8888/", result[1], "Second result is correct");
}),
browser.tabs.executeScript({
code: "location.href;",
frameId: frames[0].frameId,
}).then(result => {
browser.test.assertTrue(/\/file_iframe_document\.html$/.test(result), `Result for frameId[0] is correct: ${result}`);
}),
browser.tabs.executeScript({
code: "location.href;",
frameId: frames[1].frameId,
}).then(result => {
browser.test.assertEq("http://mochi.test:8888/", result, "Result for frameId[1] is correct");
}),
new Promise(resolve => {
browser.runtime.onMessage.addListener(message => {
browser.test.assertEq("script ran", message, "Expected runtime message");
resolve();
});
}),
]);
}).then(() => {
browser.test.notifyPass("executeScript");
}).catch(e => {
browser.test.fail(`Error: ${e} :: ${e.stack}`);
browser.test.notifyFail("executeScript");
});
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["http://mochi.test/"],
"permissions": ["http://mochi.test/", "webNavigation"],
},
background,
@ -50,9 +151,7 @@ add_task(function* testExecuteScript() {
yield extension.startup();
yield extension.awaitMessage("got result");
yield extension.awaitMessage("got callback");
yield extension.awaitMessage("got message");
yield extension.awaitFinish("executeScript");
yield extension.unload();

View File

@ -0,0 +1,110 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
/**
* These tests ensure that the runAt argument to tabs.executeScript delays
* script execution until the document has reached the correct state.
*
* Since tests of this nature are especially race-prone, it relies on a
* server-JS script to delay the completion of our test page's load cycle long
* enough for us to attempt to load our scripts in the earlies phase we support.
*
* And since we can't actually rely on that timing, it retries any attempts that
* fail to load as early as expected, but don't load at any illegal time.
*/
add_task(function* testExecuteScript() {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", true);
function background() {
let tab;
const BASE = "http://mochi.test:8888/browser/browser/components/extensions/test/browser/";
const URL = BASE + "file_iframe_document.sjs";
const MAX_TRIES = 10;
let tries = 0;
function again() {
if (tries++ == MAX_TRIES) {
return Promise.reject(new Error("Max tries exceeded"));
}
let loadingPromise = new Promise(resolve => {
browser.tabs.onUpdated.addListener(function listener(tabId, changed, tab_) {
if (tabId == tab.id && changed.status == "loading" && tab_.url == URL) {
browser.tabs.onUpdated.removeListener(listener);
resolve();
}
});
});
// TODO: Test allFrames and frameId.
return browser.tabs.update({url: URL}).then(() => {
return loadingPromise;
}).then(() => {
return Promise.all([
// Send the executeScript requests in the reverse order that we expect
// them to execute in, to avoid them passing only because of timing
// races.
browser.tabs.executeScript({
code: "document.readyState",
runAt: "document_idle",
}),
browser.tabs.executeScript({
code: "document.readyState",
runAt: "document_end",
}),
browser.tabs.executeScript({
code: "document.readyState",
runAt: "document_start",
}),
].reverse());
}).then(states => {
browser.test.log(`Got states: ${states}`);
// Make sure that none of our scripts executed earlier than expected,
// regardless of retries.
browser.test.assertTrue(states[1] == "interactive" || states[1] == "complete",
`document_end state is valid: ${states[1]}`);
browser.test.assertTrue(states[2] == "complete",
`document_idle state is valid: ${states[2]}`);
// If we have the earliest valid states for each script, we're done.
// Otherwise, try again.
if (states[0] != "loading" || states[1] != "interactive" || states[2] != "complete") {
return again();
}
});
}
browser.tabs.query({active: true, currentWindow: true}).then(tabs => {
tab = tabs[0];
return again();
}).then(() => {
browser.test.notifyPass("executeScript-runAt");
}).catch(e => {
browser.test.fail(`Error: ${e} :: ${e.stack}`);
browser.test.notifyFail("executeScript-runAt");
});
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["http://mochi.test/", "tabs"],
},
background,
});
yield extension.startup();
yield extension.awaitFinish("executeScript-runAt");
yield extension.unload();
yield BrowserTestUtils.removeTab(tab);
});

View File

@ -13,39 +13,20 @@ add_task(function* testExecuteScript() {
function background() {
let promises = [
{
background: "rgb(0, 0, 0)",
foreground: "rgb(255, 192, 203)",
promise: resolve => {
browser.tabs.insertCSS({
file: "file1.css",
code: "* { background: black }",
}, result => {
browser.test.assertEq(undefined, result, "Expected callback result");
resolve();
});
},
},
{
background: "rgb(0, 0, 0)",
background: "transparent",
foreground: "rgb(0, 113, 4)",
promise: resolve => {
browser.tabs.insertCSS({
promise: () => {
return browser.tabs.insertCSS({
file: "file2.css",
}, result => {
browser.test.assertEq(undefined, result, "Expected callback result");
resolve();
});
},
},
{
background: "rgb(42, 42, 42)",
foreground: "rgb(0, 113, 4)",
promise: resolve => {
browser.tabs.insertCSS({
promise: () => {
return browser.tabs.insertCSS({
code: "* { background: rgb(42, 42, 42) }",
}, result => {
browser.test.assertEq(undefined, result, "Expected callback result");
resolve();
});
},
},
@ -58,23 +39,29 @@ add_task(function* testExecuteScript() {
function next() {
if (!promises.length) {
browser.test.notifyPass("insertCSS");
return;
}
let {promise, background, foreground} = promises.shift();
new Promise(promise).then(() => {
browser.tabs.executeScript({
return promise().then(result => {
browser.test.assertEq(undefined, result, "Expected callback result");
return browser.tabs.executeScript({
code: `(${checkCSS})()`,
}, result => {
browser.test.assertEq(background, result[0], "Expected background color");
browser.test.assertEq(foreground, result[1], "Expected foreground color");
next();
});
}).then(result => {
browser.test.assertEq(background, result[0], "Expected background color");
browser.test.assertEq(foreground, result[1], "Expected foreground color");
return next();
});
}
next();
next().then(() => {
browser.test.notifyPass("insertCSS");
}).catch(e => {
browser.test.fail(`Error: ${e} :: ${e.stack}`);
browser.test.notifyFailure("insertCSS");
});
}
let extension = ExtensionTestUtils.loadExtension({
@ -85,7 +72,6 @@ add_task(function* testExecuteScript() {
background,
files: {
"file1.css": "* { color: pink }",
"file2.css": "* { color: rgb(0, 113, 4) }",
},
});

View File

@ -159,7 +159,7 @@ add_task(function* test_url() {
browser.test.assertEq(tabId, tab.id, "Check tab id");
browser.test.log("onUpdate: " + JSON.stringify(changeInfo));
if ("url" in changeInfo) {
browser.test.assertEq("about:preferences", changeInfo.url,
browser.test.assertEq("about:blank", changeInfo.url,
"Check changeInfo.url");
browser.tabs.onUpdated.removeListener(onUpdated);
// Remove created tab.
@ -168,7 +168,7 @@ add_task(function* test_url() {
return;
}
});
browser.tabs.update(tab.id, {url: "about:preferences"});
browser.tabs.update(tab.id, {url: "about:blank"});
});
});
});

View File

@ -0,0 +1,120 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
function* testTabsUpdateURL(existentTabURL, tabsUpdateURL, isErrorExpected) {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
},
files: {
"tab.html": `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>tab page</h1>
</body>
</html>
`.trim(),
},
background: function() {
browser.test.sendMessage("ready", browser.runtime.getURL("tab.html"));
browser.test.onMessage.addListener((msg, tabsUpdateURL, isErrorExpected) => {
let onTabsUpdated = (tab) => {
if (isErrorExpected) {
browser.test.fail(`tabs.update with URL ${tabsUpdateURL} should be rejected`);
} else {
browser.test.assertTrue(tab, "on success the tab should be defined");
}
};
let onTabsUpdateError = (error) => {
if (!isErrorExpected) {
browser.test.fails(`tabs.update with URL ${tabsUpdateURL} should not be rejected`);
} else {
browser.test.assertTrue(/^URL not allowed/.test(error.message),
"tabs.update should be rejected with the expected error message");
}
};
let onTabsUpdateDone = () => browser.test.sendMessage("done");
browser.tabs.query({lastFocusedWindow: true}, (tabs) => {
browser.tabs.update(tabs[1].id, {url: tabsUpdateURL})
.then(onTabsUpdated, onTabsUpdateError)
.then(onTabsUpdateDone);
});
});
},
});
yield extension.startup();
let mozExtTabURL = yield extension.awaitMessage("ready");
if (tabsUpdateURL == "self") {
tabsUpdateURL = mozExtTabURL;
}
info(`tab.update URL "${tabsUpdateURL}" on tab with URL "${existentTabURL}"`);
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, existentTabURL);
extension.sendMessage("start", tabsUpdateURL, isErrorExpected);
yield extension.awaitMessage("done");
yield BrowserTestUtils.removeTab(tab1);
yield extension.unload();
}
add_task(function* () {
info("Start testing tabs.update on javascript URLs");
let dataURLPage = `data:text/html,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>data url page</h1>
</body>
</html>`;
let checkList = [
{
tabsUpdateURL: "http://example.net",
isErrorExpected: false,
},
{
tabsUpdateURL: "self",
isErrorExpected: false,
},
{
tabsUpdateURL: "about:addons",
isErrorExpected: true,
},
{
tabsUpdateURL: "javascript:console.log('tabs.update execute javascript')",
isErrorExpected: true,
},
{
tabsUpdateURL: dataURLPage,
isErrorExpected: true,
},
];
let testCases = checkList
.map((check) => Object.assign({}, check, {existentTabURL: "about:blank"}));
for (let {existentTabURL, tabsUpdateURL, isErrorExpected} of testCases) {
yield* testTabsUpdateURL(existentTabURL, tabsUpdateURL, isErrorExpected);
}
info("done");
});

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<iframe src="/"></iframe>
</body>
</html>

View File

@ -0,0 +1,40 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80 ft=javascript: */
"use strict";
// This script slows the load of an HTML document so that we can reliably test
// all phases of the load cycle supported by the extension API.
/* eslint-disable no-unused-vars */
const DELAY = 1 * 1000; // Delay one second before completing the request.
const Ci = Components.interfaces;
let nsTimer = Components.Constructor("@mozilla.org/timer;1", "nsITimer", "initWithCallback");
let timer;
function handleRequest(request, response) {
response.processAsync();
response.setHeader("Content-Type", "text/html", false);
response.write(`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
`);
// Note: We need to store a reference to the timer to prevent it from being
// canceled when it's GCed.
timer = new nsTimer(() => {
response.write(`
<iframe src="/"></iframe>
</body>
</html>`);
response.finish();
}, DELAY, Ci.nsITimer.TYPE_ONE_SHOT);
}

View File

@ -972,7 +972,7 @@ PlacesController.prototype = {
PlacesUtils.bhistory.removePages(URIslice, URIslice.length);
Services.tm.mainThread.dispatch(() => gen.next(),
Ci.nsIThread.DISPATCH_NORMAL);
yield unefined;
yield undefined;
}
}
let gen = pagesChunkGenerator(URIs);

View File

@ -177,14 +177,28 @@ var SessionFileInternal = {
},
}),
// `true` once `write` has succeeded at last once.
// Used for error-reporting.
_hasWriteEverSucceeded: false,
// Number of attempted calls to `write`.
// Note that we may have _attempts > _successes + _failures,
// if attempts never complete.
// Used for error reporting.
_attempts: 0,
// Number of successful calls to `write`.
// Used for error reporting.
_successes: 0,
// Number of failed calls to `write`.
// Used for error reporting.
_failures: 0,
// Resolved once initialization is complete.
// The promise never rejects.
_deferredInitialized: PromiseUtils.defer(),
// `true` once we have started initialization, i.e. once something
// has been scheduled that will eventually resolve `_deferredInitialized`.
_initializationStarted: false,
// The ID of the latest version of Gecko for which we have an upgrade backup
// or |undefined| if no upgrade backup was ever written.
get latestUpgradeBackupID() {
@ -195,7 +209,10 @@ var SessionFileInternal = {
}
},
// Find the correct session file, read it and setup the worker.
read: Task.async(function* () {
this._initializationStarted = true;
let result;
let noFilesFound = true;
// Attempt to load by order of priority from the various backups
@ -205,6 +222,7 @@ var SessionFileInternal = {
try {
let path = this.Paths[key];
let startMs = Date.now();
let source = yield OS.File.read(path, { encoding: "utf-8" });
let parsed = JSON.parse(source);
@ -259,19 +277,39 @@ var SessionFileInternal = {
result.noFilesFound = noFilesFound;
// Initialize the worker to let it handle backups and also
// Initialize the worker (in the background) to let it handle backups and also
// as a workaround for bug 964531.
let initialized = SessionWorker.post("init", [result.origin, this.Paths, {
let promiseInitialized = SessionWorker.post("init", [result.origin, this.Paths, {
maxUpgradeBackups: Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3),
maxSerializeBack: Preferences.get(PREF_MAX_SERIALIZE_BACK, 10),
maxSerializeForward: Preferences.get(PREF_MAX_SERIALIZE_FWD, -1)
}]);
initialized.catch(Promise.reject).then(() => this._deferredInitialized.resolve());
promiseInitialized.catch(err => {
// Ensure that we report errors but that they do not stop us.
Promise.reject(err);
}).then(() => this._deferredInitialized.resolve());
return result;
}),
// Post a message to the worker, making sure that it has been initialized
// first.
_postToWorker: Task.async(function*(...args) {
if (!this._initializationStarted) {
// Initializing the worker is somewhat complex, as proper handling of
// backups requires us to first read and check the session. Consequently,
// the only way to initialize the worker is to first call `this.read()`.
// The call to `this.read()` causes background initialization of the worker.
// Initialization will be complete once `this._deferredInitialized.promise`
// resolves.
this.read();
}
yield this._deferredInitialized.promise;
return SessionWorker.post(...args)
}),
write: function (aData) {
if (RunState.isClosed) {
return Promise.reject(new Error("SessionFile is closed"));
@ -288,14 +326,15 @@ var SessionFileInternal = {
let performShutdownCleanup = isFinalWrite &&
!sessionStartup.isAutomaticRestoreEnabled();
this._attempts++;
let options = {isFinalWrite, performShutdownCleanup};
let promise = this._deferredInitialized.promise.then(() => SessionWorker.post("write", [aData, options]));
let promise = this._postToWorker("write", [aData, options]);
// Wait until the write is done.
promise = promise.then(msg => {
// Record how long the write took.
this._recordTelemetry(msg.telemetry);
this._hasWriteEverSucceeded = true;
this._successes++;
if (msg.result.upgradeBackup) {
// We have just completed a backup-on-upgrade, store the information
// in preferences.
@ -305,6 +344,7 @@ var SessionFileInternal = {
}, err => {
// Catch and report any errors.
console.error("Could not write session state file ", err, err.stack);
this._failures++;
// By not doing anything special here we ensure that |promise| cannot
// be rejected anymore. The shutdown/cleanup code at the end of the
// function will thus always be executed.
@ -318,7 +358,9 @@ var SessionFileInternal = {
{
fetchState: () => ({
options,
hasEverSucceeded: this._hasWriteEverSucceeded
attempts: this._attempts,
successes: this._successes,
failures: this._failures,
})
});
@ -336,7 +378,7 @@ var SessionFileInternal = {
},
wipe: function () {
return this._deferredInitialized.promise.then(() => SessionWorker.post("wipe"));
return this._postToWorker("wipe");
},
_recordTelemetry: function(telemetry) {

View File

@ -151,8 +151,10 @@ var SessionStorageInternal = {
try {
let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
storage = storageManager.getStorage(window, aPrincipal);
storage.length; // XXX: Bug 1232955 - storage.length can throw, catch that failure
} catch (e) {
// sessionStorage might throw if it's turned off, see bug 458954
storage = null;
}
if (storage && storage.length) {

View File

@ -52,6 +52,7 @@ support-files =
restore_redirect_http.html^headers^
restore_redirect_js.html
restore_redirect_target.html
browser_1234021_page.html
#NB: the following are disabled
# browser_464620_a.html
@ -220,3 +221,4 @@ run-if = e10s
[browser_async_window_flushing.js]
[browser_forget_async_closings.js]
[browser_sessionStoreContainer.js]
[browser_1234021.js]

View File

@ -0,0 +1,18 @@
"use strict";
const PREF = 'network.cookie.cookieBehavior';
const PAGE_URL = 'http://mochi.test:8888/browser/' +
'browser/components/sessionstore/test/browser_1234021_page.html';
const BEHAVIOR_REJECT = 2;
add_task(function* test() {
yield pushPrefs([PREF, BEHAVIOR_REJECT]);
yield BrowserTestUtils.withNewTab({
gBrowser: gBrowser,
url: PAGE_URL
}, function* handler(aBrowser) {
yield TabStateFlusher.flush(aBrowser);
ok(true, "Flush didn't time out");
});
});

View File

@ -0,0 +1,6 @@
<!doctype html>
<html>
<script>
sessionStorage
</script>
</html>

View File

@ -15,18 +15,21 @@ distribution.test.bool.false=false
[LocalizablePreferences]
distribution.test.locale="%LOCALE%"
distribution.test.reset="Set"
distribution.test.locale.set="First Set"
distribution.test.language.set="First Set"
distribution.test.language.reset="Preference Set"
distribution.test.locale.reset="Preference Set"
distribution.test.locale.set="Preference Set"
distribution.test.language.set="Preference Set"
[LocalizablePreferences-en]
distribution.test.language.en="en"
distribution.test.language.set="Second Set"
distribution.test.language.reset=
distribution.test.language.set="Language Set"
distribution.test.locale.set="Language Set"
[LocalizablePreferences-en-US]
distribution.test.locale.en-US="en-US"
distribution.test.reset=
distribution.test.locale.set="Second Set"
distribution.test.locale.reset=
distribution.test.locale.set="Locale Set"
[LocalizablePreferences-de]
distribution.test.locale.de="de"

View File

@ -71,11 +71,14 @@ add_task(function* () {
Assert.equal(Services.prefs.getComplexValue("distribution.test.language.en", Ci.nsIPrefLocalizedString).data, "en");
Assert.equal(Services.prefs.getComplexValue("distribution.test.locale.en-US", Ci.nsIPrefLocalizedString).data, "en-US");
Assert.throws(() => Services.prefs.getComplexValue("distribution.test.locale.de", Ci.nsIPrefLocalizedString));
// This value was never set because of the empty language specific pref
Assert.throws(() => Services.prefs.getComplexValue("distribution.test.language.reset", Ci.nsIPrefLocalizedString));
// This value was never set because of the empty locale specific pref
// This testcase currently fails - the value is set to "undefined" - it should not be set at all (throw)
// Assert.throws(() => Services.prefs.getComplexValue("distribution.test.reset", Ci.nsIPrefLocalizedString));
// This value was overriden by a locale specific setting
Assert.equal(Services.prefs.getComplexValue("distribution.test.locale.set", Ci.nsIPrefLocalizedString).data, "Second Set");
// This value was overriden by a language specific setting
Assert.equal(Services.prefs.getComplexValue("distribution.test.language.set", Ci.nsIPrefLocalizedString).data, "Second Set");
Assert.throws(() => Services.prefs.getComplexValue("distribution.test.locale.reset", Ci.nsIPrefLocalizedString));
// This value was overridden by a locale specific setting
Assert.equal(Services.prefs.getComplexValue("distribution.test.locale.set", Ci.nsIPrefLocalizedString).data, "Locale Set");
// This value was overridden by a language specific setting
Assert.equal(Services.prefs.getComplexValue("distribution.test.language.set", Ci.nsIPrefLocalizedString).data, "Language Set");
// Language should not override locale
Assert.notEqual(Services.prefs.getComplexValue("distribution.test.locale.set", Ci.nsIPrefLocalizedString).data, "Language Set");
});

View File

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.4.83
Current extension version is: 1.4.95

View File

@ -288,7 +288,7 @@ ChromeActions.prototype = {
try {
// contentDisposition/contentDispositionFilename is readonly before FF18
channel.contentDisposition = Ci.nsIChannel.DISPOSITION_ATTACHMENT;
if (self.contentDispositionFilename) {
if (self.contentDispositionFilename && !data.isAttachment) {
channel.contentDispositionFilename = self.contentDispositionFilename;
} else {
channel.contentDispositionFilename = filename;

View File

@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdf = {}));
// Use strict in our context only - users might not want it
'use strict';
var pdfjsVersion = '1.4.83';
var pdfjsBuild = '0629fd0';
var pdfjsVersion = '1.4.95';
var pdfjsBuild = '2b813c0';
var pdfjsFilePath =
typeof document !== 'undefined' && document.currentScript ?
@ -407,6 +407,17 @@ var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
font: 'font'
};
// Gets the file name from a given URL.
function getFilenameFromUrl(url) {
var anchor = url.indexOf('#');
var query = url.indexOf('?');
var end = Math.min(
anchor > 0 ? anchor : url.length,
query > 0 ? query : url.length);
return url.substring(url.lastIndexOf('/', end) + 1, end);
}
PDFJS.getFilenameFromUrl = getFilenameFromUrl;
// Combines two URLs. The baseUrl shall be absolute URL. If the url is an
// absolute URL, it will be returned as is.
function combineUrl(baseUrl, url) {
@ -1537,6 +1548,7 @@ exports.combineUrl = combineUrl;
exports.createPromiseCapability = createPromiseCapability;
exports.deprecated = deprecated;
exports.error = error;
exports.getFilenameFromUrl = getFilenameFromUrl;
exports.getLookupTableFactory = getLookupTableFactory;
exports.info = info;
exports.isArray = isArray;
@ -1577,6 +1589,7 @@ var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
var AnnotationType = sharedUtil.AnnotationType;
var Util = sharedUtil.Util;
var addLinkAttributes = sharedUtil.addLinkAttributes;
var getFilenameFromUrl = sharedUtil.getFilenameFromUrl;
var warn = sharedUtil.warn;
var CustomStyle = displayDOMUtils.CustomStyle;
@ -1587,6 +1600,7 @@ var CustomStyle = displayDOMUtils.CustomStyle;
* @property {PDFPage} page
* @property {PageViewport} viewport
* @property {IPDFLinkService} linkService
* @property {DownloadManager} downloadManager
*/
/**
@ -1628,6 +1642,9 @@ AnnotationElementFactory.prototype =
case AnnotationType.STRIKEOUT:
return new StrikeOutAnnotationElement(parameters);
case AnnotationType.FILEATTACHMENT:
return new FileAttachmentAnnotationElement(parameters);
default:
return new AnnotationElement(parameters);
}
@ -1646,6 +1663,7 @@ var AnnotationElement = (function AnnotationElementClosure() {
this.page = parameters.page;
this.viewport = parameters.viewport;
this.linkService = parameters.linkService;
this.downloadManager = parameters.downloadManager;
if (isRenderable) {
this.container = this._createContainer();
@ -1744,6 +1762,43 @@ var AnnotationElement = (function AnnotationElementClosure() {
return container;
},
/**
* Create a popup for the annotation's HTML element. This is used for
* annotations that do not have a Popup entry in the dictionary, but
* are of a type that works with popups (such as Highlight annotations).
*
* @private
* @param {HTMLSectionElement} container
* @param {HTMLDivElement|HTMLImageElement|null} trigger
* @param {Object} data
* @memberof AnnotationElement
*/
_createPopup:
function AnnotationElement_createPopup(container, trigger, data) {
// If no trigger element is specified, create it.
if (!trigger) {
trigger = document.createElement('div');
trigger.style.height = container.style.height;
trigger.style.width = container.style.width;
container.appendChild(trigger);
}
var popupElement = new PopupElement({
container: container,
trigger: trigger,
color: data.color,
title: data.title,
contents: data.contents,
hideWrapper: true
});
var popup = popupElement.render();
// Position the popup next to the annotation's container.
popup.style.left = container.style.width;
container.appendChild(popup);
},
/**
* Render the annotation's HTML element in the empty container.
*
@ -1872,20 +1927,7 @@ var TextAnnotationElement = (function TextAnnotationElementClosure() {
image.dataset.l10nArgs = JSON.stringify({type: this.data.name});
if (!this.data.hasPopup) {
var popupElement = new PopupElement({
container: this.container,
trigger: image,
color: this.data.color,
title: this.data.title,
contents: this.data.contents,
hideWrapper: true
});
var popup = popupElement.render();
// Position the popup next to the Text annotation's container.
popup.style.left = image.style.width;
this.container.appendChild(popup);
this._createPopup(this.container, image, this.data);
}
this.container.appendChild(image);
@ -2162,7 +2204,9 @@ var PopupElement = (function PopupElementClosure() {
var HighlightAnnotationElement = (
function HighlightAnnotationElementClosure() {
function HighlightAnnotationElement(parameters) {
AnnotationElement.call(this, parameters, true);
var isRenderable = !!(parameters.data.hasPopup ||
parameters.data.title || parameters.data.contents);
AnnotationElement.call(this, parameters, isRenderable);
}
Util.inherit(HighlightAnnotationElement, AnnotationElement, {
@ -2175,6 +2219,11 @@ var HighlightAnnotationElement = (
*/
render: function HighlightAnnotationElement_render() {
this.container.className = 'highlightAnnotation';
if (!this.data.hasPopup) {
this._createPopup(this.container, null, this.data);
}
return this.container;
}
});
@ -2189,7 +2238,9 @@ var HighlightAnnotationElement = (
var UnderlineAnnotationElement = (
function UnderlineAnnotationElementClosure() {
function UnderlineAnnotationElement(parameters) {
AnnotationElement.call(this, parameters, true);
var isRenderable = !!(parameters.data.hasPopup ||
parameters.data.title || parameters.data.contents);
AnnotationElement.call(this, parameters, isRenderable);
}
Util.inherit(UnderlineAnnotationElement, AnnotationElement, {
@ -2202,6 +2253,11 @@ var UnderlineAnnotationElement = (
*/
render: function UnderlineAnnotationElement_render() {
this.container.className = 'underlineAnnotation';
if (!this.data.hasPopup) {
this._createPopup(this.container, null, this.data);
}
return this.container;
}
});
@ -2215,7 +2271,9 @@ var UnderlineAnnotationElement = (
*/
var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
function SquigglyAnnotationElement(parameters) {
AnnotationElement.call(this, parameters, true);
var isRenderable = !!(parameters.data.hasPopup ||
parameters.data.title || parameters.data.contents);
AnnotationElement.call(this, parameters, isRenderable);
}
Util.inherit(SquigglyAnnotationElement, AnnotationElement, {
@ -2228,6 +2286,11 @@ var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
*/
render: function SquigglyAnnotationElement_render() {
this.container.className = 'squigglyAnnotation';
if (!this.data.hasPopup) {
this._createPopup(this.container, null, this.data);
}
return this.container;
}
});
@ -2242,7 +2305,9 @@ var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
var StrikeOutAnnotationElement = (
function StrikeOutAnnotationElementClosure() {
function StrikeOutAnnotationElement(parameters) {
AnnotationElement.call(this, parameters, true);
var isRenderable = !!(parameters.data.hasPopup ||
parameters.data.title || parameters.data.contents);
AnnotationElement.call(this, parameters, isRenderable);
}
Util.inherit(StrikeOutAnnotationElement, AnnotationElement, {
@ -2255,6 +2320,11 @@ var StrikeOutAnnotationElement = (
*/
render: function StrikeOutAnnotationElement_render() {
this.container.className = 'strikeoutAnnotation';
if (!this.data.hasPopup) {
this._createPopup(this.container, null, this.data);
}
return this.container;
}
});
@ -2262,6 +2332,62 @@ var StrikeOutAnnotationElement = (
return StrikeOutAnnotationElement;
})();
/**
* @class
* @alias FileAttachmentAnnotationElement
*/
var FileAttachmentAnnotationElement = (
function FileAttachmentAnnotationElementClosure() {
function FileAttachmentAnnotationElement(parameters) {
AnnotationElement.call(this, parameters, true);
this.filename = getFilenameFromUrl(parameters.data.file.filename);
this.content = parameters.data.file.content;
}
Util.inherit(FileAttachmentAnnotationElement, AnnotationElement, {
/**
* Render the file attachment annotation's HTML element in the empty
* container.
*
* @public
* @memberof FileAttachmentAnnotationElement
* @returns {HTMLSectionElement}
*/
render: function FileAttachmentAnnotationElement_render() {
this.container.className = 'fileAttachmentAnnotation';
var trigger = document.createElement('div');
trigger.style.height = this.container.style.height;
trigger.style.width = this.container.style.width;
trigger.addEventListener('dblclick', this._download.bind(this));
if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
this._createPopup(this.container, trigger, this.data);
}
this.container.appendChild(trigger);
return this.container;
},
/**
* Download the file attachment associated with this annotation.
*
* @private
* @memberof FileAttachmentAnnotationElement
*/
_download: function FileAttachmentAnnotationElement_download() {
if (!this.downloadManager) {
warn('Download cannot be started due to unavailable download manager');
return;
}
this.downloadManager.downloadData(this.content, this.filename, '');
}
});
return FileAttachmentAnnotationElement;
})();
/**
* @typedef {Object} AnnotationLayerParameters
* @property {PageViewport} viewport
@ -2298,7 +2424,8 @@ var AnnotationLayer = (function AnnotationLayerClosure() {
layer: parameters.div,
page: parameters.page,
viewport: parameters.viewport,
linkService: parameters.linkService
linkService: parameters.linkService,
downloadManager: parameters.downloadManager
};
var element = annotationElementFactory.create(properties);
if (element.isRenderable) {

View File

@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdfWorker = {}));
// Use strict in our context only - users might not want it
'use strict';
var pdfjsVersion = '1.4.83';
var pdfjsBuild = '0629fd0';
var pdfjsVersion = '1.4.95';
var pdfjsBuild = '2b813c0';
var pdfjsFilePath =
typeof document !== 'undefined' && document.currentScript ?
@ -2366,6 +2366,17 @@ var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
font: 'font'
};
// Gets the file name from a given URL.
function getFilenameFromUrl(url) {
var anchor = url.indexOf('#');
var query = url.indexOf('?');
var end = Math.min(
anchor > 0 ? anchor : url.length,
query > 0 ? query : url.length);
return url.substring(url.lastIndexOf('/', end) + 1, end);
}
PDFJS.getFilenameFromUrl = getFilenameFromUrl;
// Combines two URLs. The baseUrl shall be absolute URL. If the url is an
// absolute URL, it will be returned as is.
function combineUrl(baseUrl, url) {
@ -3496,6 +3507,7 @@ exports.combineUrl = combineUrl;
exports.createPromiseCapability = createPromiseCapability;
exports.deprecated = deprecated;
exports.error = error;
exports.getFilenameFromUrl = getFilenameFromUrl;
exports.getLookupTableFactory = getLookupTableFactory;
exports.info = info;
exports.isArray = isArray;
@ -34982,6 +34994,7 @@ var ObjectLoader = (function() {
exports.Catalog = Catalog;
exports.ObjectLoader = ObjectLoader;
exports.XRef = XRef;
exports.FileSpec = FileSpec;
}));
@ -38792,6 +38805,7 @@ var isName = corePrimitives.isName;
var Stream = coreStream.Stream;
var ColorSpace = coreColorSpace.ColorSpace;
var ObjectLoader = coreObj.ObjectLoader;
var FileSpec = coreObj.FileSpec;
var OperatorList = coreEvaluator.OperatorList;
/**
@ -38817,6 +38831,7 @@ AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ {
// Return the right annotation object based on the subtype and field type.
var parameters = {
xref: xref,
dict: dict,
ref: ref
};
@ -38850,6 +38865,9 @@ AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ {
case 'StrikeOut':
return new StrikeOutAnnotation(parameters);
case 'FileAttachment':
return new FileAttachmentAnnotation(parameters);
default:
warn('Unimplemented annotation type "' + subtype + '", ' +
'falling back to base annotation');
@ -39083,6 +39101,24 @@ var Annotation = (function AnnotationClosure() {
}
},
/**
* Prepare the annotation for working with a popup in the display layer.
*
* @private
* @memberof Annotation
* @param {Dict} dict - The annotation's data dictionary
*/
_preparePopup: function Annotation_preparePopup(dict) {
if (!dict.has('C')) {
// Fall back to the default background color.
this.data.color = null;
}
this.data.hasPopup = dict.has('Popup');
this.data.title = stringToPDFString(dict.get('T') || '');
this.data.contents = stringToPDFString(dict.get('Contents') || '');
},
loadResources: function Annotation_loadResources(keys) {
return new Promise(function (resolve, reject) {
this.appearance.dict.getAsync('Resources').then(function (resources) {
@ -39400,27 +39436,15 @@ var TextAnnotation = (function TextAnnotationClosure() {
this.data.annotationType = AnnotationType.TEXT;
var dict = parameters.dict;
if (this.data.hasAppearance) {
this.data.name = 'NoIcon';
} else {
this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
this.data.name = dict.has('Name') ? dict.get('Name').name : 'Note';
}
if (!dict.has('C')) {
// Fall back to the default background color.
this.data.color = null;
}
this.data.hasPopup = dict.has('Popup');
if (!this.data.hasPopup) {
// There is no associated Popup annotation, so the Text annotation
// must create its own popup.
this.data.title = stringToPDFString(dict.get('T') || '');
this.data.contents = stringToPDFString(dict.get('Contents') || '');
this.data.name = parameters.dict.has('Name') ?
parameters.dict.get('Name').name : 'Note';
}
this._preparePopup(parameters.dict);
}
Util.inherit(TextAnnotation, Annotation, {});
@ -39539,6 +39563,7 @@ var HighlightAnnotation = (function HighlightAnnotationClosure() {
Annotation.call(this, parameters);
this.data.annotationType = AnnotationType.HIGHLIGHT;
this._preparePopup(parameters.dict);
// PDF viewers completely ignore any border styles.
this.data.borderStyle.setWidth(0);
@ -39554,6 +39579,7 @@ var UnderlineAnnotation = (function UnderlineAnnotationClosure() {
Annotation.call(this, parameters);
this.data.annotationType = AnnotationType.UNDERLINE;
this._preparePopup(parameters.dict);
// PDF viewers completely ignore any border styles.
this.data.borderStyle.setWidth(0);
@ -39569,6 +39595,7 @@ var SquigglyAnnotation = (function SquigglyAnnotationClosure() {
Annotation.call(this, parameters);
this.data.annotationType = AnnotationType.SQUIGGLY;
this._preparePopup(parameters.dict);
// PDF viewers completely ignore any border styles.
this.data.borderStyle.setWidth(0);
@ -39584,6 +39611,7 @@ var StrikeOutAnnotation = (function StrikeOutAnnotationClosure() {
Annotation.call(this, parameters);
this.data.annotationType = AnnotationType.STRIKEOUT;
this._preparePopup(parameters.dict);
// PDF viewers completely ignore any border styles.
this.data.borderStyle.setWidth(0);
@ -39594,6 +39622,22 @@ var StrikeOutAnnotation = (function StrikeOutAnnotationClosure() {
return StrikeOutAnnotation;
})();
var FileAttachmentAnnotation = (function FileAttachmentAnnotationClosure() {
function FileAttachmentAnnotation(parameters) {
Annotation.call(this, parameters);
var file = new FileSpec(parameters.dict.get('FS'), parameters.xref);
this.data.annotationType = AnnotationType.FILEATTACHMENT;
this.data.file = file.serializable;
this._preparePopup(parameters.dict);
}
Util.inherit(FileAttachmentAnnotation, Annotation, {});
return FileAttachmentAnnotation;
})();
exports.Annotation = Annotation;
exports.AnnotationBorderStyle = AnnotationBorderStyle;
exports.AnnotationFactory = AnnotationFactory;

View File

@ -132,7 +132,8 @@
.annotationLayer .highlightAnnotation,
.annotationLayer .underlineAnnotation,
.annotationLayer .squigglyAnnotation,
.annotationLayer .strikeoutAnnotation {
.annotationLayer .strikeoutAnnotation,
.annotationLayer .fileAttachmentAnnotation {
cursor: pointer;
}

View File

@ -12,15 +12,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals PDFJS, PDFBug, FirefoxCom, Stats, ProgressBar,
DownloadManager, getFileName, getPDFFileNameFromURL,
PDFHistory, Preferences, SidebarView, ViewHistory, Stats,
PDFThumbnailViewer, URL, noContextMenuHandler, SecondaryToolbar,
PasswordPrompt, PDFPresentationMode, PDFDocumentProperties, HandTool,
Promise, PDFLinkService, PDFOutlineView, PDFAttachmentView,
OverlayManager, PDFFindController, PDFFindBar, PDFViewer,
PDFRenderingQueue, PresentationModeState, parseQueryString,
RenderingStates, UNKNOWN_SCALE, DEFAULT_SCALE_VALUE,
/* globals PDFJS, PDFBug, FirefoxCom, Stats, ProgressBar, DownloadManager,
getPDFFileNameFromURL, PDFHistory, Preferences, SidebarView,
ViewHistory, Stats, PDFThumbnailViewer, URL, noContextMenuHandler,
SecondaryToolbar, PasswordPrompt, PDFPresentationMode,
PDFDocumentProperties, HandTool, Promise, PDFLinkService,
PDFOutlineView, PDFAttachmentView, OverlayManager,
PDFFindController, PDFFindBar, PDFViewer, PDFRenderingQueue,
PresentationModeState, parseQueryString, RenderingStates,
UNKNOWN_SCALE, DEFAULT_SCALE_VALUE,
IGNORE_CURRENT_POSITION_ON_ZOOM: true */
'use strict';
@ -52,15 +52,6 @@ var MAX_AUTO_SCALE = 1.25;
var SCROLLBAR_PADDING = 40;
var VERTICAL_PADDING = 5;
function getFileName(url) {
var anchor = url.indexOf('#');
var query = url.indexOf('?');
var end = Math.min(
anchor > 0 ? anchor : url.length,
query > 0 ? query : url.length);
return url.substring(url.lastIndexOf('/', end) + 1, end);
}
/**
* Returns scale factor for the canvas. It makes sense for the HiDPI displays.
* @return {Object} The object with horizontal (sx) and vertical (sy)
@ -4299,6 +4290,7 @@ DefaultTextLayerFactory.prototype = {
* @property {HTMLDivElement} pageDiv
* @property {PDFPage} pdfPage
* @property {IPDFLinkService} linkService
* @property {DownloadManager} downloadManager
*/
/**
@ -4313,6 +4305,7 @@ var AnnotationLayerBuilder = (function AnnotationLayerBuilderClosure() {
this.pageDiv = options.pageDiv;
this.pdfPage = options.pdfPage;
this.linkService = options.linkService;
this.downloadManager = options.downloadManager;
this.div = null;
}
@ -4337,7 +4330,8 @@ var AnnotationLayerBuilder = (function AnnotationLayerBuilderClosure() {
div: self.div,
annotations: annotations,
page: self.pdfPage,
linkService: self.linkService
linkService: self.linkService,
downloadManager: self.downloadManager
};
if (self.div) {
@ -4401,6 +4395,8 @@ DefaultAnnotationLayerFactory.prototype = {
* @property {HTMLDivElement} container - The container for the viewer element.
* @property {HTMLDivElement} viewer - (optional) The viewer element.
* @property {IPDFLinkService} linkService - The navigation/linking service.
* @property {DownloadManager} downloadManager - (optional) The download
* manager component.
* @property {PDFRenderingQueue} renderingQueue - (optional) The rendering
* queue object.
* @property {boolean} removePageBorders - (optional) Removes the border shadow
@ -4453,6 +4449,7 @@ var PDFViewer = (function pdfViewer() {
this.container = options.container;
this.viewer = options.viewer || options.container.firstElementChild;
this.linkService = options.linkService || new SimpleLinkService();
this.downloadManager = options.downloadManager || null;
this.removePageBorders = options.removePageBorders || false;
this.defaultRenderingQueue = !options.renderingQueue;
@ -5118,7 +5115,8 @@ var PDFViewer = (function pdfViewer() {
return new AnnotationLayerBuilder({
pageDiv: pageDiv,
pdfPage: pdfPage,
linkService: this.linkService
linkService: this.linkService,
downloadManager: this.downloadManager
});
},
@ -5242,7 +5240,6 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
this.linkService = linkService;
this.renderingQueue = renderingQueue;
this.hasImage = false;
this.resume = null;
this.renderingState = RenderingStates.INITIAL;
@ -5298,7 +5295,6 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
if (this.renderTask) {
this.renderTask.cancel();
}
this.hasImage = false;
this.resume = null;
this.renderingState = RenderingStates.INITIAL;
@ -5401,11 +5397,9 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
draw: function PDFThumbnailView_draw() {
if (this.renderingState !== RenderingStates.INITIAL) {
console.error('Must be in new state before drawing');
}
if (this.hasImage) {
return Promise.resolve(undefined);
}
this.hasImage = true;
this.renderingState = RenderingStates.RUNNING;
var resolveRenderPromise, rejectRenderPromise;
@ -5426,6 +5420,7 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
rejectRenderPromise(error);
return;
}
self.renderingState = RenderingStates.FINISHED;
self._convertCanvasToImage();
@ -5469,14 +5464,17 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
},
setImage: function PDFThumbnailView_setImage(pageView) {
if (this.renderingState !== RenderingStates.INITIAL) {
return;
}
var img = pageView.canvas;
if (this.hasImage || !img) {
if (!img) {
return;
}
if (!this.pdfPage) {
this.setPdfPage(pageView.pdfPage);
}
this.hasImage = true;
this.renderingState = RenderingStates.FINISHED;
var ctx = this._getPageDrawContext(true);
@ -5927,7 +5925,7 @@ var PDFAttachmentView = (function PDFAttachmentViewClosure() {
for (var i = 0; i < attachmentsCount; i++) {
var item = attachments[names[i]];
var filename = getFileName(item.filename);
var filename = PDFJS.getFilenameFromUrl(item.filename);
var div = document.createElement('div');
div.className = 'attachmentsItem';
var button = document.createElement('button');
@ -5993,7 +5991,8 @@ var PDFViewerApplication = {
container: container,
viewer: viewer,
renderingQueue: pdfRenderingQueue,
linkService: pdfLinkService
linkService: pdfLinkService,
downloadManager: new DownloadManager()
});
pdfRenderingQueue.setViewer(this.pdfViewer);
pdfLinkService.setViewer(this.pdfViewer);
@ -6334,7 +6333,7 @@ var PDFViewerApplication = {
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
this.url = url;
try {
this.setTitle(decodeURIComponent(getFileName(url)) || url);
this.setTitle(decodeURIComponent(PDFJS.getFilenameFromUrl(url)) || url);
} catch (e) {
// decodeURIComponent may throw URIError,
// fall back to using the unprocessed url in that case

View File

@ -1,7 +1,7 @@
@import url("chrome://pocket-shared/skin/pocket.css");
#nav-bar #pocket-button > .toolbarbutton-icon {
padding: 2px 6px;
padding: calc(var(--toolbarbutton-vertical-inner-padding)) 6px;
}
:-moz-any(#TabsToolbar, .widget-overflow-list) #pocket-button > .toolbarbutton-icon {

View File

@ -403,9 +403,9 @@ pointerLock.autoLock.title3=This site will hide the pointer.
# it's okay for them to have the same access key
safebrowsing.getMeOutOfHereButton.label=Get me out of here!
safebrowsing.getMeOutOfHereButton.accessKey=G
safebrowsing.reportedWebForgery=Reported Web Forgery!
safebrowsing.notAForgeryButton.label=This isn't a web forgery
safebrowsing.notAForgeryButton.accessKey=F
safebrowsing.deceptiveSite=Deceptive Site!
safebrowsing.notADeceptiveSiteButton.label=This isn't a deceptive site
safebrowsing.notADeceptiveSiteButton.accessKey=D
safebrowsing.reportedAttackSite=Reported Attack Site!
safebrowsing.notAnAttackButton.label=This isn't an attack site…
safebrowsing.notAnAttackButton.accessKey=A

View File

@ -4,7 +4,8 @@
<!ENTITY safeb.palm.accept.label "Get me out of here!">
<!ENTITY safeb.palm.decline.label "Ignore this warning">
<!ENTITY safeb.palm.notforgery.label2 "This isn't a web forgery…">
<!-- Localization note (safeb.palm.notdeceptive.label) - Label of the Help menu item. -->
<!ENTITY safeb.palm.notdeceptive.label "This isn't a deceptive site…">
<!ENTITY safeb.palm.reportPage.label "Why was this page blocked?">
<!ENTITY safeb.palm.whyForbidden.label "Why was this page blocked?">
@ -18,10 +19,10 @@
<!ENTITY safeb.blocked.unwantedPage.shortDesc "This web page at <span id='unwanted_sitename'/> has been reported to contain unwanted software and has been blocked based on your security preferences.">
<!ENTITY safeb.blocked.unwantedPage.longDesc "<p>Unwanted software pages try to install software that can be deceptive and affect your system in unexpected ways.</p>">
<!ENTITY safeb.blocked.phishingPage.title "Reported Web Forgery!">
<!-- Localization note (safeb.blocked.phishingPage.shortDesc) - Please don't translate the contents of the <span id="phishing_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
<!ENTITY safeb.blocked.phishingPage.shortDesc "This web page at <span id='phishing_sitename'/> has been reported as a web forgery and has been blocked based on your security preferences.">
<!ENTITY safeb.blocked.phishingPage.longDesc "<p>Web forgeries are designed to trick you into revealing personal or financial information by imitating sources you may trust.</p><p>Entering any information on this web page may result in identity theft or other fraud.</p>">
<!ENTITY safeb.blocked.phishingPage.title2 "Deceptive Site!">
<!-- Localization note (safeb.blocked.phishingPage.shortDesc2) - Please don't translate the contents of the <span id="phishing_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
<!ENTITY safeb.blocked.phishingPage.shortDesc2 "This web page at <span id='phishing_sitename'/> has been reported as a deceptive site and has been blocked based on your security preferences.">
<!ENTITY safeb.blocked.phishingPage.longDesc2 "<p>Deceptive sites are designed to trick you into doing something dangerous, like installing software, or revealing your personal information, like passwords, phone numbers or credit cards.</p><p>Entering any information on this web page may result in identity theft or other fraud.</p>">
<!ENTITY safeb.blocked.forbiddenPage.title2 "Blocked Site">
<!-- Localization note (safeb.blocked.forbiddenPage.shortDesc2) - Please don't translate the contents of the <span id="forbidden_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->

View File

@ -2,5 +2,5 @@
- 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/. -->
<!ENTITY reportPhishSiteMenu.title2 "Report Web Forgery…">
<!ENTITY reportPhishSiteMenu.accesskey "F">
<!ENTITY reportDeceptiveSiteMenu.title "Report deceptive site…">
<!ENTITY reportDeceptiveSiteMenu.accesskey "D">

View File

@ -31,7 +31,7 @@ externalProtocolChkMsg=Remember my choice for all links of this type.
externalProtocolLaunchBtn=Launch application
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences.
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.

View File

@ -160,27 +160,6 @@ be temporary, and you can try again later.</li>
</ul>
">
<!ENTITY malwareBlocked.title "Suspected Attack Site!">
<!ENTITY malwareBlocked.longDesc "
<p>Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.</p>
<p>Website owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
">
<!ENTITY unwantedBlocked.title "Suspected Unwanted Software Site!">
<!ENTITY unwantedBlocked.longDesc "
<p>Unwanted software pages try to install software that can be deceptive and affect your system in unexpected ways.</p>
">
<!ENTITY phishingBlocked.title "Suspected Web Forgery!">
<!ENTITY phishingBlocked.longDesc "
<p>Entering any personal information on this page may result in identity theft or other fraud.</p>
<p>These types of web forgeries are used in scams known as phishing attacks, in which fraudulent web pages and emails are used to imitate sources you may trust.</p>
">
<!ENTITY forbiddenBlocked.title "Forbidden Site">
<!ENTITY forbiddenBlocked.longDesc "<p>&brandShortName; prevented this page from loading because it is configured to block it.</p>
">
<!ENTITY cspBlocked.title "Blocked by Content Security Policy">
<!ENTITY cspBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">

View File

@ -1,12 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
GENERATED_DIRS = $(TEST_EXTENSIONS_DIR)
XPI_PKGNAME = mozscreenshots@mozilla.org
include $(topsrcdir)/config/rules.mk
libs::
(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - $(XPI_NAME)) | (cd $(TEST_EXTENSIONS_DIR) && tar -xf -)

View File

@ -9,7 +9,7 @@
<Description about="urn:mozilla:install-manifest">
<em:id>mozscreenshots@mozilla.org</em:id>
#expand <em:version>__MOZILLA_VERSION_U__</em:version>
<em:version>0.3.2</em:version>
<em:bootstrap>true</em:bootstrap>
<!-- for running custom screenshot binaries -->

View File

@ -15,3 +15,7 @@ FINAL_TARGET_PP_FILES += [
'bootstrap.js',
'install.rdf',
]
TEST_HARNESS_FILES.testing.mochitest.extensions += [
'mozscreenshots-signed.xpi',
]

View File

@ -9,13 +9,18 @@ MOZ_ARG_ENABLE_BOOL(clang-plugin,
ENABLE_CLANG_PLUGIN=1,
ENABLE_CLANG_PLUGIN= )
if test -n "$ENABLE_CLANG_PLUGIN"; then
if test -z "$CLANG_CC"; then
if test -z "${CLANG_CC}${CLANG_CL}"; then
AC_MSG_ERROR([Can't use clang plugin without clang.])
fi
AC_MSG_CHECKING([for llvm-config])
if test -z "$LLVMCONFIG"; then
LLVMCONFIG=`$CXX -print-prog-name=llvm-config`
if test -n "$CLANG_CL"; then
CXX_COMPILER="$(dirname "$CXX")/clang"
else
CXX_COMPILER="${CXX}"
fi
LLVMCONFIG=`$CXX_COMPILER -print-prog-name=llvm-config`
fi
if test -z "$LLVMCONFIG"; then
@ -36,18 +41,57 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
dnl The clang package we use on OSX is old, and its llvm-config doesn't
dnl recognize --system-libs, so ask for that separately. llvm-config's
dnl failure here is benign, so we can ignore it if it happens.
LLVM_LDFLAGS=`$LLVMCONFIG --system-libs | xargs`
LLVM_LDFLAGS="$LLVM_LDFLAGS `$LLVMCONFIG --ldflags --libs core mc analysis asmparser mcparser bitreader option | xargs`"
dnl Use tr instead of xargs in order to avoid problems with path separators on Windows.
LLVM_LDFLAGS=`$LLVMCONFIG --system-libs | tr '\n' ' '`
LLVM_LDFLAGS="$LLVM_LDFLAGS `$LLVMCONFIG --ldflags --libs core mc analysis asmparser mcparser bitreader option | tr '\n' ' '`"
if test "${HOST_OS_ARCH}" = "Darwin"; then
CLANG_LDFLAGS="-lclangFrontend -lclangDriver -lclangSerialization"
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangParse -lclangSema -lclangAnalysis"
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangEdit -lclangAST -lclangLex"
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangBasic -lclangASTMatchers"
elif test "${HOST_OS_ARCH}" = "WINNT"; then
CLANG_LDFLAGS="clangFrontend.lib clangDriver.lib clangSerialization.lib"
CLANG_LDFLAGS="$CLANG_LDFLAGS clangParse.lib clangSema.lib clangAnalysis.lib"
CLANG_LDFLAGS="$CLANG_LDFLAGS clangEdit.lib clangAST.lib clangLex.lib"
CLANG_LDFLAGS="$CLANG_LDFLAGS clangBasic.lib clangASTMatchers.lib"
else
CLANG_LDFLAGS="-lclangASTMatchers"
fi
if test -n "$CLANG_CL"; then
dnl The llvm-config coming with clang-cl may give us arguments in the
dnl /ARG form, which in msys will be interpreted as a path name. So we
dnl need to split the args and convert the leading slashes that we find
dnl into a dash.
LLVM_REPLACE_CXXFLAGS=''
for arg in $LLVM_CXXFLAGS; do
dnl The following expression replaces a leading slash with a dash.
dnl Also replace any backslashes with forward slash.
arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'`
LLVM_REPLACE_CXXFLAGS="$LLVM_REPLACE_CXXFLAGS $arg"
done
LLVM_CXXFLAGS="$LLVM_REPLACE_CXXFLAGS"
LLVM_REPLACE_LDFLAGS=''
for arg in $LLVM_LDFLAGS; do
dnl The following expression replaces a leading slash with a dash.
dnl Also replace any backslashes with forward slash.
arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'`
LLVM_REPLACE_LDFLAGS="$LLVM_REPLACE_LDFLAGS $arg"
done
LLVM_LDFLAGS="$LLVM_REPLACE_LDFLAGS"
CLANG_REPLACE_LDFLAGS=''
for arg in $CLANG_LDFLAGS; do
dnl The following expression replaces a leading slash with a dash.
dnl Also replace any backslashes with forward slash.
arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'`
CLANG_REPLACE_LDFLAGS="$CLANG_REPLACE_LDFLAGS $arg"
done
CLANG_LDFLAGS="$CLANG_REPLACE_LDFLAGS"
fi
dnl Check for the new ASTMatcher API names. Since this happened in the
dnl middle of the 3.8 cycle, our CLANG_VERSION_FULL is impossible to use
dnl correctly, so we have to detect this at configure time.

View File

@ -9,10 +9,14 @@ include $(topsrcdir)/config/config.mk
# In the current moz.build world, we need to override essentially every
# variable to limit ourselves to what we need to build the clang plugin.
ifeq ($(HOST_OS_ARCH),WINNT)
OS_CXXFLAGS := $(LLVM_CXXFLAGS) -GR- -EHsc
else
OS_CXXFLAGS := $(LLVM_CXXFLAGS) -fno-rtti -fno-exceptions
DSO_LDOPTS := -shared
endif
OS_COMPILE_CXXFLAGS :=
OS_LDFLAGS := $(LLVM_LDFLAGS) $(CLANG_LDFLAGS)
DSO_LDOPTS := -shared
ifeq ($(HOST_OS_ARCH)_$(OS_ARCH),Linux_Darwin)
# Use the host compiler instead of the target compiler.

View File

@ -1517,3 +1517,7 @@ public:
static FrontendPluginRegistry::Add<MozCheckAction> X("moz-check",
"check moz action");
// Export the registry on Windows.
#ifdef LLVM_EXPORT_REGISTRY
LLVM_EXPORT_REGISTRY(FrontendPluginRegistry)
#endif

View File

@ -54,16 +54,9 @@ leak:mozilla::plugins::PPluginModuleParent::OnCallReceived
leak:sec_asn1e_allocate_item
leak:PORT_Strdup_Util
# Bug 1021302 - Leak of fds allocated in nsSocketTransport::BuildSocket(). m1, m5, dt, oth
leak:nsSocketTransport::BuildSocket
leak:nsServerSocket::OnSocketReady
# Bug 1021350 - Small leak under event_base_once. m1, m4, bc3
leak:event_base_once
# Bug 1021854 - nsFileStreamBase::DoOpen() leaking fds. bc1, oth
leak:nsLocalFile::OpenNSPRFileDesc
# Bug 1022010 - Small leak under _render_glyph_outline. bc1
leak:_render_glyph_outline
@ -74,7 +67,7 @@ leak:SECITEM_AllocItem_Util
leak:GlobalPrinters::InitializeGlobalPrinters
leak:nsPSPrinterList::GetPrinterList
# Bug 1028456 - More leaks with _PR_Getfd, in nsLocalFile::CopyToNative and do_create. bc1, bc3
# Bug 1028456 - Various NSPR fd-related leaks. m1-m5, bc1,bc2,bc5,bc7,dt4,dt5.
leak:_PR_Getfd
# Bug 1028483 - The XML parser sometimes leaks an object. bc3

View File

@ -495,6 +495,8 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
if (const char *file = scriptFilename.get()) {
CopyUTF8toUTF16(nsDependentCString(file), fileName);
}
} else {
MOZ_ASSERT(!JS_IsExceptionPending(cx));
}
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
fileName,

View File

@ -6,7 +6,7 @@
# script. Additional scripts may be added by specific subdirectories.
ifdef ENABLE_CLANG_PLUGIN
CLANG_PLUGIN := $(DEPTH)/build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
CLANG_PLUGIN := $(topobjdir)/build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
OS_CXXFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
OS_CFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
endif

View File

@ -1,4 +1,7 @@
{
"plugins": [
"react"
],
"globals": {
"Cc": true,
"Ci": true,
@ -30,6 +33,23 @@
"mozilla/reject-importGlobalProperties": 1,
"mozilla/var-only-at-top-level": 1,
// Rules from the React plugin
"react/display-name": 1,
"react/no-danger": 1,
"react/no-did-mount-set-state": 1,
"react/no-did-update-set-state": 1,
"react/no-direct-mutation-state": 1,
"react/no-unknown-property": 1,
"react/prefer-es6-class": 1,
"react/prop-types": 1,
"react/sort-comp": [1, {
order: [
"propTypes",
"everything-else",
"render"
]
}],
// Disallow using variables outside the blocks they are defined (especially
// since only let and const are used, see "no-var").
"block-scoped-var": 2,

View File

@ -8,26 +8,33 @@
const Services = require("Services");
const React = require("devtools/client/shared/vendor/react");
const { TabMenu } = require("./tab-menu");
const { createFactory, createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
loader.lazyRequireGetter(this, "AddonsTab", "./components/addons-tab", true);
loader.lazyRequireGetter(this, "WorkersTab", "./components/workers-tab", true);
const TabMenu = createFactory(require("./tab-menu"));
loader.lazyGetter(this, "AddonsTab",
() => createFactory(require("./addons-tab")));
loader.lazyGetter(this, "WorkersTab",
() => createFactory(require("./workers-tab")));
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
const tabs = [
{ id: "addons", name: Strings.GetStringFromName("addons"),
icon: "chrome://devtools/skin/images/debugging-addons.svg",
component: AddonsTab },
{ id: "workers", name: Strings.GetStringFromName("workers"),
icon: "chrome://devtools/skin/images/debugging-workers.svg",
component: WorkersTab },
];
const tabs = [{
id: "addons",
name: Strings.GetStringFromName("addons"),
icon: "chrome://devtools/skin/images/debugging-addons.svg",
component: AddonsTab
}, {
id: "workers",
name: Strings.GetStringFromName("workers"),
icon: "chrome://devtools/skin/images/debugging-workers.svg",
component: WorkersTab
}];
const defaultTabId = "addons";
exports.AboutDebuggingApp = React.createClass({
module.exports = createClass({
displayName: "AboutDebuggingApp",
getInitialState() {
@ -55,12 +62,11 @@ exports.AboutDebuggingApp = React.createClass({
let selectedTab = tabs.find(t => t.id == selectedTabId);
return React.createElement(
"div", { className: "app"},
React.createElement(TabMenu, { tabs, selectedTabId, selectTab }),
React.createElement("div", { className: "main-content" },
React.createElement(selectedTab.component, { client }))
);
return dom.div({ className: "app" },
TabMenu({ tabs, selectedTabId, selectTab }),
dom.div({ className: "main-content" },
selectedTab.component({ client }))
);
},
onHashChange() {

View File

@ -12,7 +12,7 @@ loader.lazyImporter(this, "AddonManager",
const { Cc, Ci } = require("chrome");
const Services = require("Services");
const React = require("devtools/client/shared/vendor/react");
const { createClass, DOM: dom } = require("devtools/client/shared/vendor/react");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
@ -20,32 +20,31 @@ const Strings = Services.strings.createBundle(
const MORE_INFO_URL = "https://developer.mozilla.org/docs/Tools" +
"/about:debugging#Enabling_add-on_debugging";
exports.AddonsControls = React.createClass({
module.exports = createClass({
displayName: "AddonsControls",
render() {
let { debugDisabled } = this.props;
return React.createElement(
"div", { className: "addons-controls" }, React.createElement(
"div", { className: "addons-options" },
React.createElement("input", {
return dom.div({ className: "addons-controls" },
dom.div({ className: "addons-options" },
dom.input({
id: "enable-addon-debugging",
type: "checkbox",
checked: !debugDisabled,
onChange: this.onEnableAddonDebuggingChange,
}),
React.createElement("label", {
dom.label({
className: "addons-debugging-label",
htmlFor: "enable-addon-debugging",
title: Strings.GetStringFromName("addonDebugging.tooltip")
}, Strings.GetStringFromName("addonDebugging.label")),
"(",
React.createElement("a", { href: MORE_INFO_URL, target: "_blank" },
dom.a({ href: MORE_INFO_URL, target: "_blank" },
Strings.GetStringFromName("addonDebugging.moreInfo")),
")"
),
React.createElement("button", {
dom.button({
id: "load-addon-from-file",
onClick: this.loadAddonFromFile,
}, Strings.GetStringFromName("loadTemporaryAddon"))

View File

@ -2,17 +2,16 @@
* 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/. */
/* global React */
"use strict";
const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
const Services = require("Services");
const React = require("devtools/client/shared/vendor/react");
const { AddonsControls } = require("./addons-controls");
const { TabHeader } = require("./tab-header");
const { TargetList } = require("./target-list");
const { createFactory, createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
const AddonsControls = createFactory(require("./addons-controls"));
const TabHeader = createFactory(require("./tab-header"));
const TargetList = createFactory(require("./target-list"));
const ExtensionIcon = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
const Strings = Services.strings.createBundle(
@ -21,7 +20,7 @@ const Strings = Services.strings.createBundle(
const CHROME_ENABLED_PREF = "devtools.chrome.enabled";
const REMOTE_ENABLED_PREF = "devtools.debugger.remote-enabled";
exports.AddonsTab = React.createClass({
module.exports = createClass({
displayName: "AddonsTab",
getInitialState() {
@ -56,19 +55,17 @@ exports.AddonsTab = React.createClass({
let { debugDisabled, extensions: targets } = this.state;
let name = Strings.GetStringFromName("extensions");
return React.createElement(
"div", { id: "tab-addons", className: "tab", role: "tabpanel",
"aria-labelledby": "tab-addons-header-name" },
React.createElement(TabHeader, {
id: "tab-addons-header-name",
name: Strings.GetStringFromName("addons")}),
React.createElement(AddonsControls, { debugDisabled }),
React.createElement(
"div", { id: "addons" },
React.createElement(TargetList,
{ name, targets, client, debugDisabled })
)
);
return dom.div({
id: "tab-addons",
className: "tab",
role: "tabpanel",
"aria-labelledby": "tab-addons-header-name" },
TabHeader({
id: "tab-addons-header-name",
name: Strings.GetStringFromName("addons") }),
AddonsControls({ debugDisabled }),
dom.div({ id: "addons" },
TargetList({ name, targets, client, debugDisabled })));
},
updateDebugStatus() {

View File

@ -4,16 +4,16 @@
"use strict";
const React = require("devtools/client/shared/vendor/react");
const { createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
exports.TabHeader = React.createClass({
module.exports = createClass({
displayName: "TabHeader",
render() {
let { name, id } = this.props;
return React.createElement(
"div", { className: "header" }, React.createElement(
"h1", { id, className: "header-name" }, name));
return dom.div({ className: "header" },
dom.h1({ id, className: "header-name" }, name));
},
});

View File

@ -4,9 +4,10 @@
"use strict";
const React = require("devtools/client/shared/vendor/react");
const { createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
exports.TabMenuEntry = React.createClass({
module.exports = createClass({
displayName: "TabMenuEntry",
render() {
@ -15,13 +16,13 @@ exports.TabMenuEntry = React.createClass({
// Here .category, .category-icon, .category-name classnames are used to
// apply common styles defined.
let className = "category" + (selected ? " selected" : "");
return React.createElement(
"div", { className, onClick: this.onClick,
"aria-selected": selected, role: "tab" },
React.createElement("img", { className: "category-icon", src: icon,
role: "presentation" }),
React.createElement("div", { className: "category-name" }, name)
);
return dom.div({
"aria-selected": selected,
className,
onClick: this.onClick,
role: "tab" },
dom.img({ className: "category-icon", src: icon, role: "presentation" }),
dom.div({ className: "category-name" }, name));
},
onClick() {

View File

@ -2,25 +2,23 @@
* 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/. */
/* global React */
"use strict";
const React = require("devtools/client/shared/vendor/react");
const { TabMenuEntry } = require("./tab-menu-entry");
const { createClass, createFactory, DOM: dom } =
require("devtools/client/shared/vendor/react");
const TabMenuEntry = createFactory(require("./tab-menu-entry"));
exports.TabMenu = React.createClass({
module.exports = createClass({
displayName: "TabMenu",
render() {
let { tabs, selectedTabId, selectTab } = this.props;
let tabLinks = tabs.map(({ id, name, icon }) => {
let selected = id == selectedTabId;
return React.createElement(TabMenuEntry,
{ tabId: id, name, icon, selected, selectTab });
return TabMenuEntry({ tabId: id, name, icon, selected, selectTab });
});
// "categories" id used for styling purposes
return React.createElement("div", { id: "categories" }, tabLinks);
return dom.div({ id: "categories" }, tabLinks);
},
});

View File

@ -2,14 +2,13 @@
* 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/. */
/* global React */
"use strict";
const Services = require("Services");
const React = require("devtools/client/shared/vendor/react");
const { Target } = require("./target");
const { createClass, createFactory, DOM: dom } =
require("devtools/client/shared/vendor/react");
const Target = createFactory(require("./target"));
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
@ -18,19 +17,21 @@ const LocaleCompare = (a, b) => {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
};
exports.TargetList = React.createClass({
module.exports = createClass({
displayName: "TargetList",
render() {
let { client, debugDisabled } = this.props;
let targets = this.props.targets.sort(LocaleCompare).map(target => {
return React.createElement(Target, { client, target, debugDisabled });
return Target({ client, target, debugDisabled });
});
return (
React.createElement("div", { id: this.props.id, className: "targets" },
React.createElement("h4", null, this.props.name),
targets.length > 0 ? targets :
React.createElement("p", null, Strings.GetStringFromName("nothing"))
dom.div({ id: this.props.id, className: "targets" },
dom.h4(null, this.props.name),
targets.length > 0 ?
targets :
dom.p(null, Strings.GetStringFromName("nothing"))
)
);
},

View File

@ -17,28 +17,29 @@ loader.lazyImporter(this, "BrowserToolboxProcess",
"resource://devtools/client/framework/ToolboxProcess.jsm");
const Services = require("Services");
const React = require("devtools/client/shared/vendor/react");
const { createClass, DOM: dom } =
require("devtools/client/shared/vendor/react");
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
exports.Target = React.createClass({
module.exports = createClass({
displayName: "Target",
render() {
let { target, debugDisabled } = this.props;
let isServiceWorker = (target.type === "serviceworker");
let isRunning = (!isServiceWorker || target.workerActor);
return React.createElement("div", { className: "target" },
React.createElement("img", {
return dom.div({ className: "target" },
dom.img({
className: "target-icon",
role: "presentation",
src: target.icon }),
React.createElement("div", { className: "target-details" },
React.createElement("div", { className: "target-name" }, target.name)
dom.div({ className: "target-details" },
dom.div({ className: "target-name" }, target.name)
),
(isRunning ?
React.createElement("button", {
dom.button({
className: "debug-button",
onClick: this.debug,
disabled: debugDisabled,

View File

@ -8,15 +8,16 @@ const { Ci } = require("chrome");
const { Task } = require("resource://gre/modules/Task.jsm");
const Services = require("Services");
const React = require("devtools/client/shared/vendor/react");
const { TargetList } = require("./target-list");
const { TabHeader } = require("./tab-header");
const { createClass, createFactory, DOM: dom } =
require("devtools/client/shared/vendor/react");
const TabHeader = createFactory(require("./tab-header"));
const TargetList = createFactory(require("./target-list"));
const Strings = Services.strings.createBundle(
"chrome://devtools/locale/aboutdebugging.properties");
const WorkerIcon = "chrome://devtools/skin/images/debugging-workers.svg";
exports.WorkersTab = React.createClass({
module.exports = createClass({
displayName: "WorkersTab",
getInitialState() {
@ -48,27 +49,30 @@ exports.WorkersTab = React.createClass({
let { client } = this.props;
let { workers } = this.state;
return React.createElement(
"div", { id: "tab-workers", className: "tab", role: "tabpanel",
"aria-labelledby": "tab-workers-header-name" },
React.createElement(TabHeader, {
id: "tab-workers-header-name",
name: Strings.GetStringFromName("workers")}),
React.createElement(
"div", { id: "workers", className: "inverted-icons" },
React.createElement(TargetList, {
id: "service-workers",
name: Strings.GetStringFromName("serviceWorkers"),
targets: workers.service, client }),
React.createElement(TargetList, {
id: "shared-workers",
name: Strings.GetStringFromName("sharedWorkers"),
targets: workers.shared, client }),
React.createElement(TargetList, {
id: "other-workers",
name: Strings.GetStringFromName("otherWorkers"),
targets: workers.other, client }))
);
return dom.div({
id: "tab-workers",
className: "tab",
role: "tabpanel",
"aria-labelledby": "tab-workers-header-name" },
TabHeader({
id: "tab-workers-header-name",
name: Strings.GetStringFromName("workers") }),
dom.div({ id: "workers", className: "inverted-icons" },
TargetList({
id: "service-workers",
name: Strings.GetStringFromName("serviceWorkers"),
targets: workers.service,
client }),
TargetList({
id: "shared-workers",
name: Strings.GetStringFromName("sharedWorkers"),
targets: workers.shared,
client }),
TargetList({
id: "other-workers",
name: Strings.GetStringFromName("otherWorkers"),
targets: workers.other,
client })));
},
update() {

View File

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env browser */
/* global DebuggerClient, DebuggerServer */
"use strict";
@ -22,8 +21,11 @@ const { BrowserLoader } = Components.utils.import(
const { require } =
BrowserLoader("resource://devtools/client/aboutdebugging/", window);
const React = require("devtools/client/shared/vendor/react");
const { AboutDebuggingApp } = require("./components/aboutdebugging");
const {
createFactory,
render,
unmountComponentAtNode } = require("devtools/client/shared/vendor/react");
const AboutDebuggingApp = createFactory(require("./components/aboutdebugging"));
var AboutDebugging = {
init() {
@ -38,13 +40,13 @@ var AboutDebugging = {
let client = this.client;
let telemetry = new Telemetry();
let app = React.createElement(AboutDebuggingApp, { client, telemetry });
React.render(app, document.querySelector("#body"));
render(AboutDebuggingApp({ client, telemetry }),
document.querySelector("#body"));
});
},
destroy() {
React.unmountComponentAtNode(document.querySelector("#body"));
unmountComponentAtNode(document.querySelector("#body"));
this.client.close();
this.client = null;

View File

@ -5,7 +5,6 @@
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://devtools/client/shared/widgets/SideMenuWidget.jsm");
Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm");
@ -13,6 +12,7 @@ Cu.import("resource://gre/modules/Console.jsm");
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
const promise = require("promise");
const Services = require("Services");
const EventEmitter = require("devtools/shared/event-emitter");
const { CallWatcherFront } = require("devtools/server/actors/call-watcher");
const { CanvasFront } = require("devtools/server/actors/canvas");

View File

@ -4,17 +4,11 @@
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
var { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
// Disable logging for all the tests. Both the debugger server and frontend will
// be affected by this pref.
var gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
Services.prefs.setBoolPref("devtools.debugger.log", false);
var { generateUUID } = Cc['@mozilla.org/uuid-generator;1'].getService(Ci.nsIUUIDGenerator);
var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
var Services = require("Services");
var promise = require("promise");
var { gDevTools } = require("devtools/client/framework/devtools");
var { DebuggerClient } = require("devtools/shared/client/main");
@ -43,6 +37,11 @@ const WEBGL_DRAW_ARRAYS = EXAMPLE_URL + "doc_webgl-drawArrays.html";
const WEBGL_DRAW_ELEMENTS = EXAMPLE_URL + "doc_webgl-drawElements.html";
const RAF_BEGIN_URL = EXAMPLE_URL + "doc_raf-begin.html";
// Disable logging for all the tests. Both the debugger server and frontend will
// be affected by this pref.
var gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
Services.prefs.setBoolPref("devtools.debugger.log", false);
// All tests are asynchronous.
waitForExplicitFinish();

View File

@ -4,6 +4,7 @@
// Test various GCLI commands
const TEST_URI = "data:text/html;charset=utf-8,gcli-commands";
const HUDService = require("devtools/client/webconsole/hudservice");
function test() {
return Task.spawn(spawnTest).then(finish, helpers.handleError);

View File

@ -93,7 +93,6 @@ const FRAME_TYPE = {
PUBLIC_CLIENT_EVAL: 3
};
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://devtools/shared/event-emitter.js");
Cu.import("resource://devtools/client/shared/widgets/SimpleListWidget.jsm");
@ -137,6 +136,7 @@ var services = {
WAIT_UNTIL: waitUntilService.NAME
};
var Services = require("Services");
var {TargetFactory} = require("devtools/client/framework/target");
var {Toolbox} = require("devtools/client/framework/toolbox");
var DevToolsUtils = require("devtools/shared/DevToolsUtils");

View File

@ -4,7 +4,7 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
<?xml-stylesheet href="debugger.css" type="text/css"?>
<?xml-stylesheet href="chrome://devtools/content/debugger/debugger.css" type="text/css"?>
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
<?xml-stylesheet href="chrome://devtools/skin/debugger.css" type="text/css"?>
<!DOCTYPE window [

View File

@ -5,8 +5,7 @@
"use strict";
const {Cc, Ci} = require("chrome");
const { Services } = require("resource://gre/modules/Services.jsm");
const Services = require("Services");
loader.lazyGetter(this, "osString", () => Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS);

View File

@ -7,10 +7,9 @@ const {rgbToHsl} = require("devtools/shared/css-color").colorUtils;
const Telemetry = require("devtools/client/shared/telemetry");
const {EventEmitter} = Cu.import("resource://devtools/shared/event-emitter.js");
const promise = require("promise");
const Services = require("Services");
const {setTimeout, clearTimeout} = Cu.import("resource://gre/modules/Timer.jsm", {});
Cu.import("resource://gre/modules/Services.jsm");
loader.lazyGetter(this, "clipboardHelper", function() {
return Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper);

View File

@ -11,7 +11,6 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
const DBG_XUL = "chrome://devtools/content/framework/toolbox-process-window.xul";
const CHROME_DEBUGGER_PROFILE_NAME = "chrome_debugger_profile";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm")
const { require, DevToolsLoader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
@ -22,6 +21,7 @@ XPCOMUtils.defineLazyGetter(this, "EventEmitter", function () {
return require("devtools/shared/event-emitter");
});
const promise = require("promise");
const Services = require("Services");
this.EXPORTED_SYMBOLS = ["BrowserToolboxProcess"];

View File

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const {Cc, Ci, Cu} = require("chrome");
const Services = Cu.import("resource://gre/modules/Services.jsm", {}).Services;
const Services = require("Services");
const promise = require("promise");
function l10n(name) {

View File

@ -8,9 +8,9 @@
var Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
var {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
var Services = require("Services");
var {gDevTools} = require("devtools/client/framework/devtools");
var {TargetFactory} = require("devtools/client/framework/target");
var {Toolbox} = require("devtools/client/framework/toolbox")

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