MozReview-Commit-ID: EcjJhQuqDFI
This commit is contained in:
Kartikaya Gupta 2017-02-05 10:39:54 -05:00
Родитель bf7599ac75 cde93160c2
Коммит 2c58155ac0
2719 изменённых файлов: 526347 добавлений и 23894 удалений

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

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Merge day clobber
Touch clobber because of bug 1336456

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

@ -2087,11 +2087,13 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
child->SetRelocated(true);
children->InsertElementAt(arrayIdx, child);
insertIdx = child->IndexInParent() + 1;
arrayIdx++;
// Create subtree before adjusting the insertion index, since subtree
// creation may alter children in the container.
CreateSubtree(child);
FireEventsOnInsertion(aOwner);
insertIdx = child->IndexInParent() + 1;
arrayIdx++;
}
}
continue;

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

@ -14,6 +14,7 @@ interface IGeckoCustom : IUnknown
[propget] HRESULT anchorCount([out, retval] long* aCount);
[propget] HRESULT DOMNodeID([out, retval] BSTR* aID);
[propget] HRESULT minimumIncrement([out, retval] double* aIncrement);
[propget] HRESULT mozState([out, retval] unsigned __int64* aState);
}

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

@ -39,7 +39,7 @@ ProxyAccessibleBase<Derived>::Shutdown()
for (uint32_t idx = 0; idx < childCount; idx++)
mChildren[idx]->Shutdown();
} else {
if (mChildren.Length() > 1)
if (mChildren.Length() != 1)
MOZ_CRASH("outer doc doesn't own adoc!");
mChildren[0]->AsDoc()->Unbind();
@ -76,7 +76,9 @@ ProxyAccessibleBase<Derived>::ClearChildDoc(DocAccessibleParent* aChildDoc)
// in SetChildDoc(). This could result in two subsequent calls to
// ClearChildDoc() even though mChildren.Length() == 1.
MOZ_ASSERT(mChildren.Length() <= 1);
mChildren.RemoveElement(aChildDoc);
if (mChildren.RemoveElement(aChildDoc)) {
mOuterDoc = false;
}
}
template <class Derived>

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

@ -193,18 +193,17 @@ ProxyAccessible::Description(nsString& aDesc) const
uint64_t
ProxyAccessible::State() const
{
uint64_t state = 0;
RefPtr<IAccessible> acc;
if (!GetCOMInterface((void**)getter_AddRefs(acc))) {
return state;
RefPtr<IGeckoCustom> custom = QueryInterface<IGeckoCustom>(this);
if (!custom) {
return 0;
}
VARIANT varState;
HRESULT hr = acc->get_accState(kChildIdSelf, &varState);
uint64_t state;
HRESULT hr = custom->get_mozState(&state);
if (FAILED(hr)) {
return state;
return 0;
}
return uint64_t(varState.lVal);
return state;
}
nsIntRect

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

@ -532,6 +532,50 @@
}
}
/**
* Set ARIA owns on inaccessible span element that contains
* accessible children. This will move children from the container for
* the span.
*/
function test8()
{
this.eventSeq = [
new invokerChecker(EVENT_REORDER, "t8_container")
];
this.invoke = function test8_invoke()
{
var tree =
{ SECTION: [
{ PUSHBUTTON: [] },
{ ENTRY: [] },
{ ENTRY: [] },
{ ENTRY: [] }
] };
testAccessibleTree("t8_container", tree);
getNode(t8_container).setAttribute("aria-owns", "t8_span t8_button");
}
this.finalCheck = function test8_finalCheck()
{
var tree =
{ SECTION: [
{ TEXT: [
{ ENTRY: [] },
{ ENTRY: [] },
{ ENTRY: [] }
] },
{ PUSHBUTTON: [] }
] };
testAccessibleTree("t8_container", tree);
}
this.getID = function test8_getID()
{
return `Set ARIA owns on inaccessible span element that contains accessible children`;
}
}
////////////////////////////////////////////////////////////////////////////
// Test
@ -580,6 +624,8 @@
gQueue.push(new setARIAOwnsOnElToRemove("t7_parent", "t7_child"));
gQueue.push(new test8());
gQueue.invoke(); // SimpleTest.finish() will be called in the end
}
@ -638,6 +684,10 @@
<div id="t7_child"></div>
</div>
</div>
<div id="t8_container">
<input id="t8_button" type="button"><span id="t8_span"><input><input><input></span>
</div>
</body>
</html>

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

@ -50,3 +50,10 @@ GeckoCustom::get_minimumIncrement(double* aIncrement)
*aIncrement = mAcc->Step();
return S_OK;
}
STDMETHODIMP
GeckoCustom::get_mozState(uint64_t* aState)
{
*aState = mAcc->State();
return S_OK;
}

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

@ -30,6 +30,7 @@ public:
virtual STDMETHODIMP get_DOMNodeID(BSTR* aID);
virtual STDMETHODIMP get_ID(uint64_t* aID);
virtual STDMETHODIMP get_minimumIncrement(double* aIncrement);
virtual STDMETHODIMP get_mozState(uint64_t* aState);
private:
GeckoCustom() = delete;

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

@ -233,8 +233,7 @@ DEFAULT_TEST_PREFS = {
# Disable useragent updates.
'general.useragent.updates.enabled': False,
'media.eme.enabled': True,
'media.eme.apiVisible': True,
# Don't forceably kill content processes after a timeout
# Don't forcibly kill content processes after a timeout
'dom.ipc.tabs.shutdownTimeoutSecs': 0,
'general.useragent.locale': "en-US",
'intl.locale.matchOS': "en-US",

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

@ -37,7 +37,6 @@
"browser.download.panel.shown": true,
"general.useragent.updates.enabled": false,
"media.eme.enabled": true,
"media.eme.apiVisible": true,
"dom.ipc.tabs.shutdownTimeoutSecs": 0,
"general.useragent.locale": "en-US",
"intl.locale.matchOS": "en-US",

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

@ -324,7 +324,6 @@ pref("media.gonk.enabled", true);
//Encrypted media extensions.
pref("media.eme.enabled", true);
pref("media.eme.apiVisible", true);
// The default number of decoded video frames that are enqueued in
// MediaDecoderReader's mVideoQueue.
pref("media.video-queue.default-size", 3);

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

@ -498,8 +498,6 @@
@RESPATH@/components/formautofill.manifest
@RESPATH@/components/FormAutofillContentService.js
@RESPATH@/components/FormAutofillStartup.js
@RESPATH@/components/CSSUnprefixingService.js
@RESPATH@/components/CSSUnprefixingService.manifest
@RESPATH@/components/contentAreaDropListener.manifest
@RESPATH@/components/contentAreaDropListener.js
@RESPATH@/components/messageWakeupService.js

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

@ -534,7 +534,8 @@ pref("privacy.sanitize.migrateFx3Prefs", false);
pref("privacy.panicButton.enabled", true);
pref("privacy.firstparty.isolate", false);
pref("privacy.firstparty.isolate", false);
pref("privacy.firstparty.isolate.restrict_opener_access", true);
// Time until temporary permissions expire, in ms
pref("privacy.temporary_permission_expire_time_ms", 3600000);
@ -1375,7 +1376,6 @@ pref("media.eme.enabled", false);
#else
pref("media.eme.enabled", true);
#endif
pref("media.eme.apiVisible", true);
// Whether we should run a test-pattern through EME GMPs before assuming they'll
// decode H.264.

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

@ -3400,8 +3400,10 @@ var PrintPreviewListener = {
return gBrowser.getBrowserForTab(this._printPreviewTab);
},
createSimplifiedBrowser() {
let browser = this._tabBeforePrintPreview.linkedBrowser;
this._simplifyPageTab = gBrowser.loadOneTab("about:blank",
{ inBackground: true });
{ inBackground: true,
relatedBrowser: browser });
return this.getSimplifiedSourceBrowser();
},
getSourceBrowser() {

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

@ -311,10 +311,21 @@ Site.prototype = {
_speculativeConnect: function Site_speculativeConnect() {
let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
let uri = Services.io.newURI(this.url);
if (!uri.schemeIs("http") && !uri.schemeIs("https")) {
return;
}
try {
// This can throw for certain internal URLs, when they wind up in
// about:newtab. Be sure not to propagate the error.
sc.speculativeConnect(uri, null);
// We use the URI's codebase principal here to open its speculative
// connection.
let originAttributes = document.docShell.getOriginAttributes();
let principal = Services.scriptSecurityManager
.createCodebasePrincipal(uri, originAttributes);
sc.speculativeConnect2(uri, principal, null);
} catch (e) {}
},

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

@ -7109,14 +7109,6 @@
this.removeAttribute("blocked");
modifiedAttrs.push("blocked");
// We don't want sound icon flickering between "blocked", "none" and
// "sound-playing", here adding the "soundplaying" is to keep the
// transition smoothly.
if (!this.hasAttribute("soundplaying")) {
this.setAttribute("soundplaying", true);
modifiedAttrs.push("soundplaying");
}
browser.resumeMedia();
hist.add(3 /* unblockByClickingIcon */);
this.finishMediaBlockTimer();

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

@ -81,11 +81,19 @@ const PAGECONTENT_TRANSLATED =
"</div></body></html>";
const PAGECONTENT_COLORS =
"<html><head><style>.blue { color: #fff; background-color: #00f; } .green { color: #800080; background-color: green; }</style>" +
"<html><head><style>" +
" .blue { color: #fff; background-color: #00f; }" +
" .green { color: #800080; background-color: green; }" +
" .defaultColor { color: -moz-ComboboxText; }" +
" .defaultBackground { background-color: -moz-Combobox; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One" style="color: #fff; background-color: #f00;">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(255, 0, 0)"}</option>' +
' <option value="Two" class="blue">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(0, 0, 255)"}</option>' +
' <option value="Three" class="green">{"color": "rgb(128, 0, 128)", "backgroundColor": "rgb(0, 128, 0)"}</option>' +
' <option value="Four" class="defaultColor defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "transparent", "unstyled": "true"}</option>' +
' <option value="Five" class="defaultColor">{"color": "-moz-ComboboxText", "backgroundColor": "transparent", "unstyled": "true"}</option>' +
' <option value="Six" class="defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "transparent", "unstyled": "true"}</option>' +
"</select></body></html>";
function openSelectPopup(selectPopup, mode = "key", selector = "select", win = window) {
@ -738,11 +746,6 @@ add_task(function* test_somehidden() {
});
add_task(function* test_colors_applied_to_popup() {
function inverseRGBString(rgbString) {
let [, r, g, b] = rgbString.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return `rgb(${255 - r}, ${255 - g}, ${255 - b})`;
}
const pageUrl = "data:text/html," + escape(PAGECONTENT_COLORS);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
@ -754,62 +757,39 @@ add_task(function* test_colors_applied_to_popup() {
// The label contains a JSON string of the expected colors for
// `color` and `background-color`.
is(selectPopup.parentNode.itemCount, 3, "Correct number of items");
is(selectPopup.parentNode.itemCount, 6, "Correct number of items");
let child = selectPopup.firstChild;
let idx = 1;
ok(child.selected, "The first child should be selected");
while (child) {
let expectedColors = JSON.parse(child.label);
let expected = JSON.parse(child.label);
// We need to use Canvas here to get the actual pixel color
// because the computedStyle will only tell us the 'color' or
// 'backgroundColor' of the element, but not what the displayed
// color is due to composition of various CSS rules such as
// 'filter' which is applied when elements have custom background
// or foreground elements.
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas = document.documentElement.appendChild(canvas);
let rect = child.getBoundingClientRect();
canvas.setAttribute("width", rect.width);
canvas.setAttribute("height", rect.height);
canvas.mozOpaque = true;
let ctx = canvas.getContext("2d");
ctx.drawWindow(window, rect.x + rect.left, rect.y + rect.top, rect.width, rect.height, "#000", ctx.DRAWWINDOW_USE_WIDGET_LAYERS);
let frame = ctx.getImageData(0, 0, rect.width, rect.height);
let pixels = frame.data.length / 4;
// Assume the inverse backgroundColor is the color of the first pixel.
let [inverseBgR, inverseBgG, inverseBgB] = frame.data;
let inverseBackgroundColor = `rgb(${inverseBgR}, ${inverseBgG}, ${inverseBgB})`;
// Use the next different pixel color as the foreground color, assuming
// no anti-aliasing.
let inverseColor = inverseBackgroundColor;
for (let i = 0; i < pixels; i++) {
if (inverseBgR != frame.data[i * 4 + 0] &&
inverseBgG != frame.data[i * 4 + 1] &&
inverseBgB != frame.data[i * 4 + 2]) {
inverseColor = `rgb(${frame.data[i * 4 + 0]}, ${frame.data[i * 4 + 1]}, ${frame.data[i * 4 + 2]})`;
for (let color of Object.keys(expected)) {
if (color.toLowerCase().includes("color") &&
!expected[color].startsWith("rgb")) {
// Need to convert system color to RGB color.
let textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
textarea.style.color = expected[color];
expected[color] = getComputedStyle(textarea).color;
}
}
// The canvas code above isn't getting the right colors for the pixels,
// it always returns rgb(255,255,255).
todo_is(inverseColor, inverseRGBString(getComputedStyle(child).color),
"Item " + (idx) + " has correct inverse foreground color when selected");
todo_is(inverseBackgroundColor, inverseRGBString(getComputedStyle(child).backgroundColor),
"Item " + (idx) + " has correct inverse background color when selected");
canvas.remove();
// Press Down to move the selected item to the next item in the
// list and check the colors of this item when it's not selected.
EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
is(getComputedStyle(child).color, expectedColors.color,
"Item " + (idx) + " has correct foreground color");
is(getComputedStyle(child).backgroundColor, expectedColors.backgroundColor,
"Item " + (idx++) + " has correct background color");
if (expected.unstyled) {
ok(!child.hasAttribute("customoptionstyling"),
`Item ${idx} should not have any custom option styling`);
} else {
is(getComputedStyle(child).color, expected.color,
"Item " + (idx) + " has correct foreground color");
is(getComputedStyle(child).backgroundColor, expected.backgroundColor,
"Item " + (idx) + " has correct background color");
}
idx++;
child = child.nextSibling;
}

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

@ -86,7 +86,6 @@ add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({"set": [
[ "privacy.userContext.enabled", true ],
[ "media.mediasource.enabled", true ],
[ "media.eme.apiVisible", true ],
[ "media.mediasource.webm.enabled", true ],
[ "media.clearkey.persistent-license.enabled", true ],
]});

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

@ -179,7 +179,6 @@ add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({"set": [
[ "privacy.userContext.enabled", true ],
[ "media.mediasource.enabled", true ],
[ "media.eme.apiVisible", true ],
[ "media.mediasource.webm.enabled", true ],
[ "media.clearkey.persistent-license.enabled", true ],
]});

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

@ -495,7 +495,9 @@
<![CDATA[
// Speculatively connect to the current engine's search URI (and
// suggest URI, if different) to reduce request latency
this.currentEngine.speculativeConnect({window});
this.currentEngine.speculativeConnect({window,
originAttributes: gBrowser.contentPrincipal
.originAttributes});
if (this._ignoreFocus) {
// This window has been re-focused, don't show the suggestions

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

@ -11,7 +11,7 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
XPCOMUtils.defineLazyModuleGetter(this, "PrivacyLevel",
"resource:///modules/sessionstore/PrivacyLevel.jsm");
"resource://gre/modules/sessionstore/PrivacyLevel.jsm");
/**
* A module that provides methods to filter various kinds of data collected

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

@ -15,7 +15,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
XPCOMUtils.defineLazyModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivacyLevel",
"resource:///modules/sessionstore/PrivacyLevel.jsm");
"resource://gre/modules/sessionstore/PrivacyLevel.jsm");
// MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision.
const MAX_EXPIRY = Math.pow(2, 62);

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

@ -29,7 +29,6 @@ EXTRA_JS_MODULES.sessionstore = [
'GlobalState.jsm',
'PageStyle.jsm',
'PrivacyFilter.jsm',
'PrivacyLevel.jsm',
'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
'RunState.jsm',
'SessionCookies.jsm',

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

@ -2,6 +2,24 @@ MOZ_AUTOMATION_BUILD_SYMBOLS=0
MOZ_AUTOMATION_PACKAGE_TESTS=0
MOZ_AUTOMATION_L10N_CHECK=0
# The toolchain installed on our OSX 10.7 build machines is too old to support
# MachO LC_DATA_IN_CODE load command, which newer LLVM generates, so we need to
# use a newer toolchain that we build.
#
# Unfortunately setting $PATH is not enough, because the build system hardcodes
# the default values for some of the build tools, which we also need to
# override below. The default value for host ar and host ranlib is also
# hardcoded so we need to override those separately.
CCTOOLS_DIR="$topsrcdir/cctools/bin"
export PATH="$CCTOOLS_DIR:$PATH"
export AR="$CCTOOLS_DIR/ar"
export HOST_AR="$CCTOOLS_DIR/ar"
export RANLIB="$CCTOOLS_DIR/ranlib"
export HOST_RANLIB="$CCTOOLS_DIR/ranlib"
export LIPO="$CCTOOLS_DIR/lipo"
export OTOOL="$CCTOOLS_DIR/otool"
export STRIP="$CCTOOLS_DIR/strip"
. $topsrcdir/build/macosx/mozconfig.common
ac_add_options --enable-debug

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

@ -1,8 +1,8 @@
[
{
"version": "clang 3.8.0",
"size": 133060926,
"digest": "aff5ad3ac2d41db19d1ba0df5f97b189a7d7e1b6af8c56e22c2b0cced84d75fa98394ded6a4ba5713652e6684a0a46f47aeccf87991f9e849bf8d7d82e564f6f",
"version": "clang 3.9.0",
"size": 184678304,
"digest": "cfde9a0f7f59823200f94422b4adb9a2fb5d4d07f240bbd1142c792434f6a1cbb4096d25c9853d77008fc40db0d827daa7003e78016f51241f621d6040ccc635",
"algorithm": "sha512",
"filename": "clang.tar.bz2",
"unpack": true
@ -25,9 +25,9 @@
"size": 1143715
},
{
"version": "cctools port from commit hash db1f8d906cb28, ld only",
"size": 634496,
"digest": "037f31fcf29e7bb7fada0d2bdd5e95c7d4cb2692f2a5c98ed6f6a7561b9d81622d015f0d12b291d3667719655f1369e8ce8a0a4a4773aa0ee4753e04a8821173",
"version": "cctools port from commit hash 84ce22dbb22a26ce7f392e9de0ee39c2efe6fd68",
"size": 2174783,
"digest": "8678348faff8f344b377075007975ae77a55a2a73488e36950a43c8ec27a79970cd8e34003e33e756a57d9cbf5c3e2e4461184102c6c03f793377a4d250a7f24",
"algorithm": "sha512",
"filename": "cctools.tar.bz2",
"unpack": true

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

@ -16,12 +16,12 @@
"unpack": true
},
{
"size": 3008804,
"size": 1349196,
"visibility": "public",
"digest": "ba6937f14f3d8b26dcb2d39490dee6b0a8afb60f672f5debb71d7b62c1ec52103201b4b1a3d258f945567de531384b36ddb2ce4aa73dc63d72305b11c146847c",
"digest": "438a36523a74cbc4a58226647e0501fa64a1b63f32931dc364a75d699df8accb45afdf26f4cb61c6ac7f58be530205acb6da22008bec19603c6f6fda3a12a8cc",
"algorithm": "sha512",
"unpack": true,
"filename": "cctools.tar.gz"
"filename": "cctools.tar.xz"
},
{
"size": 30823112,

2
browser/extensions/e10srollout/bootstrap.js поставляемый
Просмотреть файл

@ -14,11 +14,13 @@ Cu.import("resource://gre/modules/UpdateUtils.jsm");
const TEST_THRESHOLD = {
"beta" : 0.5, // 50%
"release" : 1.0, // 100%
"esr" : 1.0, // 100%
};
const ADDON_ROLLOUT_POLICY = {
"beta" : "51alladdons", // Any WebExtension or addon except with mpc = false
"release" : "51set1",
"esr" : "esrA", // WebExtensions and Addons with mpc=true
};
const PREF_COHORT_SAMPLE = "e10s.rollout.cohortSample";

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

@ -10,7 +10,7 @@
<Description about="urn:mozilla:install-manifest">
<em:id>e10srollout@mozilla.org</em:id>
<em:version>1.8</em:version>
<em:version>1.9</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:multiprocessCompatible>true</em:multiprocessCompatible>

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

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

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

@ -23,8 +23,8 @@
}
}(this, function (exports) {
'use strict';
var pdfjsVersion = '1.7.235';
var pdfjsBuild = '3f320f0b';
var pdfjsVersion = '1.7.242';
var pdfjsBuild = '6f0cf8c4';
var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
var pdfjsLibs = {};
(function pdfjsWrapper() {
@ -1788,6 +1788,7 @@
}(this, function (exports, sharedUtil, displayDOMUtils) {
var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
var AnnotationType = sharedUtil.AnnotationType;
var stringToPDFString = sharedUtil.stringToPDFString;
var Util = sharedUtil.Util;
var addLinkAttributes = displayDOMUtils.addLinkAttributes;
var LinkTarget = displayDOMUtils.LinkTarget;
@ -2330,8 +2331,14 @@
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;
var file = this.data.file;
this.filename = getFilenameFromUrl(file.filename);
this.content = file.content;
this.linkService.onFileAttachmentAnnotation({
id: stringToPDFString(file.filename),
filename: file.filename,
content: file.content
});
}
Util.inherit(FileAttachmentAnnotationElement, AnnotationElement, {
render: function FileAttachmentAnnotationElement_render() {
@ -2365,7 +2372,7 @@
if (!data) {
continue;
}
var properties = {
var element = annotationElementFactory.create({
data: data,
layer: parameters.div,
page: parameters.page,
@ -2374,8 +2381,7 @@
downloadManager: parameters.downloadManager,
imageResourcesPath: parameters.imageResourcesPath || getDefaultSetting('imageResourcesPath'),
renderInteractiveForms: parameters.renderInteractiveForms || false
};
var element = annotationElementFactory.create(properties);
});
if (element.isRenderable) {
parameters.div.appendChild(element.render());
}
@ -5565,7 +5571,6 @@
var MessageHandler = sharedUtil.MessageHandler;
var MissingPDFException = sharedUtil.MissingPDFException;
var PageViewport = sharedUtil.PageViewport;
var PasswordResponses = sharedUtil.PasswordResponses;
var PasswordException = sharedUtil.PasswordException;
var StatTimer = sharedUtil.StatTimer;
var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
@ -6978,6 +6983,7 @@
exports.renderTextLayer = pdfjsLibs.pdfjsDisplayTextLayer.renderTextLayer;
exports.AnnotationLayer = pdfjsLibs.pdfjsDisplayAnnotationLayer.AnnotationLayer;
exports.CustomStyle = pdfjsLibs.pdfjsDisplayDOMUtils.CustomStyle;
exports.createPromiseCapability = pdfjsLibs.pdfjsSharedUtil.createPromiseCapability;
exports.PasswordResponses = pdfjsLibs.pdfjsSharedUtil.PasswordResponses;
exports.InvalidPDFException = pdfjsLibs.pdfjsSharedUtil.InvalidPDFException;
exports.MissingPDFException = pdfjsLibs.pdfjsSharedUtil.MissingPDFException;

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

@ -23,8 +23,8 @@
}
}(this, function (exports) {
'use strict';
var pdfjsVersion = '1.7.235';
var pdfjsBuild = '3f320f0b';
var pdfjsVersion = '1.7.242';
var pdfjsBuild = '6f0cf8c4';
var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
var pdfjsLibs = {};
(function pdfjsWrapper() {
@ -6080,7 +6080,6 @@
var encoding = Object.create(null);
var bytes = this.bytes;
var predefined = false;
var hasSupplement = false;
var format, i, ii;
var raw = null;
function readSupplement() {
@ -6130,7 +6129,6 @@
if (format & 0x80) {
bytes[dataStart] &= 0x7f;
readSupplement();
hasSupplement = true;
}
raw = bytes.subarray(dataStart, dataEnd);
}
@ -7444,8 +7442,7 @@
subStream.end = start + length || this.end;
subStream.dict = dict;
return subStream;
},
isStream: true
}
};
return ChunkedStream;
}();
@ -12848,14 +12845,12 @@
var deltaHeight = decodeInteger(contextCache, 'IADH', decoder);
currentHeight += deltaHeight;
var currentWidth = 0;
var totalWidth = 0;
while (true) {
var deltaWidth = decodeInteger(contextCache, 'IADW', decoder);
if (deltaWidth === null) {
break;
}
currentWidth += deltaWidth;
totalWidth += currentWidth;
var bitmap;
if (refinement) {
var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
@ -13265,7 +13260,7 @@
delete pageInfo.height;
}
var pageSegmentFlags = data[position + 16];
var pageStripingInformation = readUint16(data, position + 17);
readUint16(data, position + 17);
pageInfo.lossless = !!(pageSegmentFlags & 1);
pageInfo.refinement = !!(pageSegmentFlags & 2);
pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1;
@ -13308,7 +13303,7 @@
header.numberOfPages = readUint32(data, position);
position += 4;
}
var segments = readSegments(header, data, position, end);
readSegments(header, data, position, end);
error('Not implemented');
}
function parseJbig2Chunks(chunks) {
@ -14145,7 +14140,7 @@
resetInterval = readUint16();
break;
case 0xFFDA:
var scanLength = readUint16();
readUint16();
var selectorsCount = data[offset++];
var components = [], component;
for (i = 0; i < selectorsCount; i++) {
@ -22560,7 +22555,6 @@
var isArray = sharedUtil.isArray;
var createObjectURL = sharedUtil.createObjectURL;
var shadow = sharedUtil.shadow;
var warn = sharedUtil.warn;
var isSpace = sharedUtil.isSpace;
var Dict = corePrimitives.Dict;
var isDict = corePrimitives.isDict;
@ -22642,8 +22636,7 @@
},
makeSubStream: function Stream_makeSubStream(start, length, dict) {
return new Stream(this.bytes.buffer, start, length, dict);
},
isStream: true
}
};
return Stream;
}();
@ -31220,264 +31213,6 @@
return AES128Cipher;
}();
var AES256Cipher = function AES256CipherClosure() {
var rcon = new Uint8Array([
0x8d,
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80,
0x1b,
0x36,
0x6c,
0xd8,
0xab,
0x4d,
0x9a,
0x2f,
0x5e,
0xbc,
0x63,
0xc6,
0x97,
0x35,
0x6a,
0xd4,
0xb3,
0x7d,
0xfa,
0xef,
0xc5,
0x91,
0x39,
0x72,
0xe4,
0xd3,
0xbd,
0x61,
0xc2,
0x9f,
0x25,
0x4a,
0x94,
0x33,
0x66,
0xcc,
0x83,
0x1d,
0x3a,
0x74,
0xe8,
0xcb,
0x8d,
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80,
0x1b,
0x36,
0x6c,
0xd8,
0xab,
0x4d,
0x9a,
0x2f,
0x5e,
0xbc,
0x63,
0xc6,
0x97,
0x35,
0x6a,
0xd4,
0xb3,
0x7d,
0xfa,
0xef,
0xc5,
0x91,
0x39,
0x72,
0xe4,
0xd3,
0xbd,
0x61,
0xc2,
0x9f,
0x25,
0x4a,
0x94,
0x33,
0x66,
0xcc,
0x83,
0x1d,
0x3a,
0x74,
0xe8,
0xcb,
0x8d,
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80,
0x1b,
0x36,
0x6c,
0xd8,
0xab,
0x4d,
0x9a,
0x2f,
0x5e,
0xbc,
0x63,
0xc6,
0x97,
0x35,
0x6a,
0xd4,
0xb3,
0x7d,
0xfa,
0xef,
0xc5,
0x91,
0x39,
0x72,
0xe4,
0xd3,
0xbd,
0x61,
0xc2,
0x9f,
0x25,
0x4a,
0x94,
0x33,
0x66,
0xcc,
0x83,
0x1d,
0x3a,
0x74,
0xe8,
0xcb,
0x8d,
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80,
0x1b,
0x36,
0x6c,
0xd8,
0xab,
0x4d,
0x9a,
0x2f,
0x5e,
0xbc,
0x63,
0xc6,
0x97,
0x35,
0x6a,
0xd4,
0xb3,
0x7d,
0xfa,
0xef,
0xc5,
0x91,
0x39,
0x72,
0xe4,
0xd3,
0xbd,
0x61,
0xc2,
0x9f,
0x25,
0x4a,
0x94,
0x33,
0x66,
0xcc,
0x83,
0x1d,
0x3a,
0x74,
0xe8,
0xcb,
0x8d,
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80,
0x1b,
0x36,
0x6c,
0xd8,
0xab,
0x4d,
0x9a,
0x2f,
0x5e,
0xbc,
0x63,
0xc6,
0x97,
0x35,
0x6a,
0xd4,
0xb3,
0x7d,
0xfa,
0xef,
0xc5,
0x91,
0x39,
0x72,
0xe4,
0xd3,
0xbd,
0x61,
0xc2,
0x9f,
0x25,
0x4a,
0x94,
0x33,
0x66,
0xcc,
0x83,
0x1d,
0x3a,
0x74,
0xe8,
0xcb,
0x8d
]);
var s = new Uint8Array([
0x63,
0x7c,
@ -33036,9 +32771,9 @@
function parseCmap(data, start, end) {
var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16);
var format = getUshort(data, start + offset);
var length, ranges, p, i;
var ranges, p, i;
if (format === 4) {
length = getUshort(data, start + offset + 2);
getUshort(data, start + offset + 2);
var segCount = getUshort(data, start + offset + 6) >> 1;
p = start + offset + 14;
ranges = [];
@ -33065,7 +32800,7 @@
}
return ranges;
} else if (format === 12) {
length = getLong(data, start + offset + 4);
getLong(data, start + offset + 4);
var groups = getLong(data, start + offset + 12);
p = start + offset + 16;
ranges = [];
@ -36162,7 +35897,7 @@
error = true;
break;
}
var wy = this.stack.pop();
this.stack.pop();
wx = this.stack.pop();
var sby = this.stack.pop();
sbx = this.stack.pop();
@ -36414,7 +36149,7 @@
}
break;
case 'Subrs':
var num = this.readInt();
this.readInt();
this.getToken();
while ((token = this.getToken()) === 'dup') {
var index = this.readInt();
@ -39067,9 +38802,6 @@
this.sizes = [];
this.missingFile = false;
this.glyphCache = Object.create(null);
var names = name.split('+');
names = names.length > 1 ? names[1] : names[0];
names = names.split(/[-,_]/g)[0];
this.isSerifFont = !!(properties.flags & FontFlags.Serif);
this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
@ -39657,7 +39389,7 @@
var segment;
var start = (font.start ? font.start : 0) + cmap.offset;
font.pos = start;
var version = font.getUint16();
font.getUint16();
var numTables = font.getUint16();
var potentialTable;
var canBreak = false;
@ -39703,8 +39435,8 @@
};
}
var format = font.getUint16();
var length = font.getUint16();
var language = font.getUint16();
font.getUint16();
font.getUint16();
var hasShortCmap = false;
var mappings = [];
var j, glyphId;
@ -45192,22 +44924,11 @@
var width = 0;
var height = 0;
var glyphs = font.charsToGlyphs(chars);
var defaultVMetrics = font.defaultVMetrics;
for (var i = 0; i < glyphs.length; i++) {
var glyph = glyphs[i];
var vMetricX = null;
var vMetricY = null;
var glyphWidth = null;
if (font.vertical) {
if (glyph.vmetric) {
glyphWidth = glyph.vmetric[0];
vMetricX = glyph.vmetric[1];
vMetricY = glyph.vmetric[2];
} else {
glyphWidth = glyph.width;
vMetricX = glyph.width * 0.5;
vMetricY = defaultVMetrics[2];
}
if (font.vertical && glyph.vmetric) {
glyphWidth = glyph.vmetric[0];
} else {
glyphWidth = glyph.width;
}
@ -47120,7 +46841,6 @@
var AnnotationType = sharedUtil.AnnotationType;
var OPS = sharedUtil.OPS;
var Util = sharedUtil.Util;
var isString = sharedUtil.isString;
var isArray = sharedUtil.isArray;
var isInt = sharedUtil.isInt;
var stringToBytes = sharedUtil.stringToBytes;
@ -48473,7 +48193,6 @@
var MissingPDFException = sharedUtil.MissingPDFException;
var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
var PasswordException = sharedUtil.PasswordException;
var PasswordResponses = sharedUtil.PasswordResponses;
var UnknownErrorException = sharedUtil.UnknownErrorException;
var XRefParseException = sharedUtil.XRefParseException;
var arrayByteLength = sharedUtil.arrayByteLength;
@ -48739,7 +48458,7 @@
var xhr = new XMLHttpRequest();
var responseExists = 'response' in xhr;
try {
var dummy = xhr.responseType;
xhr.responseType;
} catch (e) {
responseExists = false;
}

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

@ -1084,6 +1084,24 @@ html[dir="rtl"] #viewOutline.toolbarButton::before {
content: url(images/toolbarButton-search.png);
}
.toolbarButton.pdfSidebarNotification::after {
position: absolute;
display: inline-block;
top: 1px;
/* Create a filled circle, with a diameter of 9 pixels, using only CSS: */
content: '';
background-color: #70DB55;
height: 9px;
width: 9px;
border-radius: 50%;
}
html[dir='ltr'] .toolbarButton.pdfSidebarNotification::after {
left: 17px;
}
html[dir='rtl'] .toolbarButton.pdfSidebarNotification::after {
right: 17px;
}
.secondaryToolbarButton {
position: relative;
margin: 0 0 4px 0;

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

@ -561,20 +561,26 @@ var pdfjsWebLibs;
this.container = options.container;
this.eventBus = options.eventBus;
this.downloadManager = options.downloadManager;
this._renderedCapability = pdfjsLib.createPromiseCapability();
this.eventBus.on('fileattachmentannotation', this._appendAttachment.bind(this));
}
PDFAttachmentViewer.prototype = {
reset: function PDFAttachmentViewer_reset() {
reset: function PDFAttachmentViewer_reset(keepRenderedCapability) {
this.attachments = null;
var container = this.container;
while (container.firstChild) {
container.removeChild(container.firstChild);
}
if (!keepRenderedCapability) {
this._renderedCapability = pdfjsLib.createPromiseCapability();
}
},
_dispatchEvent: function PDFAttachmentViewer_dispatchEvent(attachmentsCount) {
this.eventBus.dispatch('attachmentsloaded', {
source: this,
attachmentsCount: attachmentsCount
});
this._renderedCapability.resolve();
},
_bindLink: function PDFAttachmentViewer_bindLink(button, content, filename) {
button.onclick = function downloadFile(e) {
@ -583,10 +589,12 @@ var pdfjsWebLibs;
}.bind(this);
},
render: function PDFAttachmentViewer_render(params) {
var attachments = params && params.attachments || null;
params = params || {};
var attachments = params.attachments || null;
var attachmentsCount = 0;
if (this.attachments) {
this.reset();
var keepRenderedCapability = params.keepRenderedCapability === true;
this.reset(keepRenderedCapability);
}
this.attachments = attachments;
if (!attachments) {
@ -609,6 +617,28 @@ var pdfjsWebLibs;
this.container.appendChild(div);
}
this._dispatchEvent(attachmentsCount);
},
_appendAttachment: function PDFAttachmentViewer_appendAttachment(item) {
this._renderedCapability.promise.then(function (id, filename, content) {
var attachments = this.attachments;
if (!attachments) {
attachments = Object.create(null);
} else {
for (var name in attachments) {
if (id === name) {
return;
}
}
}
attachments[id] = {
filename: filename,
content: content
};
this.render({
attachments: attachments,
keepRenderedCapability: true
});
}.bind(this, item.id, item.filename, item.content));
}
};
return PDFAttachmentViewer;
@ -752,234 +782,6 @@ var pdfjsWebLibs;
}();
exports.PDFOutlineViewer = PDFOutlineViewer;
}));
(function (root, factory) {
factory(root.pdfjsWebPDFSidebar = {}, root.pdfjsWebPDFRenderingQueue);
}(this, function (exports, pdfRenderingQueue) {
var RenderingStates = pdfRenderingQueue.RenderingStates;
var SidebarView = {
NONE: 0,
THUMBS: 1,
OUTLINE: 2,
ATTACHMENTS: 3
};
var PDFSidebar = function PDFSidebarClosure() {
function PDFSidebar(options) {
this.isOpen = false;
this.active = SidebarView.THUMBS;
this.isInitialViewSet = false;
this.onToggled = null;
this.pdfViewer = options.pdfViewer;
this.pdfThumbnailViewer = options.pdfThumbnailViewer;
this.pdfOutlineViewer = options.pdfOutlineViewer;
this.mainContainer = options.mainContainer;
this.outerContainer = options.outerContainer;
this.eventBus = options.eventBus;
this.toggleButton = options.toggleButton;
this.thumbnailButton = options.thumbnailButton;
this.outlineButton = options.outlineButton;
this.attachmentsButton = options.attachmentsButton;
this.thumbnailView = options.thumbnailView;
this.outlineView = options.outlineView;
this.attachmentsView = options.attachmentsView;
this._addEventListeners();
}
PDFSidebar.prototype = {
reset: function PDFSidebar_reset() {
this.isInitialViewSet = false;
this.close();
this.switchView(SidebarView.THUMBS);
this.outlineButton.disabled = false;
this.attachmentsButton.disabled = false;
},
get visibleView() {
return this.isOpen ? this.active : SidebarView.NONE;
},
get isThumbnailViewVisible() {
return this.isOpen && this.active === SidebarView.THUMBS;
},
get isOutlineViewVisible() {
return this.isOpen && this.active === SidebarView.OUTLINE;
},
get isAttachmentsViewVisible() {
return this.isOpen && this.active === SidebarView.ATTACHMENTS;
},
setInitialView: function PDFSidebar_setInitialView(view) {
if (this.isInitialViewSet) {
return;
}
this.isInitialViewSet = true;
if (this.isOpen && view === SidebarView.NONE) {
this._dispatchEvent();
return;
}
var isViewPreserved = view === this.visibleView;
this.switchView(view, true);
if (isViewPreserved) {
this._dispatchEvent();
}
},
switchView: function PDFSidebar_switchView(view, forceOpen) {
if (view === SidebarView.NONE) {
this.close();
return;
}
var isViewChanged = view !== this.active;
var shouldForceRendering = false;
switch (view) {
case SidebarView.THUMBS:
this.thumbnailButton.classList.add('toggled');
this.outlineButton.classList.remove('toggled');
this.attachmentsButton.classList.remove('toggled');
this.thumbnailView.classList.remove('hidden');
this.outlineView.classList.add('hidden');
this.attachmentsView.classList.add('hidden');
if (this.isOpen && isViewChanged) {
this._updateThumbnailViewer();
shouldForceRendering = true;
}
break;
case SidebarView.OUTLINE:
if (this.outlineButton.disabled) {
return;
}
this.thumbnailButton.classList.remove('toggled');
this.outlineButton.classList.add('toggled');
this.attachmentsButton.classList.remove('toggled');
this.thumbnailView.classList.add('hidden');
this.outlineView.classList.remove('hidden');
this.attachmentsView.classList.add('hidden');
break;
case SidebarView.ATTACHMENTS:
if (this.attachmentsButton.disabled) {
return;
}
this.thumbnailButton.classList.remove('toggled');
this.outlineButton.classList.remove('toggled');
this.attachmentsButton.classList.add('toggled');
this.thumbnailView.classList.add('hidden');
this.outlineView.classList.add('hidden');
this.attachmentsView.classList.remove('hidden');
break;
default:
console.error('PDFSidebar_switchView: "' + view + '" is an unsupported value.');
return;
}
this.active = view | 0;
if (forceOpen && !this.isOpen) {
this.open();
return;
}
if (shouldForceRendering) {
this._forceRendering();
}
if (isViewChanged) {
this._dispatchEvent();
}
},
open: function PDFSidebar_open() {
if (this.isOpen) {
return;
}
this.isOpen = true;
this.toggleButton.classList.add('toggled');
this.outerContainer.classList.add('sidebarMoving');
this.outerContainer.classList.add('sidebarOpen');
if (this.active === SidebarView.THUMBS) {
this._updateThumbnailViewer();
}
this._forceRendering();
this._dispatchEvent();
},
close: function PDFSidebar_close() {
if (!this.isOpen) {
return;
}
this.isOpen = false;
this.toggleButton.classList.remove('toggled');
this.outerContainer.classList.add('sidebarMoving');
this.outerContainer.classList.remove('sidebarOpen');
this._forceRendering();
this._dispatchEvent();
},
toggle: function PDFSidebar_toggle() {
if (this.isOpen) {
this.close();
} else {
this.open();
}
},
_dispatchEvent: function PDFSidebar_dispatchEvent() {
this.eventBus.dispatch('sidebarviewchanged', {
source: this,
view: this.visibleView
});
},
_forceRendering: function PDFSidebar_forceRendering() {
if (this.onToggled) {
this.onToggled();
} else {
this.pdfViewer.forceRendering();
this.pdfThumbnailViewer.forceRendering();
}
},
_updateThumbnailViewer: function PDFSidebar_updateThumbnailViewer() {
var pdfViewer = this.pdfViewer;
var thumbnailViewer = this.pdfThumbnailViewer;
var pagesCount = pdfViewer.pagesCount;
for (var pageIndex = 0; pageIndex < pagesCount; pageIndex++) {
var pageView = pdfViewer.getPageView(pageIndex);
if (pageView && pageView.renderingState === RenderingStates.FINISHED) {
var thumbnailView = thumbnailViewer.getThumbnail(pageIndex);
thumbnailView.setImage(pageView);
}
}
thumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);
},
_addEventListeners: function PDFSidebar_addEventListeners() {
var self = this;
self.mainContainer.addEventListener('transitionend', function (evt) {
if (evt.target === this) {
self.outerContainer.classList.remove('sidebarMoving');
}
});
self.thumbnailButton.addEventListener('click', function () {
self.switchView(SidebarView.THUMBS);
});
self.outlineButton.addEventListener('click', function () {
self.switchView(SidebarView.OUTLINE);
});
self.outlineButton.addEventListener('dblclick', function () {
self.pdfOutlineViewer.toggleOutlineTree();
});
self.attachmentsButton.addEventListener('click', function () {
self.switchView(SidebarView.ATTACHMENTS);
});
self.eventBus.on('outlineloaded', function (e) {
var outlineCount = e.outlineCount;
self.outlineButton.disabled = !outlineCount;
if (!outlineCount && self.active === SidebarView.OUTLINE) {
self.switchView(SidebarView.THUMBS);
}
});
self.eventBus.on('attachmentsloaded', function (e) {
var attachmentsCount = e.attachmentsCount;
self.attachmentsButton.disabled = !attachmentsCount;
if (!attachmentsCount && self.active === SidebarView.ATTACHMENTS) {
self.switchView(SidebarView.THUMBS);
}
});
self.eventBus.on('presentationmodechanged', function (e) {
if (!e.active && !e.switchInProgress && self.isThumbnailViewVisible) {
self._updateThumbnailViewer();
}
});
}
};
return PDFSidebar;
}();
exports.SidebarView = SidebarView;
exports.PDFSidebar = PDFSidebar;
}));
(function (root, factory) {
factory(root.pdfjsWebUIUtils = {}, root.pdfjsWebPDFJS);
}(this, function (exports, pdfjsLib) {
@ -2418,6 +2220,289 @@ var pdfjsWebLibs;
}();
exports.PDFPresentationMode = PDFPresentationMode;
}));
(function (root, factory) {
factory(root.pdfjsWebPDFSidebar = {}, root.pdfjsWebPDFRenderingQueue, root.pdfjsWebUIUtils);
}(this, function (exports, pdfRenderingQueue, uiUtils) {
var RenderingStates = pdfRenderingQueue.RenderingStates;
var mozL10n = uiUtils.mozL10n;
var UI_NOTIFICATION_CLASS = 'pdfSidebarNotification';
var SidebarView = {
NONE: 0,
THUMBS: 1,
OUTLINE: 2,
ATTACHMENTS: 3
};
var PDFSidebar = function PDFSidebarClosure() {
function PDFSidebar(options) {
this.isOpen = false;
this.active = SidebarView.THUMBS;
this.isInitialViewSet = false;
this.onToggled = null;
this.pdfViewer = options.pdfViewer;
this.pdfThumbnailViewer = options.pdfThumbnailViewer;
this.pdfOutlineViewer = options.pdfOutlineViewer;
this.mainContainer = options.mainContainer;
this.outerContainer = options.outerContainer;
this.eventBus = options.eventBus;
this.toggleButton = options.toggleButton;
this.thumbnailButton = options.thumbnailButton;
this.outlineButton = options.outlineButton;
this.attachmentsButton = options.attachmentsButton;
this.thumbnailView = options.thumbnailView;
this.outlineView = options.outlineView;
this.attachmentsView = options.attachmentsView;
this.disableNotification = options.disableNotification || false;
this._addEventListeners();
}
PDFSidebar.prototype = {
reset: function PDFSidebar_reset() {
this.isInitialViewSet = false;
this._hideUINotification(null);
this.switchView(SidebarView.THUMBS);
this.outlineButton.disabled = false;
this.attachmentsButton.disabled = false;
},
get visibleView() {
return this.isOpen ? this.active : SidebarView.NONE;
},
get isThumbnailViewVisible() {
return this.isOpen && this.active === SidebarView.THUMBS;
},
get isOutlineViewVisible() {
return this.isOpen && this.active === SidebarView.OUTLINE;
},
get isAttachmentsViewVisible() {
return this.isOpen && this.active === SidebarView.ATTACHMENTS;
},
setInitialView: function PDFSidebar_setInitialView(view) {
if (this.isInitialViewSet) {
return;
}
this.isInitialViewSet = true;
if (this.isOpen && view === SidebarView.NONE) {
this._dispatchEvent();
return;
}
var isViewPreserved = view === this.visibleView;
this.switchView(view, true);
if (isViewPreserved) {
this._dispatchEvent();
}
},
switchView: function PDFSidebar_switchView(view, forceOpen) {
if (view === SidebarView.NONE) {
this.close();
return;
}
var isViewChanged = view !== this.active;
var shouldForceRendering = false;
switch (view) {
case SidebarView.THUMBS:
this.thumbnailButton.classList.add('toggled');
this.outlineButton.classList.remove('toggled');
this.attachmentsButton.classList.remove('toggled');
this.thumbnailView.classList.remove('hidden');
this.outlineView.classList.add('hidden');
this.attachmentsView.classList.add('hidden');
if (this.isOpen && isViewChanged) {
this._updateThumbnailViewer();
shouldForceRendering = true;
}
break;
case SidebarView.OUTLINE:
if (this.outlineButton.disabled) {
return;
}
this.thumbnailButton.classList.remove('toggled');
this.outlineButton.classList.add('toggled');
this.attachmentsButton.classList.remove('toggled');
this.thumbnailView.classList.add('hidden');
this.outlineView.classList.remove('hidden');
this.attachmentsView.classList.add('hidden');
break;
case SidebarView.ATTACHMENTS:
if (this.attachmentsButton.disabled) {
return;
}
this.thumbnailButton.classList.remove('toggled');
this.outlineButton.classList.remove('toggled');
this.attachmentsButton.classList.add('toggled');
this.thumbnailView.classList.add('hidden');
this.outlineView.classList.add('hidden');
this.attachmentsView.classList.remove('hidden');
break;
default:
console.error('PDFSidebar_switchView: "' + view + '" is an unsupported value.');
return;
}
this.active = view | 0;
if (forceOpen && !this.isOpen) {
this.open();
return;
}
if (shouldForceRendering) {
this._forceRendering();
}
if (isViewChanged) {
this._dispatchEvent();
}
this._hideUINotification(this.active);
},
open: function PDFSidebar_open() {
if (this.isOpen) {
return;
}
this.isOpen = true;
this.toggleButton.classList.add('toggled');
this.outerContainer.classList.add('sidebarMoving');
this.outerContainer.classList.add('sidebarOpen');
if (this.active === SidebarView.THUMBS) {
this._updateThumbnailViewer();
}
this._forceRendering();
this._dispatchEvent();
this._hideUINotification(this.active);
},
close: function PDFSidebar_close() {
if (!this.isOpen) {
return;
}
this.isOpen = false;
this.toggleButton.classList.remove('toggled');
this.outerContainer.classList.add('sidebarMoving');
this.outerContainer.classList.remove('sidebarOpen');
this._forceRendering();
this._dispatchEvent();
},
toggle: function PDFSidebar_toggle() {
if (this.isOpen) {
this.close();
} else {
this.open();
}
},
_dispatchEvent: function PDFSidebar_dispatchEvent() {
this.eventBus.dispatch('sidebarviewchanged', {
source: this,
view: this.visibleView
});
},
_forceRendering: function PDFSidebar_forceRendering() {
if (this.onToggled) {
this.onToggled();
} else {
this.pdfViewer.forceRendering();
this.pdfThumbnailViewer.forceRendering();
}
},
_updateThumbnailViewer: function PDFSidebar_updateThumbnailViewer() {
var pdfViewer = this.pdfViewer;
var thumbnailViewer = this.pdfThumbnailViewer;
var pagesCount = pdfViewer.pagesCount;
for (var pageIndex = 0; pageIndex < pagesCount; pageIndex++) {
var pageView = pdfViewer.getPageView(pageIndex);
if (pageView && pageView.renderingState === RenderingStates.FINISHED) {
var thumbnailView = thumbnailViewer.getThumbnail(pageIndex);
thumbnailView.setImage(pageView);
}
}
thumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber);
},
_showUINotification: function (view) {
if (this.disableNotification) {
return;
}
this.toggleButton.title = mozL10n.get('toggle_sidebar_notification.title', null, 'Toggle Sidebar (document contains outline/attachments)');
if (!this.isOpen) {
this.toggleButton.classList.add(UI_NOTIFICATION_CLASS);
} else if (view === this.active) {
return;
}
switch (view) {
case SidebarView.OUTLINE:
this.outlineButton.classList.add(UI_NOTIFICATION_CLASS);
break;
case SidebarView.ATTACHMENTS:
this.attachmentsButton.classList.add(UI_NOTIFICATION_CLASS);
break;
}
},
_hideUINotification: function (view) {
if (this.disableNotification) {
return;
}
var removeNotification = function (view) {
switch (view) {
case SidebarView.OUTLINE:
this.outlineButton.classList.remove(UI_NOTIFICATION_CLASS);
break;
case SidebarView.ATTACHMENTS:
this.attachmentsButton.classList.remove(UI_NOTIFICATION_CLASS);
break;
}
}.bind(this);
if (!this.isOpen && view !== null) {
return;
}
this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS);
if (view !== null) {
removeNotification(view);
return;
}
for (view in SidebarView) {
removeNotification(SidebarView[view]);
}
this.toggleButton.title = mozL10n.get('toggle_sidebar.title', null, 'Toggle Sidebar');
},
_addEventListeners: function PDFSidebar_addEventListeners() {
var self = this;
self.mainContainer.addEventListener('transitionend', function (evt) {
if (evt.target === this) {
self.outerContainer.classList.remove('sidebarMoving');
}
});
self.thumbnailButton.addEventListener('click', function () {
self.switchView(SidebarView.THUMBS);
});
self.outlineButton.addEventListener('click', function () {
self.switchView(SidebarView.OUTLINE);
});
self.outlineButton.addEventListener('dblclick', function () {
self.pdfOutlineViewer.toggleOutlineTree();
});
self.attachmentsButton.addEventListener('click', function () {
self.switchView(SidebarView.ATTACHMENTS);
});
self.eventBus.on('outlineloaded', function (e) {
var outlineCount = e.outlineCount;
self.outlineButton.disabled = !outlineCount;
if (outlineCount) {
self._showUINotification(SidebarView.OUTLINE);
} else if (self.active === SidebarView.OUTLINE) {
self.switchView(SidebarView.THUMBS);
}
});
self.eventBus.on('attachmentsloaded', function (e) {
var attachmentsCount = e.attachmentsCount;
self.attachmentsButton.disabled = !attachmentsCount;
if (attachmentsCount) {
self._showUINotification(SidebarView.ATTACHMENTS);
} else if (self.active === SidebarView.ATTACHMENTS) {
self.switchView(SidebarView.THUMBS);
}
});
self.eventBus.on('presentationmodechanged', function (e) {
if (!e.active && !e.switchInProgress && self.isThumbnailViewVisible) {
self._updateThumbnailViewer();
}
});
}
};
return PDFSidebar;
}();
exports.SidebarView = SidebarView;
exports.PDFSidebar = PDFSidebar;
}));
(function (root, factory) {
factory(root.pdfjsWebPDFThumbnailView = {}, root.pdfjsWebUIUtils, root.pdfjsWebPDFRenderingQueue);
}(this, function (exports, uiUtils, pdfRenderingQueue) {
@ -3745,6 +3830,14 @@ var pdfjsWebLibs;
action: action
});
},
onFileAttachmentAnnotation: function (params) {
this.eventBus.dispatch('fileattachmentannotation', {
source: this,
id: params.id,
filename: params.filename,
content: params.content
});
},
cachePageRef: function PDFLinkService_cachePageRef(pageNum, pageRef) {
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
this._pagesRefCache[refStr] = pageNum;
@ -3827,6 +3920,8 @@ var pdfjsWebLibs;
},
executeNamedAction: function (action) {
},
onFileAttachmentAnnotation: function (params) {
},
cachePageRef: function (pageNum, pageRef) {
}
};
@ -4074,7 +4169,6 @@ var pdfjsWebLibs;
this.renderingState = RenderingStates.RUNNING;
var self = this;
var pdfPage = this.pdfPage;
var viewport = this.viewport;
var div = this.div;
var canvasWrapper = document.createElement('div');
canvasWrapper.style.width = div.style.width;
@ -4194,8 +4288,6 @@ var pdfjsWebLibs;
renderTask.cancel();
}
};
var self = this;
var pdfPage = this.pdfPage;
var viewport = this.viewport;
var canvas = document.createElement('canvas');
canvas.id = 'page' + this.id;

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

@ -471,8 +471,6 @@
@RESPATH@/components/formautofill.manifest
@RESPATH@/components/FormAutofillContentService.js
@RESPATH@/components/FormAutofillStartup.js
@RESPATH@/components/CSSUnprefixingService.js
@RESPATH@/components/CSSUnprefixingService.manifest
@RESPATH@/components/contentAreaDropListener.manifest
@RESPATH@/components/contentAreaDropListener.js
@RESPATH@/browser/components/BrowserProfileMigrators.manifest

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

@ -838,16 +838,10 @@ Function LaunchApp
FunctionEnd
Function LaunchAppFromElevatedProcess
; Find the installation directory when launching using GetFunctionAddress
; from an elevated installer since $INSTDIR will not be set in this installer
${StrFilter} "${FileMainEXE}" "+" "" "" $R9
ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
${GetPathFromString} "$0" $0
${GetParent} "$0" $1
; Set our current working directory to the application's install directory
; otherwise the 7-Zip temp directory will be in use and won't be deleted.
SetOutPath "$1"
Exec "$\"$0$\""
SetOutPath "$INSTDIR"
Exec "$\"$INSTDIR\${FileMainEXE}$\""
FunctionEnd
################################################################################

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

@ -2065,15 +2065,9 @@ Function LaunchApp
FunctionEnd
Function LaunchAppFromElevatedProcess
; Find the installation directory when launching using GetFunctionAddress
; from an elevated installer since $INSTDIR will not be set in this installer
${StrFilter} "${FileMainEXE}" "+" "" "" $R9
ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
${GetPathFromString} "$0" $0
; Set the current working directory to the installation directory
${GetParent} "$0" $1
SetOutPath "$1"
Exec "$\"$0$\""
SetOutPath "$INSTDIR"
Exec "$\"$INSTDIR\${FileMainEXE}$\""
FunctionEnd
Function CopyPostSigningData

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

@ -101,6 +101,7 @@ print_progress_close=Cancel
# (the _label strings are alt text for the buttons, the .title strings are
# tooltips)
toggle_sidebar.title=Toggle Sidebar
toggle_sidebar_notification.title=Toggle Sidebar (document contains outline/attachments)
toggle_sidebar_label=Toggle Sidebar
document_outline.title=Show Document Outline (double-click to expand/collapse all items)
document_outline_label=Document Outline

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

@ -4,6 +4,38 @@
"google", "yahoo", "amazondotcom", "bing", "ddg", "twitter", "wikipedia"
]
},
"regionOverrides": {
"US": {
"google": "google-nocodes"
},
"CA": {
"google": "google-nocodes"
},
"KZ": {
"google": "google-nocodes"
},
"BY": {
"google": "google-nocodes"
},
"RU": {
"google": "google-nocodes"
},
"TR": {
"google": "google-nocodes"
},
"UA": {
"google": "google-nocodes"
},
"CN": {
"google": "google-nocodes"
},
"TW": {
"google": "google-nocodes"
},
"HK": {
"google": "google-nocodes"
}
},
"locales": {
"en-US": {
"default": {
@ -11,16 +43,6 @@
"google", "yahoo", "amazondotcom", "bing", "ddg", "twitter", "wikipedia"
]
},
"US": {
"visibleDefaultEngines": [
"yahoo", "google-nocodes", "bing", "amazondotcom", "ddg", "twitter", "wikipedia"
]
},
"CA": {
"visibleDefaultEngines": [
"google-nocodes", "yahoo", "bing", "amazondotcom", "ddg", "twitter", "wikipedia"
]
},
"experimental-hidden": {
"visibleDefaultEngines": [
"yahoo-en-CA"
@ -396,31 +418,6 @@
"visibleDefaultEngines": [
"yandex-kk", "google", "ddg", "flip", "kaz-kk", "twitter", "wikipedia-kk"
]
},
"KZ": {
"visibleDefaultEngines": [
"yandex-kk", "google-nocodes", "ddg", "flip", "kaz-kk", "twitter", "wikipedia-kk"
]
},
"BY": {
"visibleDefaultEngines": [
"yandex-kk", "google-nocodes", "ddg", "flip", "kaz-kk", "twitter", "wikipedia-kk"
]
},
"RU": {
"visibleDefaultEngines": [
"yandex-kk", "google-nocodes", "ddg", "flip", "kaz-kk", "twitter", "wikipedia-kk"
]
},
"TR": {
"visibleDefaultEngines": [
"yandex-kk", "google-nocodes", "ddg", "flip", "kaz-kk", "twitter", "wikipedia-kk"
]
},
"UA": {
"visibleDefaultEngines": [
"yandex-kk", "google-nocodes", "ddg", "flip", "kaz-kk", "twitter", "wikipedia-kk"
]
}
},
"km": {
@ -596,31 +593,6 @@
"visibleDefaultEngines": [
"yandex-ru", "google", "ddg", "ozonru", "priceru", "wikipedia-ru", "mailru"
]
},
"RU": {
"visibleDefaultEngines": [
"yandex-ru", "google-nocodes", "ddg", "ozonru", "priceru", "wikipedia-ru", "mailru"
]
},
"BY": {
"visibleDefaultEngines": [
"yandex-ru", "google-nocodes", "ddg", "ozonru", "priceru", "wikipedia-ru", "mailru"
]
},
"KZ": {
"visibleDefaultEngines": [
"yandex-ru", "google-nocodes", "ddg", "ozonru", "priceru", "wikipedia-ru", "mailru"
]
},
"TR": {
"visibleDefaultEngines": [
"yandex-ru", "google-nocodes", "ddg", "ozonru", "priceru", "wikipedia-ru", "mailru"
]
},
"UA": {
"visibleDefaultEngines": [
"yandex-ru", "google-nocodes", "ddg", "ozonru", "priceru", "wikipedia-ru", "mailru"
]
}
},
"si": {
@ -705,31 +677,6 @@
"visibleDefaultEngines": [
"yandex-tr", "google", "ddg", "twitter", "wikipedia-tr"
]
},
"TR": {
"visibleDefaultEngines": [
"yandex-tr", "google-nocodes", "ddg", "twitter", "wikipedia-tr"
]
},
"BY": {
"visibleDefaultEngines": [
"yandex-tr", "google-nocodes", "ddg", "twitter", "wikipedia-tr"
]
},
"KZ": {
"visibleDefaultEngines": [
"yandex-tr", "google-nocodes", "ddg", "twitter", "wikipedia-tr"
]
},
"RU": {
"visibleDefaultEngines": [
"yandex-tr", "google-nocodes", "ddg", "twitter", "wikipedia-tr"
]
},
"UA": {
"visibleDefaultEngines": [
"yandex-tr", "google-nocodes", "ddg", "twitter", "wikipedia-tr"
]
}
},
"uk": {
@ -737,31 +684,6 @@
"visibleDefaultEngines": [
"google", "yandex-uk", "meta-ua", "ddg", "wikipedia-uk", "metamarket"
]
},
"UA": {
"visibleDefaultEngines": [
"google-nocodes", "yandex-uk", "meta-ua", "ddg", "wikipedia-uk", "metamarket"
]
},
"TR": {
"visibleDefaultEngines": [
"google-nocodes", "yandex-uk", "meta-ua", "ddg", "wikipedia-uk", "metamarket"
]
},
"BY": {
"visibleDefaultEngines": [
"google-nocodes", "yandex-uk", "meta-ua", "ddg", "wikipedia-uk", "metamarket"
]
},
"KZ": {
"visibleDefaultEngines": [
"google-nocodes", "yandex-uk", "meta-ua", "ddg", "wikipedia-uk", "metamarket"
]
},
"RU": {
"visibleDefaultEngines": [
"google-nocodes", "yandex-uk", "meta-ua", "ddg", "wikipedia-uk", "metamarket"
]
}
},
"ur": {
@ -811,16 +733,6 @@
"visibleDefaultEngines": [
"yahoo-zh-TW", "google", "ddg", "findbook-zh-TW", "wikipedia-zh-TW", "yahoo-zh-TW-HK", "yahoo-bid-zh-TW", "yahoo-answer-zh-TW"
]
},
"TW": {
"visibleDefaultEngines": [
"yahoo-zh-TW", "google-nocodes", "ddg", "findbook-zh-TW", "wikipedia-zh-TW", "yahoo-zh-TW-HK", "yahoo-bid-zh-TW", "yahoo-answer-zh-TW"
]
},
"HK": {
"visibleDefaultEngines": [
"yahoo-zh-TW-HK", "google-nocodes", "ddg", "findbook-zh-TW", "wikipedia-zh-TW", "yahoo-zh-TW", "yahoo-bid-zh-TW", "yahoo-answer-zh-TW"
]
}
}
}

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

@ -455,6 +455,7 @@ this.ContentSearch = {
if (msg.target.contentWindow) {
engine.speculativeConnect({
window: msg.target.contentWindow,
originAttributes: msg.target.contentPrincipal.originAttributes
});
}
},

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

@ -20,6 +20,10 @@
color: ButtonText;
}
#placesToolbar > toolbarbutton[disabled=true] {
color: GrayText;
}
/* back button */
#back-button {

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

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
<style type="text/css">
path {
stroke: #bb3817;
fill: #FFFFFF;
}
</style>
<path d="M6.6,9c0.3,0,0.5-0.3,0.6-0.6C7,7.7,7,6.9,7.1,6.2c0.1-0.3,0.3-0.4,0.6-0.4c0.3,0,0.3,0.4,1,0.4
c0.3,0,0.8-0.1,0.8-1.1S9,3.9,8.7,3.9c-0.6,0-0.7,0.5-1,0.5c-0.3,0-0.5-0.2-0.6-0.5c0-0.3,0-0.7,0-1c0-0.3-0.2-0.5-0.5-0.6
c0,0,0,0-0.1,0c-0.5,0-1,0.1-1.6,0C4.7,2.3,4.5,2.1,4.6,1.8c0-0.4,0.4-0.3,0.4-1C5,0.5,4.9,0,3.8,0S2.7,0.5,2.7,0.8
c0,0.6,0.5,0.7,0.5,1c0,0.3-0.2,0.5-0.5,0.5C2.1,2.4,1.6,2.4,1,2.4c-0.3,0-0.5,0.2-0.6,0.5c0,0,0,0,0,0.1v0.7c0,0-0.1,0.8,0.6,0.8
C1.5,4.5,1.6,4,2.2,4c0.3,0,0.7,0.7,0.7,1.3S2.4,6.6,2.2,6.6C1.6,6.6,1.5,6,1.1,6C0.4,5.9,0.5,6.7,0.5,6.7v1.7C0.4,8.7,0.7,9,1,9
c0,0,0,0,0,0h2.1C3.1,9,4,9,4,8.4c0-0.4-0.7-0.6-0.7-1.2C3.5,6.7,4,6.3,4.5,6.3c0.6,0,1.2,0.6,1.2,0.8c0,0.6-0.6,0.8-0.6,1.2
C5.1,9,5.9,9,5.9,9L6.6,9z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.2 KiB

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

@ -157,7 +157,7 @@
#PanelUI-menu-button[badge-status="addon-alert"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
height: 13px;
background: transparent url(chrome://browser/skin/addons/addon-badge.svg) no-repeat center;
background: #FFBF00 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
}
.panel-subviews {
@ -589,7 +589,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-footer-addons > toolbarbutton {
background-color: #C7F5FF;
background-color: #FFEFBF;
display: flex;
flex: 1 1 0%;
width: calc(@menuPanelWidth@ + 30px);
@ -597,13 +597,21 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
border-inline-start-style: none;
}
#PanelUI-footer-addons > toolbarbutton:hover {
background-color: #FFE8A2;
}
#PanelUI-footer-addons > toolbarbutton:active {
background-color: #FFE38F;
}
#PanelUI-footer-addons > toolbarbutton > .toolbarbutton-icon {
width: 14px;
height: 14px;
}
#PanelUI-footer-addons > toolbarbutton::after {
background-image: url(chrome://browser/skin/addons/addon-badge.svg);
background: #FFBF00 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
}
#PanelUI-fxa-status {

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

@ -16,7 +16,6 @@
skin/classic/browser/aboutTabCrashed.css (../shared/aboutTabCrashed.css)
skin/classic/browser/aboutWelcomeBack.css (../shared/aboutWelcomeBack.css)
skin/classic/browser/content-contextmenu.svg (../shared/content-contextmenu.svg)
skin/classic/browser/addons/addon-badge.svg (../shared/addons/addon-badge.svg)
skin/classic/browser/addons/addon-install-blocked.svg (../shared/addons/addon-install-blocked.svg)
skin/classic/browser/addons/addon-install-confirm.svg (../shared/addons/addon-install-confirm.svg)
skin/classic/browser/addons/addon-install-downloading.svg (../shared/addons/addon-install-downloading.svg)

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

@ -746,7 +746,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
}
#nav-bar .toolbarbutton-1[type=panel] > .toolbarbutton-icon,
#nav-bar .toolbarbutton-1[type=menu]:not(#PanelUI-menu-button):not(#back-button):not(#forward-button) > .toolbarbutton-icon {
#nav-bar .toolbarbutton-1[type=menu]:not(#PanelUI-menu-button):not(#back-button):not(#forward-button):not(#new-tab-button) > .toolbarbutton-icon {
/* horizontal padding + border + icon width */
max-width: 43px;
}

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

@ -42,8 +42,6 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
dnl --cxxflags. We use sed to remove this argument so that builds work on OSX
LLVM_CXXFLAGS=`$LLVMCONFIG --cxxflags | sed -e 's/-isysroot [[^ ]]*//'`
dnl We are loaded into clang, so we don't need to link to very many things,
dnl we just need to link to clangASTMatchers because it is not used by clang
LLVM_LDFLAGS=`$LLVMCONFIG --ldflags | tr '\n' ' '`
if test "${HOST_OS_ARCH}" = "Darwin"; then
@ -54,7 +52,14 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
dnl access to all of the symbols which are undefined in our dylib as we
dnl are building it right now, and also that we don't fail the build
dnl due to undefined symbols (which will be provided by clang).
CLANG_LDFLAGS="-Wl,-flat_namespace -Wl,-undefined,suppress -lclangASTMatchers"
CLANG_LDFLAGS="-Wl,-flat_namespace -Wl,-undefined,suppress"
dnl We are loaded into clang, so we don't need to link to very many things,
dnl we just need to link to clangASTMatchers because it is not used by clang
CLANG_LDFLAGS="$CLANG_LDFLAGS `$LLVMCONFIG --prefix`/lib/libclangASTMatchers.a"
dnl We need to remove -L/path/to/clang/lib from LDFLAGS to ensure that we
dnl don't accidentally link against the libc++ there which is a newer
dnl version that what our build machines have installed.
LLVM_LDFLAGS=`echo "$LLVM_LDFLAGS" | sed -E 's/-L[[^ ]]+\/clang\/lib//'`
elif test "${HOST_OS_ARCH}" = "WINNT"; then
CLANG_LDFLAGS="clang.lib"
else

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

@ -39,10 +39,12 @@ build-clang.py accepts a JSON config format with the following fields:
* gcc_dir: Path to the gcc toolchain installation, only required on Linux.
* cc: Path to the bootsraping C Compiler.
* cxx: Path to the bootsraping C++ Compiler.
* as: Path to the assembler tool.
* ar: Path to the library archiver tool.
* ranlib: Path to the ranlib tool.
* ranlib: Path to the ranlib tool (optional).
* libtool: Path to the libtool tool (optional).
* ld: Path to the linker.
* patches: Optional list of patches to apply per platform. Supported platforms: macosx64, linux32, linux64. The default is Release.
* patches: Optional list of patches to apply.
* build_type: The type of build to make. Supported types: Release, Debug, RelWithDebInfo or MinSizeRel.
* build_libcxx: Whether to build with libcxx. The default is false.
* build_clang_tidy: Whether to build clang-tidy with the Mozilla checks imported. The default is false.

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

@ -170,24 +170,6 @@ def svn_update(directory, revision):
run_in(directory, ["svn", "revert", "-q", "-R", revision])
def get_platform():
p = platform.system()
if p == "Darwin":
return "macosx64"
elif p == "Linux":
if platform.architecture() == "AMD64":
return "linux64"
else:
return "linux32"
elif p == "Windows":
if platform.architecture() == "AMD64":
return "win64"
else:
return "win32"
else:
raise NotImplementedError("Not supported platform")
def is_darwin():
return platform.system() == "Darwin"
@ -200,7 +182,7 @@ def is_windows():
return platform.system() == "Windows"
def build_one_stage(cc, cxx, ld, ar, ranlib,
def build_one_stage(cc, cxx, asm, ld, ar, ranlib, libtool,
src_dir, stage_dir, build_libcxx,
osx_cross_compile, build_type, assertions,
python_path, gcc_dir, libcxx_include_dir):
@ -225,11 +207,12 @@ def build_one_stage(cc, cxx, ld, ar, ranlib,
cmake_args = ["-GNinja",
"-DCMAKE_C_COMPILER=%s" % slashify_path(cc[0]),
"-DCMAKE_CXX_COMPILER=%s" % slashify_path(cxx[0]),
"-DCMAKE_ASM_COMPILER=%s" % slashify_path(cc[0]),
"-DCMAKE_ASM_COMPILER=%s" % slashify_path(asm[0]),
"-DCMAKE_LINKER=%s" % slashify_path(ld[0]),
"-DCMAKE_AR=%s" % slashify_path(ar),
"-DCMAKE_C_FLAGS=%s" % ' '.join(cc[1:]),
"-DCMAKE_CXX_FLAGS=%s" % ' '.join(cxx[1:]),
"-DCMAKE_ASM_FLAGS=%s" % ' '.join(asm[1:]),
"-DCMAKE_EXE_LINKER_FLAGS=%s" % ' '.join(ld[1:]),
"-DCMAKE_SHARED_LINKER_FLAGS=%s" % ' '.join(ld[1:]),
"-DCMAKE_BUILD_TYPE=%s" % build_type,
@ -245,6 +228,8 @@ def build_one_stage(cc, cxx, ld, ar, ranlib,
cmake_args.insert(-1, "-DLLVM_USE_CRT_RELEASE=MT")
if ranlib is not None:
cmake_args += ["-DCMAKE_RANLIB=%s" % slashify_path(ranlib)]
if libtool is not None:
cmake_args += ["-DCMAKE_LIBTOOL=%s" % slashify_path(libtool)]
if osx_cross_compile:
cmake_args += ["-DCMAKE_SYSTEM_NAME=Darwin",
"-DCMAKE_SYSTEM_VERSION=10.10",
@ -258,7 +243,7 @@ def build_one_stage(cc, cxx, ld, ar, ranlib,
"-DCMAKE_MACOSX_RPATH=@executable_path",
"-DCMAKE_OSX_ARCHITECTURES=x86_64",
"-DDARWIN_osx_ARCHS=x86_64",
"-DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-apple-darwin10"]
"-DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-apple-darwin11"]
build_package(build_dir, cmake_args)
if is_linux():
@ -464,9 +449,13 @@ if __name__ == "__main__":
raise ValueError("Config file needs to set gcc_dir")
cc = get_tool(config, "cc")
cxx = get_tool(config, "cxx")
asm = get_tool(config, "ml" if is_windows() else "as")
ld = get_tool(config, "link" if is_windows() else "ld")
ar = get_tool(config, "lib" if is_windows() else "ar")
ranlib = None if is_windows() else get_tool(config, "ranlib")
libtool = None
if "libtool" in config:
libtool = get_tool(config, "libtool")
if not os.path.exists(source_dir):
os.makedirs(source_dir)
@ -485,7 +474,7 @@ if __name__ == "__main__":
checkout_or_update(libcxxabi_repo, libcxxabi_source_dir)
if extra_repo:
checkout_or_update(extra_repo, extra_source_dir)
for p in config.get("patches", {}).get(get_platform(), []):
for p in config.get("patches", []):
patch(p, source_dir)
symlinks = [(source_dir + "/clang",
@ -525,12 +514,14 @@ if __name__ == "__main__":
extra_cxxflags = ["-stdlib=libc++"]
extra_cflags2 = []
extra_cxxflags2 = ["-stdlib=libc++"]
extra_asmflags = []
extra_ldflags = []
elif is_linux():
extra_cflags = ["-static-libgcc"]
extra_cxxflags = ["-static-libgcc", "-static-libstdc++"]
extra_cflags2 = ["-fPIC"]
extra_cxxflags2 = ["-fPIC", "-static-libstdc++"]
extra_asmflags = []
extra_ldflags = []
if os.environ.has_key('LD_LIBRARY_PATH'):
@ -545,6 +536,7 @@ if __name__ == "__main__":
# Force things on.
extra_cflags2 = []
extra_cxxflags2 = ['-fms-compatibility-version=19.00.24213', '-Xclang', '-std=c++14']
extra_asmflags = []
extra_ldflags = []
if osx_cross_compile:
@ -554,7 +546,7 @@ if __name__ == "__main__":
extra_cxxflags = ["-stdlib=libc++"]
extra_cxxflags2 = ["-stdlib=libc++"]
extra_flags = ["-target", "x86_64-apple-darwin10", "-mlinker-version=136",
extra_flags = ["-target", "x86_64-apple-darwin11", "-mlinker-version=137",
"-B", "%s/bin" % os.getenv("CROSS_CCTOOLS_PATH"),
"-isysroot", os.getenv("CROSS_SYSROOT"),
# technically the sysroot flag there should be enough to deduce this,
@ -565,14 +557,16 @@ if __name__ == "__main__":
extra_cxxflags += extra_flags
extra_cflags2 += extra_flags
extra_cxxflags2 += extra_flags
extra_asmflags += extra_flags
extra_ldflags = ["-Wl,-syslibroot,%s" % os.getenv("CROSS_SYSROOT"),
"-Wl,-dead_strip"]
build_one_stage(
[cc] + extra_cflags,
[cxx] + extra_cxxflags,
[asm] + extra_asmflags,
[ld] + extra_ldflags,
ar, ranlib,
ar, ranlib, libtool,
llvm_source_dir, stage1_dir, build_libcxx, osx_cross_compile,
build_type, assertions, python_path, gcc_dir, libcxx_include_dir)
@ -585,8 +579,10 @@ if __name__ == "__main__":
(cc_name, exe_ext)] + extra_cflags2,
[stage1_inst_dir + "/bin/%s%s" %
(cxx_name, exe_ext)] + extra_cxxflags2,
[stage1_inst_dir + "/bin/%s%s" %
(cc_name, exe_ext)] + extra_asmflags,
[ld] + extra_ldflags,
ar, ranlib,
ar, ranlib, libtool,
llvm_source_dir, stage2_dir, build_libcxx, osx_cross_compile,
build_type, assertions, python_path, gcc_dir, libcxx_include_dir)
@ -598,8 +594,10 @@ if __name__ == "__main__":
(cc_name, exe_ext)] + extra_cflags2,
[stage2_inst_dir + "/bin/%s%s" %
(cxx_name, exe_ext)] + extra_cxxflags2,
[stage2_inst_dir + "/bin/%s%s" %
(cc_name, exe_ext)] + extra_asmflags,
[ld] + extra_ldflags,
ar, ranlib,
ar, ranlib, libtool,
llvm_source_dir, stage3_dir, build_libcxx, osx_cross_compile,
build_type, assertions, python_path, gcc_dir, libcxx_include_dir)

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

@ -13,15 +13,8 @@
"gcc_dir": "/home/worker/workspace/build/src/gcc",
"cc": "/home/worker/workspace/build/src/gcc/bin/gcc",
"cxx": "/home/worker/workspace/build/src/gcc/bin/g++",
"patches": {
"macosx64": [
"llvm-debug-frame.patch"
],
"linux64": [
"llvm-debug-frame.patch"
],
"linux32": [
"llvm-debug-frame.patch"
]
}
"as": "/home/worker/workspace/build/src/gcc/bin/gcc",
"patches": [
"llvm-debug-frame.patch"
]
}

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

@ -1,29 +1,29 @@
{
"llvm_revision": "262557",
"stages": "3",
"llvm_revision": "290136",
"stages": "1",
"build_libcxx": true,
"build_type": "Release",
"assertions": false,
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_380/final",
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_380/final",
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_380/final",
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_380/final",
"python_path": "/usr/local/bin/python2.7",
"cc": "/Users/cltbld/clang/bin/clang",
"cxx": "/Users/cltbld/clang/bin/clang++",
"patches": {
"macosx64": [
"disable-mac-tsan.patch",
"llvm-debug-frame.patch",
"return-empty-string-non-mangled.patch"
],
"linux64": [
"llvm-debug-frame.patch",
"return-empty-string-non-mangled.patch"
],
"linux32": [
"llvm-debug-frame.patch",
"return-empty-string-non-mangled.patch"
]
}
"osx_cross_compile": true,
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_390/final",
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_390/final",
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_390/final",
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_390/final",
"libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_390/final",
"python_path": "/usr/bin/python2.7",
"gcc_dir": "/home/worker/workspace/build/src/gcc",
"cc": "/home/worker/workspace/build/src/clang/bin/clang",
"cxx": "/home/worker/workspace/build/src/clang/bin/clang++",
"as": "/home/worker/workspace/build/src/clang/bin/clang",
"ar": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin11-ar",
"ranlib": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin11-ranlib",
"libtool": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin11-libtool",
"ld": "/home/worker/workspace/build/src/clang/bin/clang",
"patches":[
"llvm-debug-frame.patch",
"compiler-rt-cross-compile.patch",
"pr28831-r280042.patch",
"r277806.patch",
"r285657.patch"
]
}

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

@ -10,7 +10,5 @@
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
"python_path": "c:/mozilla-build/python/python.exe",
"cc": "cl.exe",
"cxx": "cl.exe",
"patches": {
}
"cxx": "cl.exe"
}

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

@ -11,6 +11,5 @@
"python_path": "c:/mozilla-build/python/python.exe",
"cc": "cl.exe",
"cxx": "cl.exe",
"patches": {
}
"ml": "ml64.exe"
}

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

@ -14,5 +14,6 @@
"python_path": "/usr/bin/python2.7",
"gcc_dir": "/home/worker/workspace/build/src/gcc",
"cc": "/home/worker/workspace/build/src/gcc/bin/gcc",
"cxx": "/home/worker/workspace/build/src/gcc/bin/g++"
"cxx": "/home/worker/workspace/build/src/gcc/bin/g++",
"as": "/home/worker/workspace/build/src/gcc/bin/gcc"
}

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

@ -16,7 +16,12 @@
"gcc_dir": "/home/worker/workspace/build/src/gcc",
"cc": "/home/worker/workspace/build/src/clang/bin/clang",
"cxx": "/home/worker/workspace/build/src/clang/bin/clang++",
"ar": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin10-ar",
"ranlib": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin10-ranlib",
"ld": "/home/worker/workspace/build/src/clang/bin/clang"
"as": "/home/worker/workspace/build/src/clang/bin/clang",
"ar": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin11-ar",
"ranlib": "/home/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin11-ranlib",
"ld": "/home/worker/workspace/build/src/clang/bin/clang",
"patches": [
"llvm-debug-frame.patch",
"compiler-rt-cross-compile.patch"
]
}

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

@ -12,5 +12,6 @@
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
"python_path": "c:/mozilla-build/python/python.exe",
"cc": "cl.exe",
"cxx": "cl.exe"
"cxx": "cl.exe",
"ml": "ml64.exe"
}

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

@ -0,0 +1,15 @@
Add `-target x86_64-apple-darwin11' to the compiler-rt overridden CFLAGS
diff --git a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake
index 28d398672..aac68bf36 100644
--- a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake
+++ b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake
@@ -265,7 +265,7 @@ endfunction()
macro(darwin_add_builtin_libraries)
set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes)
- set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer")
+ set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer -target x86_64-apple-darwin11 -isysroot ${CMAKE_OSX_SYSROOT} -I${CMAKE_OSX_SYSROOT}/usr/include")
set(CMAKE_C_FLAGS "")
set(CMAKE_CXX_FLAGS "")
set(CMAKE_ASM_FLAGS "")

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

@ -1,11 +0,0 @@
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -617,7 +617,7 @@
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
- OS_NAME MATCHES "Darwin|Linux|FreeBSD")
+ OS_NAME MATCHES "Linux|FreeBSD")
set(COMPILER_RT_HAS_TSAN TRUE)
else()
set(COMPILER_RT_HAS_TSAN FALSE)

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

@ -0,0 +1,19 @@
Backport the fix to PR28831 plus its follow-up (r280042)
diff --git a/libcxx/lib/CMakeLists.txt b/libcxx/lib/CMakeLists.txt
index afc388e76..4f43f3711 100644
--- a/libcxx/lib/CMakeLists.txt
+++ b/libcxx/lib/CMakeLists.txt
@@ -115,9 +115,9 @@ if ( APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR
"-Wl,-unexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++unexp.exp"
"/usr/lib/libSystem.B.dylib")
else()
- if ( ${CMAKE_OSX_SYSROOT} )
- list(FIND ${CMAKE_OSX_ARCHITECTURES} "armv7" OSX_HAS_ARMV7)
- if (OSX_HAS_ARMV7)
+ if (DEFINED CMAKE_OSX_SYSROOT)
+ list(FIND CMAKE_OSX_ARCHITECTURES "armv7" OSX_HAS_ARMV7)
+ if (NOT OSX_HAS_ARMV7 EQUAL -1)
set(OSX_RE_EXPORT_LINE
"${CMAKE_OSX_SYSROOT}/usr/lib/libc++abi.dylib"
"-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++sjlj-abi.exp")

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

@ -1,79 +0,0 @@
commit 865b9340996f9f9d04b73b187248737dc6fd845e
Author: Michael Wu <mwu@mozilla.com>
Date: Mon Sep 14 17:47:21 2015 -0400
Add support for querying the visibility of a cursor
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index fad9cfa..311bfcb 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2440,6 +2440,24 @@ enum CXLinkageKind {
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
/**
+ * \brief Describe the visibility of the entity referred to by a cursor.
+ */
+enum CXVisibilityKind {
+ /** \brief This value indicates that no visibility information is available
+ * for a provided CXCursor. */
+ CXVisibility_Invalid,
+
+ /** \brief Symbol not seen by the linker. */
+ CXVisibility_Hidden,
+ /** \brief Symbol seen by the linker but resolves to a symbol inside this object. */
+ CXVisibility_Protected,
+ /** \brief Symbol seen by the linker and acts like a normal symbol. */
+ CXVisibility_Default,
+};
+
+CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
+
+/**
* \brief Determine the availability of the entity that this cursor refers to,
* taking the current target platform into account.
*
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 8225a6c..9fa18d3 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -6361,6 +6361,27 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
} // end: extern "C"
//===----------------------------------------------------------------------===//
+// Operations for querying visibility of a cursor.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
+ if (!clang_isDeclaration(cursor.kind))
+ return CXVisibility_Invalid;
+
+ const Decl *D = cxcursor::getCursorDecl(cursor);
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+ switch (ND->getVisibility()) {
+ case HiddenVisibility: return CXVisibility_Hidden;
+ case ProtectedVisibility: return CXVisibility_Protected;
+ case DefaultVisibility: return CXVisibility_Default;
+ };
+
+ return CXVisibility_Invalid;
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
// Operations for querying language of a cursor.
//===----------------------------------------------------------------------===//
diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
index f6a7175..a919a8e 100644
--- a/clang/tools/libclang/libclang.exports
+++ b/clang/tools/libclang/libclang.exports
@@ -173,6 +173,7 @@ clang_getCursorSemanticParent
clang_getCursorSpelling
clang_getCursorType
clang_getCursorUSR
+clang_getCursorVisibility
clang_getDeclObjCTypeEncoding
clang_getDefinitionSpellingAndExtent
clang_getDiagnostic

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

@ -0,0 +1,321 @@
commit eca7f4535bffb1c86cb1620b9d9425ff3ce31ab9
Author: John Brawn <john.brawn@arm.com>
Date: Fri Aug 5 11:01:08 2016 +0000
Reapply r276973 "Adjust Registry interface to not require plugins to export a registry"
This differs from the previous version by being more careful about template
instantiation/specialization in order to prevent errors when building with
clang -Werror. Specifically:
* begin is not defined in the template and is instead instantiated when Head
is. I think the warning when we don't do that is wrong (PR28815) but for now
at least do it this way to avoid the warning.
* Instead of performing template specializations in LLVM_INSTANTIATE_REGISTRY
instead provide a template definition then do explicit instantiation. No
compiler I've tried has problems with doing it the other way, but strictly
speaking it's not permitted by the C++ standard so better safe than sorry.
Original commit message:
Currently the Registry class contains the vestiges of a previous attempt to
allow plugins to be used on Windows without using BUILD_SHARED_LIBS, where a
plugin would have its own copy of a registry and export it to be imported by
the tool that's loading the plugin. This only works if the plugin is entirely
self-contained with the only interface between the plugin and tool being the
registry, and in particular this conflicts with how IR pass plugins work.
This patch changes things so that instead the add_node function of the registry
is exported by the tool and then imported by the plugin, which solves this
problem and also means that instead of every plugin having to export every
registry they use instead LLVM only has to export the add_node functions. This
allows plugins that use a registry to work on Windows if
LLVM_EXPORT_SYMBOLS_FOR_PLUGINS is used.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277806 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/llvm/include/llvm/Support/Registry.h b/llvm/include/llvm/Support/Registry.h
index 27f025fcd08..9557f56093b 100644
--- a/llvm/include/llvm/Support/Registry.h
+++ b/llvm/include/llvm/Support/Registry.h
@@ -44,6 +44,7 @@ namespace llvm {
template <typename T>
class Registry {
public:
+ typedef T type;
typedef SimpleRegistryEntry<T> entry;
class node;
@@ -69,13 +70,14 @@ namespace llvm {
node(const entry &V) : Next(nullptr), Val(V) {}
};
- static void add_node(node *N) {
- if (Tail)
- Tail->Next = N;
- else
- Head = N;
- Tail = N;
- }
+ /// Add a node to the Registry: this is the interface between the plugin and
+ /// the executable.
+ ///
+ /// This function is exported by the executable and called by the plugin to
+ /// add a node to the executable's registry. Therefore it's not defined here
+ /// to avoid it being instantiated in the plugin and is instead defined in
+ /// the executable (see LLVM_INSTANTIATE_REGISTRY below).
+ static void add_node(node *N);
/// Iterators for registry entries.
///
@@ -92,7 +94,9 @@ namespace llvm {
const entry *operator->() const { return &Cur->Val; }
};
- static iterator begin() { return iterator(Head); }
+ // begin is not defined here in order to avoid usage of an undefined static
+ // data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY.
+ static iterator begin();
static iterator end() { return iterator(nullptr); }
static iterator_range<iterator> entries() {
@@ -120,61 +124,37 @@ namespace llvm {
add_node(&Node);
}
};
-
- /// A dynamic import facility. This is used on Windows to
- /// import the entries added in the plugin.
- static void import(sys::DynamicLibrary &DL, const char *RegistryName) {
- typedef void *(*GetRegistry)();
- std::string Name("LLVMGetRegistry_");
- Name.append(RegistryName);
- GetRegistry Getter =
- (GetRegistry)(intptr_t)DL.getAddressOfSymbol(Name.c_str());
- if (Getter) {
- // Call the getter function in order to get the full copy of the
- // registry defined in the plugin DLL, and copy them over to the
- // current Registry.
- typedef std::pair<const node *, const node *> Info;
- Info *I = static_cast<Info *>(Getter());
- iterator begin(I->first);
- iterator end(I->second);
- for (++end; begin != end; ++begin) {
- // This Node object needs to remain alive for the
- // duration of the program.
- add_node(new node(*begin));
- }
- }
- }
-
- /// Retrieve the data to be passed across DLL boundaries when
- /// importing registries from another DLL on Windows.
- static void *exportRegistry() {
- static std::pair<const node *, const node *> Info(Head, Tail);
- return &Info;
- }
};
-
-
- // Since these are defined in a header file, plugins must be sure to export
- // these symbols.
- template <typename T>
- typename Registry<T>::node *Registry<T>::Head;
-
- template <typename T>
- typename Registry<T>::node *Registry<T>::Tail;
} // end namespace llvm
-#ifdef LLVM_ON_WIN32
-#define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS) \
- extern "C" { \
- __declspec(dllexport) void *__cdecl LLVMGetRegistry_##REGISTRY_CLASS() { \
- return REGISTRY_CLASS::exportRegistry(); \
- } \
+/// Instantiate a registry class.
+///
+/// This provides template definitions of add_node, begin, and the Head and Tail
+/// pointers, then explicitly instantiates them. We could explicitly specialize
+/// them, instead of the two-step process of define then instantiate, but
+/// strictly speaking that's not allowed by the C++ standard (we would need to
+/// have explicit specialization declarations in all translation units where the
+/// specialization is used) so we don't.
+#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
+ namespace llvm { \
+ template<typename T> typename Registry<T>::node *Registry<T>::Head = nullptr;\
+ template<typename T> typename Registry<T>::node *Registry<T>::Tail = nullptr;\
+ template<typename T> \
+ void Registry<T>::add_node(typename Registry<T>::node *N) { \
+ if (Tail) \
+ Tail->Next = N; \
+ else \
+ Head = N; \
+ Tail = N; \
+ } \
+ template<typename T> typename Registry<T>::iterator Registry<T>::begin() { \
+ return iterator(Head); \
+ } \
+ template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Head; \
+ template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Tail; \
+ template \
+ void Registry<REGISTRY_CLASS::type>::add_node(REGISTRY_CLASS::node*); \
+ template REGISTRY_CLASS::iterator Registry<REGISTRY_CLASS::type>::begin(); \
}
-#define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL) \
- REGISTRY_CLASS::import(DL, #REGISTRY_CLASS)
-#else
-#define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS)
-#define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL)
-#endif
#endif // LLVM_SUPPORT_REGISTRY_H
diff --git a/llvm/lib/CodeGen/GCMetadataPrinter.cpp b/llvm/lib/CodeGen/GCMetadataPrinter.cpp
index bb8cfa1cc80..d183c7f2980 100644
--- a/llvm/lib/CodeGen/GCMetadataPrinter.cpp
+++ b/llvm/lib/CodeGen/GCMetadataPrinter.cpp
@@ -14,6 +14,8 @@
#include "llvm/CodeGen/GCMetadataPrinter.h"
using namespace llvm;
+LLVM_INSTANTIATE_REGISTRY(GCMetadataPrinterRegistry)
+
GCMetadataPrinter::GCMetadataPrinter() {}
GCMetadataPrinter::~GCMetadataPrinter() {}
diff --git a/llvm/lib/CodeGen/GCStrategy.cpp b/llvm/lib/CodeGen/GCStrategy.cpp
index 554d326942e..31ab86fdf27 100644
--- a/llvm/lib/CodeGen/GCStrategy.cpp
+++ b/llvm/lib/CodeGen/GCStrategy.cpp
@@ -16,6 +16,8 @@
using namespace llvm;
+LLVM_INSTANTIATE_REGISTRY(GCRegistry)
+
GCStrategy::GCStrategy()
: UseStatepoints(false), NeededSafePoints(0), CustomReadBarriers(false),
CustomWriteBarriers(false), CustomRoots(false), InitRoots(true),
commit 0cfb8c87dfc0a8366d6db83f93aa50e9514dbf9d
Author: John Brawn <john.brawn@arm.com>
Date: Fri Aug 5 11:01:08 2016 +0000
Reapply r276973 "Adjust Registry interface to not require plugins to export a registry"
This differs from the previous version by being more careful about template
instantiation/specialization in order to prevent errors when building with
clang -Werror. Specifically:
* begin is not defined in the template and is instead instantiated when Head
is. I think the warning when we don't do that is wrong (PR28815) but for now
at least do it this way to avoid the warning.
* Instead of performing template specializations in LLVM_INSTANTIATE_REGISTRY
instead provide a template definition then do explicit instantiation. No
compiler I've tried has problems with doing it the other way, but strictly
speaking it's not permitted by the C++ standard so better safe than sorry.
Original commit message:
Currently the Registry class contains the vestiges of a previous attempt to
allow plugins to be used on Windows without using BUILD_SHARED_LIBS, where a
plugin would have its own copy of a registry and export it to be imported by
the tool that's loading the plugin. This only works if the plugin is entirely
self-contained with the only interface between the plugin and tool being the
registry, and in particular this conflicts with how IR pass plugins work.
This patch changes things so that instead the add_node function of the registry
is exported by the tool and then imported by the plugin, which solves this
problem and also means that instead of every plugin having to export every
registry they use instead LLVM only has to export the add_node functions. This
allows plugins that use a registry to work on Windows if
LLVM_EXPORT_SYMBOLS_FOR_PLUGINS is used.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@277806 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clang/examples/AnnotateFunctions/CMakeLists.txt b/clang/examples/AnnotateFunctions/CMakeLists.txt
index cf564d527d..5684abf238 100644
--- a/clang/examples/AnnotateFunctions/CMakeLists.txt
+++ b/clang/examples/AnnotateFunctions/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_loadable_module(AnnotateFunctions AnnotateFunctions.cpp)
+add_llvm_loadable_module(AnnotateFunctions AnnotateFunctions.cpp PLUGIN_TOOL clang)
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
target_link_libraries(AnnotateFunctions PRIVATE
diff --git a/clang/examples/PrintFunctionNames/CMakeLists.txt b/clang/examples/PrintFunctionNames/CMakeLists.txt
index 5a00d5036f..f5f818866c 100644
--- a/clang/examples/PrintFunctionNames/CMakeLists.txt
+++ b/clang/examples/PrintFunctionNames/CMakeLists.txt
@@ -9,7 +9,7 @@ if( NOT MSVC ) # MSVC mangles symbols differently, and
endif()
endif()
-add_llvm_loadable_module(PrintFunctionNames PrintFunctionNames.cpp)
+add_llvm_loadable_module(PrintFunctionNames PrintFunctionNames.cpp PLUGIN_TOOL clang)
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
target_link_libraries(PrintFunctionNames PRIVATE
diff --git a/clang/include/clang/Frontend/FrontendPluginRegistry.h b/clang/include/clang/Frontend/FrontendPluginRegistry.h
index ecab630c12..9d7ee08d95 100644
--- a/clang/include/clang/Frontend/FrontendPluginRegistry.h
+++ b/clang/include/clang/Frontend/FrontendPluginRegistry.h
@@ -13,9 +13,6 @@
#include "clang/Frontend/FrontendAction.h"
#include "llvm/Support/Registry.h"
-// Instantiated in FrontendAction.cpp.
-extern template class llvm::Registry<clang::PluginASTAction>;
-
namespace clang {
/// The frontend plugin registry.
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index c9b712504e..000df6647f 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -1972,6 +1972,4 @@ typedef llvm::Registry<PragmaHandler> PragmaHandlerRegistry;
} // end namespace clang
-extern template class llvm::Registry<clang::PragmaHandler>;
-
#endif
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index d2c2a80394..2945b8925f 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -33,7 +33,7 @@
#include <system_error>
using namespace clang;
-template class llvm::Registry<clang::PluginASTAction>;
+LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)
namespace {
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 8832c7f80c..f0d6872546 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -54,7 +54,7 @@
#include <utility>
using namespace clang;
-template class llvm::Registry<clang::PragmaHandler>;
+LLVM_INSTANTIATE_REGISTRY(PragmaHandlerRegistry)
//===----------------------------------------------------------------------===//
ExternalPreprocessorSource::~ExternalPreprocessorSource() { }
diff --git a/clang/lib/Tooling/CompilationDatabase.cpp b/clang/lib/Tooling/CompilationDatabase.cpp
index 8fc4a1fe5b..6f95bf01f6 100644
--- a/clang/lib/Tooling/CompilationDatabase.cpp
+++ b/clang/lib/Tooling/CompilationDatabase.cpp
@@ -32,6 +32,8 @@
using namespace clang;
using namespace tooling;
+LLVM_INSTANTIATE_REGISTRY(CompilationDatabasePluginRegistry)
+
CompilationDatabase::~CompilationDatabase() {}
std::unique_ptr<CompilationDatabase>

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

@ -0,0 +1,64 @@
commit 783f98e4a55266c40b6ecee9b41381353f37013b
Author: Tim Shen <timshen91@gmail.com>
Date: Tue Nov 1 00:19:04 2016 +0000
[ReachableCode] Skip over ExprWithCleanups in isConfigurationValue
Summary: Fixes pr29152.
Reviewers: rsmith, pirama, krememek
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D24010
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285657 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clang/include/clang/AST/Stmt.h a/clang/include/clang/AST/Stmt.h
index 9381a44985..e28675d6a8 100644
--- a/clang/include/clang/AST/Stmt.h
+++ a/clang/include/clang/AST/Stmt.h
@@ -387,6 +387,9 @@ public:
/// Skip past any implicit AST nodes which might surround this
/// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
Stmt *IgnoreImplicit();
+ const Stmt *IgnoreImplicit() const {
+ return const_cast<Stmt *>(this)->IgnoreImplicit();
+ }
/// \brief Skip no-op (attributed, compound) container stmts and skip captured
/// stmt at the top, if \a IgnoreCaptured is true.
diff --git a/clang/lib/Analysis/ReachableCode.cpp a/clang/lib/Analysis/ReachableCode.cpp
index 8165b09f40..69d000c03b 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ a/clang/lib/Analysis/ReachableCode.cpp
@@ -164,6 +164,8 @@ static bool isConfigurationValue(const Stmt *S,
if (!S)
return false;
+ S = S->IgnoreImplicit();
+
if (const Expr *Ex = dyn_cast<Expr>(S))
S = Ex->IgnoreCasts();
diff --git a/clang/test/SemaCXX/PR29152.cpp a/clang/test/SemaCXX/PR29152.cpp
new file mode 100644
index 0000000000..63c9c9bed5
--- /dev/null
+++ a/clang/test/SemaCXX/PR29152.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunreachable-code -verify %s
+
+static const bool False = false;
+
+struct A {
+ ~A();
+ operator bool();
+};
+void Bar();
+
+void Foo() {
+ if (False && A()) {
+ Bar(); // expected-no-diagnostics
+ }
+}

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

@ -18,6 +18,7 @@ gyp_vars.update({
'include_pulse_audio': 1 if CONFIG['MOZ_PULSEAUDIO'] else 0,
# basic stuff for everything
'include_internal_video_render': 0,
'clang': 1 if CONFIG['CLANG_CXX'] else 0,
'clang_use_chrome_plugins': 0,
'enable_protobuf': 0,
'include_tests': 0,

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

@ -284,6 +284,31 @@ OriginAttributes::IsFirstPartyEnabled()
return sFirstPartyIsolation;
}
/* static */
bool
OriginAttributes::IsRestrictOpenerAccessForFPI()
{
bool isFirstPartyEnabled = IsFirstPartyEnabled();
// Cache the privacy.firstparty.isolate.restrict_opener_access pref.
static bool sRestrictedOpenerAccess = false;
static bool sCachedRestrictedAccessPref = false;
if (!sCachedRestrictedAccessPref) {
MOZ_ASSERT(NS_IsMainThread());
sCachedRestrictedAccessPref = true;
Preferences::AddBoolVarCache(&sRestrictedOpenerAccess,
"privacy.firstparty.isolate.restrict_opener_access");
}
// We always want to restrict window.opener if first party isolation is
// disabled.
if (!isFirstPartyEnabled) {
return true;
}
return isFirstPartyEnabled && sRestrictedOpenerAccess;
}
/* static */
bool
OriginAttributes::IsPrivateBrowsing(const nsACString& aOrigin)
@ -388,6 +413,24 @@ BasePrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal *aOther,
bool *aResult)
{
NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
if (Kind() == eCodebasePrincipal &&
!dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
OriginAttributesRef(), aOther->OriginAttributesRef())) {
*aResult = false;
return NS_OK;
}
*aResult = SubsumesInternal(aOther, ConsiderDocumentDomain);
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
{

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

@ -103,6 +103,11 @@ public:
// check if "privacy.firstparty.isolate" is enabled.
static bool IsFirstPartyEnabled();
// check if the access of window.opener across different FPDs is restricted.
// We only restrict the access of window.opener when first party isolation
// is enabled and "privacy.firstparty.isolate.restrict_opener_access" is on.
static bool IsRestrictOpenerAccessForFPI();
// returns true if the originAttributes suffix has mPrivateBrowsingId value
// different than 0.
static bool IsPrivateBrowsing(const nsACString& aOrigin);
@ -210,6 +215,7 @@ public:
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
@ -234,8 +240,6 @@ public:
virtual bool AddonHasPermission(const nsAString& aPerm);
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
virtual bool IsCodebasePrincipal() const { return false; };
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }

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

@ -25,7 +25,7 @@ interface nsIDOMDocument;
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[ref] native const_OriginAttributes(const mozilla::OriginAttributes);
[scriptable, builtinclass, uuid(3da7b133-f1a0-4de9-a2bc-5c49014c1077)]
[scriptable, builtinclass, uuid(f75f502d-79fd-48be-a079-e5a7b8f80c8b)]
interface nsIPrincipal : nsISerializable
{
/**
@ -94,6 +94,12 @@ interface nsIPrincipal : nsISerializable
*/
boolean subsumesConsideringDomain(in nsIPrincipal other);
/**
* Same as the subsumesConsideringDomain(), but ignores the first party
* domain in its originAttributes.
*/
boolean subsumesConsideringDomainIgnoringFPD(in nsIPrincipal other);
%{C++
inline bool Subsumes(nsIPrincipal* aOther) {
bool subsumes = false;
@ -104,6 +110,11 @@ interface nsIPrincipal : nsISerializable
bool subsumes = false;
return NS_SUCCEEDED(SubsumesConsideringDomain(aOther, &subsumes)) && subsumes;
}
inline bool SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther) {
bool subsumes = false;
return NS_SUCCEEDED(SubsumesConsideringDomainIgnoringFPD(aOther, &subsumes)) && subsumes;
}
%}
/**
@ -339,15 +350,6 @@ interface nsIPrincipal : nsISerializable
* Returns true iff this is the system principal.
*/
[infallible] readonly attribute boolean isSystemPrincipal;
/**
* Returns true if this principal's origin is recognized as being on the
* whitelist of sites that can use the CSS Unprefixing Service.
*
* (This interface provides a trivial implementation, just returning false;
* subclasses can implement something more complex as-needed.)
*/
[noscript,notxpcom,nostdcall] bool IsOnCSSUnprefixingWhitelist();
};
/**

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

@ -32,7 +32,6 @@
using namespace mozilla;
static bool gIsWhitelistingTestDomains = false;
static bool gCodeBasePrincipalSupport = false;
static bool URIIsImmutable(nsIURI* aURI)
@ -58,10 +57,6 @@ NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
/* static */ void
nsPrincipal::InitializeStatics()
{
Preferences::AddBoolVarCache(
&gIsWhitelistingTestDomains,
"layout.css.unprefixing-service.include-test-domains");
Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
"signed.applets.codebase_principal_support",
false);
@ -464,196 +459,6 @@ nsPrincipal::Write(nsIObjectOutputStream* aStream)
return NS_OK;
}
// Helper-function to indicate whether the CSS Unprefixing Service
// whitelist should include dummy domains that are only intended for
// use in testing. (Controlled by a pref.)
static inline bool
IsWhitelistingTestDomains()
{
return gIsWhitelistingTestDomains;
}
// Checks if the given URI's host is on our "full domain" whitelist
// (i.e. if it's an exact match against a domain that needs unprefixing)
static bool
IsOnFullDomainWhitelist(nsIURI* aURI)
{
nsAutoCString hostStr;
nsresult rv = aURI->GetHost(hostStr);
NS_ENSURE_SUCCESS(rv, false);
// NOTE: This static whitelist is expected to be short. If that changes,
// we should consider a different representation; e.g. hash-set, prefix tree.
static const nsLiteralCString sFullDomainsOnWhitelist[] = {
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test1.example.org"),
NS_LITERAL_CSTRING("map.baidu.com"),
NS_LITERAL_CSTRING("3g.163.com"),
NS_LITERAL_CSTRING("3glogo.gtimg.com"), // for 3g.163.com
NS_LITERAL_CSTRING("info.3g.qq.com"), // for 3g.qq.com
NS_LITERAL_CSTRING("3gimg.qq.com"), // for 3g.qq.com
NS_LITERAL_CSTRING("img.m.baidu.com"), // for [shucheng|ks].baidu.com
NS_LITERAL_CSTRING("m.mogujie.com"),
NS_LITERAL_CSTRING("touch.qunar.com"),
NS_LITERAL_CSTRING("mjs.sinaimg.cn"), // for sina.cn
NS_LITERAL_CSTRING("static.qiyi.com"), // for m.iqiyi.com
NS_LITERAL_CSTRING("cdn.kuaidi100.com"), // for m.kuaidi100.com
NS_LITERAL_CSTRING("m.pc6.com"),
NS_LITERAL_CSTRING("m.haosou.com"),
NS_LITERAL_CSTRING("m.mi.com"),
NS_LITERAL_CSTRING("wappass.baidu.com"),
NS_LITERAL_CSTRING("m.video.baidu.com"),
NS_LITERAL_CSTRING("m.video.baidu.com"),
NS_LITERAL_CSTRING("imgcache.gtimg.cn"), // for m.v.qq.com
NS_LITERAL_CSTRING("s.tabelog.jp"),
NS_LITERAL_CSTRING("s.yimg.jp"), // for s.tabelog.jp
NS_LITERAL_CSTRING("i.yimg.jp"), // for *.yahoo.co.jp
NS_LITERAL_CSTRING("ai.yimg.jp"), // for *.yahoo.co.jp
NS_LITERAL_CSTRING("m.finance.yahoo.co.jp"),
NS_LITERAL_CSTRING("daily.c.yimg.jp"), // for sp.daily.co.jp
NS_LITERAL_CSTRING("stat100.ameba.jp"), // for ameblo.jp
NS_LITERAL_CSTRING("user.ameba.jp"), // for ameblo.jp
NS_LITERAL_CSTRING("www.goo.ne.jp"),
NS_LITERAL_CSTRING("x.gnst.jp"), // for mobile.gnavi.co.jp
NS_LITERAL_CSTRING("c.x.gnst.jp"), // for mobile.gnavi.co.jp
NS_LITERAL_CSTRING("www.smbc-card.com"),
NS_LITERAL_CSTRING("static.card.jp.rakuten-static.com"), // for rakuten-card.co.jp
NS_LITERAL_CSTRING("img.travel.rakuten.co.jp"), // for travel.rakuten.co.jp
NS_LITERAL_CSTRING("img.mixi.net"), // for mixi.jp
NS_LITERAL_CSTRING("girlschannel.net"),
NS_LITERAL_CSTRING("www.fancl.co.jp"),
NS_LITERAL_CSTRING("s.cosme.net"),
NS_LITERAL_CSTRING("www.sapporobeer.jp"),
NS_LITERAL_CSTRING("www.mapion.co.jp"),
NS_LITERAL_CSTRING("touch.navitime.co.jp"),
NS_LITERAL_CSTRING("sp.mbga.jp"),
NS_LITERAL_CSTRING("ava-a.sp.mbga.jp"), // for sp.mbga.jp
NS_LITERAL_CSTRING("www.ntv.co.jp"),
NS_LITERAL_CSTRING("mobile.suntory.co.jp"), // for suntory.jp
NS_LITERAL_CSTRING("www.aeonsquare.net"),
NS_LITERAL_CSTRING("mw.nikkei.com"),
NS_LITERAL_CSTRING("www.nhk.or.jp"),
NS_LITERAL_CSTRING("www.tokyo-sports.co.jp"),
NS_LITERAL_CSTRING("www.bellemaison.jp"),
NS_LITERAL_CSTRING("www.kuronekoyamato.co.jp"),
NS_LITERAL_CSTRING("formassist.jp"), // for orico.jp
NS_LITERAL_CSTRING("sp.m.reuters.co.jp"),
NS_LITERAL_CSTRING("www.atre.co.jp"),
NS_LITERAL_CSTRING("www.jtb.co.jp"),
NS_LITERAL_CSTRING("www.sharp.co.jp"),
NS_LITERAL_CSTRING("www.biccamera.com"),
NS_LITERAL_CSTRING("weathernews.jp"),
NS_LITERAL_CSTRING("cache.ymail.jp"), // for www.yamada-denkiweb.com
};
static const size_t sNumFullDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sFullDomainsOnWhitelist);
// Skip 0th (dummy) entry in whitelist, unless a pref is enabled.
const size_t firstWhitelistIdx = IsWhitelistingTestDomains() ? 0 : 1;
for (size_t i = firstWhitelistIdx; i < sNumFullDomainsOnWhitelist; ++i) {
if (hostStr == sFullDomainsOnWhitelist[i]) {
return true;
}
}
return false;
}
// Checks if the given URI's host is on our "base domain" whitelist
// (i.e. if it's a subdomain of some host that we've whitelisted as needing
// unprefixing for all its subdomains)
static bool
IsOnBaseDomainWhitelist(nsIURI* aURI)
{
static const nsLiteralCString sBaseDomainsOnWhitelist[] = {
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test2.example.org"),
NS_LITERAL_CSTRING("tbcdn.cn"), // for m.taobao.com
NS_LITERAL_CSTRING("alicdn.com"), // for m.taobao.com
NS_LITERAL_CSTRING("dpfile.com"), // for m.dianping.com
NS_LITERAL_CSTRING("hao123img.com"), // for hao123.com
NS_LITERAL_CSTRING("tabelog.k-img.com"), // for s.tabelog.com
NS_LITERAL_CSTRING("tsite.jp"), // for *.tsite.jp
};
static const size_t sNumBaseDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sBaseDomainsOnWhitelist);
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
if (tldService) {
// Skip 0th test-entry in whitelist, unless the testing pref is enabled.
const size_t firstWhitelistIdx = IsWhitelistingTestDomains() ? 0 : 1;
// Right now, the test base-domain "test2.example.org" is the only entry in
// its whitelist with a nonzero "depth". So we'll only bother going beyond
// 0 depth (to 1) if that entry is enabled. (No point in slowing down the
// normal codepath, for the benefit of a disabled test domain.) If we add a
// "real" base-domain with a depth of >= 1 to our whitelist, we can get rid
// of this conditional & just make this a static variable.
const uint32_t maxSubdomainDepth = IsWhitelistingTestDomains() ? 1 : 0;
for (uint32_t subdomainDepth = 0;
subdomainDepth <= maxSubdomainDepth; ++subdomainDepth) {
// Get the base domain (to depth |subdomainDepth|) from passed-in URI:
nsAutoCString baseDomainStr;
nsresult rv = tldService->GetBaseDomain(aURI, subdomainDepth,
baseDomainStr);
if (NS_FAILED(rv)) {
// aURI doesn't have |subdomainDepth| levels of subdomains. If we got
// here without a match yet, then aURI is not on our whitelist.
return false;
}
// Compare the base domain against each entry in our whitelist:
for (size_t i = firstWhitelistIdx; i < sNumBaseDomainsOnWhitelist; ++i) {
if (baseDomainStr == sBaseDomainsOnWhitelist[i]) {
return true;
}
}
}
}
return false;
}
// The actual (non-cached) implementation of IsOnCSSUnprefixingWhitelist():
static bool
IsOnCSSUnprefixingWhitelistImpl(nsIURI* aURI)
{
// Check scheme, so we can drop any non-HTTP/HTTPS URIs right away
nsAutoCString schemeStr;
nsresult rv = aURI->GetScheme(schemeStr);
NS_ENSURE_SUCCESS(rv, false);
// Only proceed if scheme is "http" or "https"
if (!(StringBeginsWith(schemeStr, NS_LITERAL_CSTRING("http")) &&
(schemeStr.Length() == 4 ||
(schemeStr.Length() == 5 && schemeStr[4] == 's')))) {
return false;
}
return (IsOnFullDomainWhitelist(aURI) ||
IsOnBaseDomainWhitelist(aURI));
}
bool
nsPrincipal::IsOnCSSUnprefixingWhitelist()
{
if (mIsOnCSSUnprefixingWhitelist.isNothing()) {
// Value not cached -- perform our lazy whitelist-check.
// (NOTE: If our URI is mutable, we just assume it's not on the whitelist,
// since our caching strategy won't work. This isn't expected to be common.)
mIsOnCSSUnprefixingWhitelist.emplace(
mCodebaseImmutable &&
IsOnCSSUnprefixingWhitelistImpl(mCodebase));
}
return *mIsOnCSSUnprefixingWhitelist;
}
/************************************************************************************************************************/
NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
@ -818,15 +623,6 @@ nsExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
return false;
}
bool
nsExpandedPrincipal::IsOnCSSUnprefixingWhitelist()
{
// CSS Unprefixing Whitelist is a per-origin thing; doesn't really make sense
// for an expanded principal. (And probably shouldn't be needed.)
return false;
}
nsresult
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
{

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

@ -25,7 +25,6 @@ public:
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
bool IsCodebasePrincipal() const override { return true; }
nsresult GetOriginInternal(nsACString& aOrigin) override;
@ -51,7 +50,6 @@ public:
bool mCodebaseImmutable;
bool mDomainImmutable;
bool mInitialized;
mozilla::Maybe<bool> mIsOnCSSUnprefixingWhitelist; // Lazily-computed
protected:
virtual ~nsPrincipal();
@ -77,7 +75,6 @@ public:
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool AddonHasPermission(const nsAString& aPerm) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
virtual nsresult GetScriptLocation(nsACString &aStr) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;

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

@ -212,6 +212,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_rules_selector-highlighter_02.js]
[browser_rules_selector-highlighter_03.js]
[browser_rules_selector-highlighter_04.js]
[browser_rules_selector-highlighter_05.js]
[browser_rules_selector_highlight.js]
[browser_rules_strict-search-filter-computed-list_01.js]
[browser_rules_strict-search-filter_01.js]

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

@ -22,6 +22,8 @@ add_task(function* () {
let testActor = yield getTestActorWithoutToolbox(tab);
let inspector = yield clickOnInspectMenuItem(testActor, "span");
yield getRuleViewSelectorHighlighterIcon(inspector.ruleview.view,
"element", 3);
checkRuleViewContent(inspector.ruleview.view);
});
@ -57,4 +59,3 @@ function checkRuleViewContent({styleDocument}) {
is(propertyValues.length, 1, "There's only one property value, as expected");
}
}

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

@ -33,7 +33,7 @@ function* testSelectorHighlight(view, name) {
info("Test creating selector highlighter");
info("Clicking on a selector icon");
let icon = getRuleViewSelectorHighlighterIcon(view, name);
let icon = yield getRuleViewSelectorHighlighterIcon(view, name);
let onToggled = view.once("ruleview-selectorhighlighter-toggled");
EventUtils.synthesizeMouseAtCenter(icon, {}, view.styleWindow);

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

@ -18,6 +18,7 @@ add_task(function* () {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
yield selectNode("#test1", inspector);
yield getRuleViewSelectorHighlighterIcon(view, "element", 1);
yield elementStyleInherit(inspector, view);
});

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

@ -20,6 +20,7 @@ add_task(function* () {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
yield selectNode("a", inspector);
yield getRuleViewSelectorHighlighterIcon(view, "element", 2);
yield elementStyleInherit(inspector, view);
});

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

@ -23,7 +23,7 @@ add_task(function* () {
let highlighters = view.highlighters;
info("Clicking on a selector icon");
let icon = getRuleViewSelectorHighlighterIcon(view, "body, p, td");
let icon = yield getRuleViewSelectorHighlighterIcon(view, "body, p, td");
let onToggled = view.once("ruleview-selectorhighlighter-toggled");
EventUtils.synthesizeMouseAtCenter(icon, {}, view.styleWindow);

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

@ -24,7 +24,7 @@ add_task(function* () {
"No selectorhighlighter exist in the rule-view");
info("Clicking on a selector icon");
let icon = getRuleViewSelectorHighlighterIcon(view, "body, p, td");
let icon = yield getRuleViewSelectorHighlighterIcon(view, "body, p, td");
let onToggled = view.once("ruleview-selectorhighlighter-toggled");
EventUtils.synthesizeMouseAtCenter(icon, {}, view.styleWindow);

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

@ -46,7 +46,7 @@ add_task(function* () {
// Inject the mock highlighter in the rule-view
view.selectorHighlighter = HighlighterFront;
let icon = getRuleViewSelectorHighlighterIcon(view, "body");
let icon = yield getRuleViewSelectorHighlighterIcon(view, "body");
info("Checking that the HighlighterFront's show/hide methods are called");
@ -60,7 +60,7 @@ add_task(function* () {
info("Checking that the right NodeFront reference and options are passed");
yield selectNode("p", inspector);
icon = getRuleViewSelectorHighlighterIcon(view, "p");
icon = yield getRuleViewSelectorHighlighterIcon(view, "p");
yield clickSelectorIcon(icon, view);
is(HighlighterFront.nodeFront.tagName, "P",
@ -69,7 +69,7 @@ add_task(function* () {
"The right selector option is passed to the highlighter (1)");
yield selectNode("body", inspector);
icon = getRuleViewSelectorHighlighterIcon(view, "body");
icon = yield getRuleViewSelectorHighlighterIcon(view, "body");
yield clickSelectorIcon(icon, view);
is(HighlighterFront.nodeFront.tagName, "BODY",
"The right NodeFront is passed to the highlighter (2)");

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

@ -39,7 +39,7 @@ add_task(function* () {
info("Select .node-1 and click on the .node-1 selector icon");
yield selectNode(".node-1", inspector);
let icon = getRuleViewSelectorHighlighterIcon(view, ".node-1");
let icon = yield getRuleViewSelectorHighlighterIcon(view, ".node-1");
yield clickSelectorIcon(icon, view);
ok(HighlighterFront.isShown, "The highlighter is shown");
@ -48,12 +48,12 @@ add_task(function* () {
ok(!HighlighterFront.isShown, "The highlighter is now hidden");
info("With .node-1 still selected, click on the div selector icon");
icon = getRuleViewSelectorHighlighterIcon(view, "div");
icon = yield getRuleViewSelectorHighlighterIcon(view, "div");
yield clickSelectorIcon(icon, view);
ok(HighlighterFront.isShown, "The highlighter is shown again");
info("With .node-1 still selected, click again on the .node-1 selector icon");
icon = getRuleViewSelectorHighlighterIcon(view, ".node-1");
icon = yield getRuleViewSelectorHighlighterIcon(view, ".node-1");
yield clickSelectorIcon(icon, view);
ok(HighlighterFront.isShown,
"The highlighter is shown again since the clicked selector was different");
@ -64,14 +64,14 @@ add_task(function* () {
"The highlighter is still shown after selection");
info("With .node-2 selected, click on the div selector icon");
icon = getRuleViewSelectorHighlighterIcon(view, "div");
icon = yield getRuleViewSelectorHighlighterIcon(view, "div");
yield clickSelectorIcon(icon, view);
ok(HighlighterFront.isShown,
"The highlighter is shown still since the selected was different");
info("Switching back to .node-1 and clicking on the div selector");
yield selectNode(".node-1", inspector);
icon = getRuleViewSelectorHighlighterIcon(view, "div");
icon = yield getRuleViewSelectorHighlighterIcon(view, "div");
yield clickSelectorIcon(icon, view);
ok(!HighlighterFront.isShown,
"The highlighter is hidden now that the same selector was clicked");

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

@ -39,7 +39,7 @@ add_task(function* () {
info("Checking that the right NodeFront reference and options are passed");
yield selectNode("p", inspector);
let icon = getRuleViewSelectorHighlighterIcon(view, "element");
let icon = yield getRuleViewSelectorHighlighterIcon(view, "element");
yield clickSelectorIcon(icon, view);
is(HighlighterFront.nodeFront.tagName, "P",

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

@ -0,0 +1,64 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the selector highlighter is correctly shown when clicking on a
// inherited element
// Note that in this test, we mock the highlighter front, merely testing the
// behavior of the style-inspector UI for now
const TEST_URI = `
<div style="cursor:pointer">
A
<div style="cursor:pointer">
B<a>Cursor</a>
</div>
</div>
`;
add_task(function* () {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
// Mock the highlighter front to get the reference of the NodeFront
let HighlighterFront = {
isShown: false,
nodeFront: null,
options: null,
show: function (nodeFront, options) {
this.nodeFront = nodeFront;
this.options = options;
this.isShown = true;
},
hide: function () {
this.nodeFront = null;
this.options = null;
this.isShown = false;
}
};
// Inject the mock highlighter in the rule-view
view.selectorHighlighter = HighlighterFront;
info("Checking that the right NodeFront reference and options are passed");
yield selectNode("a", inspector);
let icon = yield getRuleViewSelectorHighlighterIcon(view, "element");
yield clickSelectorIcon(icon, view);
is(HighlighterFront.options.selector,
"body > div:nth-child(1) > div:nth-child(1) > a:nth-child(1)",
"The right selector option is passed to the highlighter (1)");
icon = yield getRuleViewSelectorHighlighterIcon(view, "element", 1);
yield clickSelectorIcon(icon, view);
is(HighlighterFront.options.selector,
"body > div:nth-child(1) > div:nth-child(1)",
"The right selector option is passed to the highlighter (1)");
icon = yield getRuleViewSelectorHighlighterIcon(view, "element", 2);
yield clickSelectorIcon(icon, view);
is(HighlighterFront.options.selector, "body > div:nth-child(1)",
"The right selector option is passed to the highlighter (1)");
});

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

@ -44,76 +44,6 @@ addTab = function (url) {
});
};
/**
* Wait for a content -> chrome message on the message manager (the window
* messagemanager is used).
*
* @param {String} name
* The message name
* @return {Promise} A promise that resolves to the response data when the
* message has been received
*/
function waitForContentMessage(name) {
info("Expecting message " + name + " from content");
let mm = gBrowser.selectedBrowser.messageManager;
let def = defer();
mm.addMessageListener(name, function onMessage(msg) {
mm.removeMessageListener(name, onMessage);
def.resolve(msg.data);
});
return def.promise;
}
/**
* Send an async message to the frame script (chrome -> content) and wait for a
* response message with the same name (content -> chrome).
*
* @param {String} name
* The message name. Should be one of the messages defined
* in doc_frame_script.js
* @param {Object} data
* Optional data to send along
* @param {Object} objects
* Optional CPOW objects to send along
* @param {Boolean} expectResponse
* If set to false, don't wait for a response with the same name
* from the content script. Defaults to true.
* @return {Promise} Resolves to the response data if a response is expected,
* immediately resolves otherwise
*/
function executeInContent(name, data = {}, objects = {},
expectResponse = true) {
info("Sending message " + name + " to content");
let mm = gBrowser.selectedBrowser.messageManager;
mm.sendAsyncMessage(name, data, objects);
if (expectResponse) {
return waitForContentMessage(name);
}
return promise.resolve();
}
/**
* Send an async message to the frame script and get back the requested
* computed style property.
*
* @param {String} selector
* The selector used to obtain the element.
* @param {String} pseudo
* pseudo id to query, or null.
* @param {String} name
* name of the property.
*/
function* getComputedStyleProperty(selector, pseudo, propName) {
return yield executeInContent("Test:GetComputedStylePropertyValue",
{selector,
pseudo,
name: propName});
}
/**
* Get an element's inline style property value.
* @param {TestActor} testActor
@ -129,49 +59,6 @@ function getStyle(testActor, selector, propName) {
`);
}
/**
* Send an async message to the frame script and wait until the requested
* computed style property has the expected value.
*
* @param {String} selector
* The selector used to obtain the element.
* @param {String} pseudo
* pseudo id to query, or null.
* @param {String} prop
* name of the property.
* @param {String} expected
* expected value of property
* @param {String} name
* the name used in test message
*/
function* waitForComputedStyleProperty(selector, pseudo, name, expected) {
return yield executeInContent("Test:WaitForComputedStylePropertyValue",
{selector,
pseudo,
expected,
name});
}
/**
* Given an inplace editable element, click to switch it to edit mode, wait for
* focus
*
* @return a promise that resolves to the inplace-editor element when ready
*/
var focusEditableField = Task.async(function* (ruleView, editable, xOffset = 1,
yOffset = 1, options = {}) {
let onFocus = once(editable.parentNode, "focus", true);
info("Clicking on editable field to turn to edit mode");
EventUtils.synthesizeMouse(editable, xOffset, yOffset, options,
editable.ownerDocument.defaultView);
yield onFocus;
info("Editable field gained focus, returning the input field now");
let onEdit = inplaceEditor(editable.ownerDocument.activeElement);
return onEdit;
});
/**
* When a tooltip is closed, this ends up "commiting" the value changed within
* the tooltip (e.g. the color in case of a colorpicker) which, in turn, ends up
@ -219,109 +106,6 @@ var waitForSuccess = Task.async(function* (validatorFn, desc = "untitled") {
}
});
/**
* Get the DOMNode for a css rule in the rule-view that corresponds to the given
* selector
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view for which the rule
* object is wanted
* @return {DOMNode}
*/
function getRuleViewRule(view, selectorText) {
let rule;
for (let r of view.styleDocument.querySelectorAll(".ruleview-rule")) {
let selector = r.querySelector(".ruleview-selectorcontainer, " +
".ruleview-selector-matched");
if (selector && selector.textContent === selectorText) {
rule = r;
break;
}
}
return rule;
}
/**
* Get references to the name and value span nodes corresponding to a given
* selector and property name in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for the property in
* @param {String} propertyName
* The name of the property
* @return {Object} An object like {nameSpan: DOMNode, valueSpan: DOMNode}
*/
function getRuleViewProperty(view, selectorText, propertyName) {
let prop;
let rule = getRuleViewRule(view, selectorText);
if (rule) {
// Look for the propertyName in that rule element
for (let p of rule.querySelectorAll(".ruleview-property")) {
let nameSpan = p.querySelector(".ruleview-propertyname");
let valueSpan = p.querySelector(".ruleview-propertyvalue");
if (nameSpan.textContent === propertyName) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
break;
}
}
}
return prop;
}
/**
* Get the text value of the property corresponding to a given selector and name
* in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for the property in
* @param {String} propertyName
* The name of the property
* @return {String} The property value
*/
function getRuleViewPropertyValue(view, selectorText, propertyName) {
return getRuleViewProperty(view, selectorText, propertyName)
.valueSpan.textContent;
}
/**
* Get a reference to the selector DOM element corresponding to a given selector
* in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for
* @return {DOMNode} The selector DOM element
*/
function getRuleViewSelector(view, selectorText) {
let rule = getRuleViewRule(view, selectorText);
return rule.querySelector(".ruleview-selector, .ruleview-selector-matched");
}
/**
* Get a reference to the selectorhighlighter icon DOM element corresponding to
* a given selector in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for
* @return {DOMNode} The selectorhighlighter icon DOM element
*/
function getRuleViewSelectorHighlighterIcon(view, selectorText) {
let rule = getRuleViewRule(view, selectorText);
return rule.querySelector(".ruleview-selectorhighlighter");
}
/**
* Simulate a color change in a given color picker tooltip, and optionally wait
* for a given element in the page to have its style changed as a result.
@ -452,34 +236,6 @@ var openCubicBezierAndChangeCoords = Task.async(function* (view, ruleIndex,
return {propEditor, swatch, bezierTooltip};
});
/**
* Get a rule-link from the rule-view given its index
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {Number} index
* The index of the link to get
* @return {DOMNode} The link if any at this index
*/
function getRuleViewLinkByIndex(view, index) {
let links = view.styleDocument.querySelectorAll(".ruleview-rule-source");
return links[index];
}
/**
* Get rule-link text from the rule-view given its index
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {Number} index
* The index of the link to get
* @return {String} The string at this index
*/
function getRuleViewLinkTextByIndex(view, index) {
let link = getRuleViewLinkByIndex(view, index);
return link.querySelector(".ruleview-rule-source-label").textContent;
}
/**
* Simulate adding a new property in an existing rule in the rule-view.
*
@ -625,74 +381,6 @@ var togglePropStatus = Task.async(function* (view, textProp) {
yield onRuleViewRefreshed;
});
/**
* Click on a rule-view's close brace to focus a new property name editor
*
* @param {RuleEditor} ruleEditor
* An instance of RuleEditor that will receive the new property
* @return a promise that resolves to the newly created editor when ready and
* focused
*/
var focusNewRuleViewProperty = Task.async(function* (ruleEditor) {
info("Clicking on a close ruleEditor brace to start editing a new property");
// Use bottom alignment to avoid scrolling out of the parent element area.
ruleEditor.closeBrace.scrollIntoView(false);
let editor = yield focusEditableField(ruleEditor.ruleView,
ruleEditor.closeBrace);
is(inplaceEditor(ruleEditor.newPropSpan), editor,
"Focused editor is the new property editor.");
return editor;
});
/**
* Create a new property name in the rule-view, focusing a new property editor
* by clicking on the close brace, and then entering the given text.
* Keep in mind that the rule-view knows how to handle strings with multiple
* properties, so the input text may be like: "p1:v1;p2:v2;p3:v3".
*
* @param {RuleEditor} ruleEditor
* The instance of RuleEditor that will receive the new property(ies)
* @param {String} inputValue
* The text to be entered in the new property name field
* @return a promise that resolves when the new property name has been entered
* and once the value field is focused
*/
var createNewRuleViewProperty = Task.async(function* (ruleEditor, inputValue) {
info("Creating a new property editor");
let editor = yield focusNewRuleViewProperty(ruleEditor);
info("Entering the value " + inputValue);
editor.input.value = inputValue;
info("Submitting the new value and waiting for value field focus");
let onFocus = once(ruleEditor.element, "focus", true);
EventUtils.synthesizeKey("VK_RETURN", {},
ruleEditor.element.ownerDocument.defaultView);
yield onFocus;
});
/**
* Set the search value for the rule-view filter styles search box.
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} searchValue
* The filter search value
* @return a promise that resolves when the rule-view is filtered for the
* search term
*/
var setSearchFilter = Task.async(function* (view, searchValue) {
info("Setting filter text to \"" + searchValue + "\"");
let win = view.styleWindow;
let searchField = view.searchField;
searchField.focus();
synthesizeKeys(searchValue, win);
yield view.inspector.once("ruleview-filtered");
});
/**
* Reload the current page and wait for the inspector to be initialized after
* the navigation
@ -778,26 +466,6 @@ function* sendKeysAndWaitForFocus(view, element, keys) {
yield onFocus;
}
/**
* Open the style editor context menu and return all of it's items in a flat array
* @param {CssRuleView} view
* The instance of the rule-view panel
* @return An array of MenuItems
*/
function openStyleContextMenuAndGetAllItems(view, target) {
let menu = view._contextmenu._openMenu({target: target});
// Flatten all menu items into a single array to make searching through it easier
let allItems = [].concat.apply([], menu.items.map(function addItem(item) {
if (item.submenu) {
return addItem(item.submenu.items);
}
return item;
}));
return allItems;
}
/**
* Wait for a markupmutation event on the inspector that is for a style modification.
* @param {InspectorPanel} inspector

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

@ -149,19 +149,34 @@ RuleEditor.prototype = {
}
if (this.rule.domRule.type !== CSSRule.KEYFRAME_RULE) {
let selector = this.rule.domRule.selectors
? this.rule.domRule.selectors.join(", ")
: this.ruleView.inspector.selectionCssSelector;
Task.spawn(function* () {
let selector;
let selectorHighlighter = createChild(header, "span", {
class: "ruleview-selectorhighlighter" +
(this.ruleView.highlighters.selectorHighlighterShown === selector ?
" highlighted" : ""),
title: l10n("rule.selectorHighlighter.tooltip")
});
selectorHighlighter.addEventListener("click", () => {
this.ruleView.toggleSelectorHighlighter(selectorHighlighter, selector);
});
if (this.rule.domRule.selectors) {
// This is a "normal" rule with a selector.
selector = this.rule.domRule.selectors.join(", ");
} else if (this.rule.inherited) {
// This is an inline style from an inherited rule. Need to resolve the unique
// selector from the node which rule this is inherited from.
selector = yield this.rule.inherited.getUniqueSelector();
} else {
// This is an inline style from the current node.
selector = this.ruleView.inspector.selectionCssSelector;
}
let selectorHighlighter = createChild(header, "span", {
class: "ruleview-selectorhighlighter" +
(this.ruleView.highlighters.selectorHighlighterShown === selector ?
" highlighted" : ""),
title: l10n("rule.selectorHighlighter.tooltip")
});
selectorHighlighter.addEventListener("click", () => {
this.ruleView.toggleSelectorHighlighter(selectorHighlighter, selector);
});
this.uniqueSelector = selector;
this.emit("selector-icon-created");
}.bind(this));
}
this.openBrace = createChild(header, "span", {

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

@ -88,123 +88,6 @@ addTab = function (url) {
});
};
/**
* Wait for a content -> chrome message on the message manager (the window
* messagemanager is used).
*
* @param {String} name
* The message name
* @return {Promise} A promise that resolves to the response data when the
* message has been received
*/
function waitForContentMessage(name) {
info("Expecting message " + name + " from content");
let mm = gBrowser.selectedBrowser.messageManager;
let def = defer();
mm.addMessageListener(name, function onMessage(msg) {
mm.removeMessageListener(name, onMessage);
def.resolve(msg.data);
});
return def.promise;
}
/**
* Send an async message to the frame script (chrome -> content) and wait for a
* response message with the same name (content -> chrome).
*
* @param {String} name
* The message name. Should be one of the messages defined
* in doc_frame_script.js
* @param {Object} data
* Optional data to send along
* @param {Object} objects
* Optional CPOW objects to send along
* @param {Boolean} expectResponse
* If set to false, don't wait for a response with the same name
* from the content script. Defaults to true.
* @return {Promise} Resolves to the response data if a response is expected,
* immediately resolves otherwise
*/
function executeInContent(name, data = {}, objects = {},
expectResponse = true) {
info("Sending message " + name + " to content");
let mm = gBrowser.selectedBrowser.messageManager;
mm.sendAsyncMessage(name, data, objects);
if (expectResponse) {
return waitForContentMessage(name);
}
return promise.resolve();
}
/**
* Send an async message to the frame script and get back the requested
* computed style property.
*
* @param {String} selector
* The selector used to obtain the element.
* @param {String} pseudo
* pseudo id to query, or null.
* @param {String} name
* name of the property.
*/
function* getComputedStyleProperty(selector, pseudo, propName) {
let data = {
selector,
pseudo,
name: propName
};
return yield executeInContent("Test:GetComputedStylePropertyValue", data);
}
/**
* Send an async message to the frame script and wait until the requested
* computed style property has the expected value.
*
* @param {String} selector
* The selector used to obtain the element.
* @param {String} pseudo
* pseudo id to query, or null.
* @param {String} prop
* name of the property.
* @param {String} expected
* expected value of property
* @param {String} name
* the name used in test message
*/
function* waitForComputedStyleProperty(selector, pseudo, name, expected) {
let data = {
selector,
pseudo,
expected,
name
};
return yield executeInContent("Test:WaitForComputedStylePropertyValue", data);
}
/**
* Given an inplace editable element, click to switch it to edit mode, wait for
* focus
*
* @return a promise that resolves to the inplace-editor element when ready
*/
var focusEditableField = Task.async(function* (ruleView, editable, xOffset = 1,
yOffset = 1, options = {}) {
let onFocus = once(editable.parentNode, "focus", true);
info("Clicking on editable field to turn to edit mode");
EventUtils.synthesizeMouse(editable, xOffset, yOffset, options,
editable.ownerDocument.defaultView);
yield onFocus;
info("Editable field gained focus, returning the input field now");
let onEdit = inplaceEditor(editable.ownerDocument.activeElement);
return onEdit;
});
/**
* Polls a given function waiting for it to return true.
*
@ -258,109 +141,6 @@ var getFontFamilyDataURL = Task.async(function* (font, nodeFront) {
* This object contains functions to get rules, get properties, ...
*/
/**
* Get the DOMNode for a css rule in the rule-view that corresponds to the given
* selector
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view for which the rule
* object is wanted
* @return {DOMNode}
*/
function getRuleViewRule(view, selectorText) {
let rule;
for (let r of view.styleDocument.querySelectorAll(".ruleview-rule")) {
let selector = r.querySelector(".ruleview-selectorcontainer, " +
".ruleview-selector-matched");
if (selector && selector.textContent === selectorText) {
rule = r;
break;
}
}
return rule;
}
/**
* Get references to the name and value span nodes corresponding to a given
* selector and property name in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for the property in
* @param {String} propertyName
* The name of the property
* @return {Object} An object like {nameSpan: DOMNode, valueSpan: DOMNode}
*/
function getRuleViewProperty(view, selectorText, propertyName) {
let prop;
let rule = getRuleViewRule(view, selectorText);
if (rule) {
// Look for the propertyName in that rule element
for (let p of rule.querySelectorAll(".ruleview-property")) {
let nameSpan = p.querySelector(".ruleview-propertyname");
let valueSpan = p.querySelector(".ruleview-propertyvalue");
if (nameSpan.textContent === propertyName) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
break;
}
}
}
return prop;
}
/**
* Get the text value of the property corresponding to a given selector and name
* in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for the property in
* @param {String} propertyName
* The name of the property
* @return {String} The property value
*/
function getRuleViewPropertyValue(view, selectorText, propertyName) {
return getRuleViewProperty(view, selectorText, propertyName)
.valueSpan.textContent;
}
/**
* Get a reference to the selector DOM element corresponding to a given selector
* in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for
* @return {DOMNode} The selector DOM element
*/
function getRuleViewSelector(view, selectorText) {
let rule = getRuleViewRule(view, selectorText);
return rule.querySelector(".ruleview-selector, .ruleview-selector-matched");
}
/**
* Get a reference to the selectorhighlighter icon DOM element corresponding to
* a given selector in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for
* @return {DOMNode} The selectorhighlighter icon DOM element
*/
function getRuleViewSelectorHighlighterIcon(view, selectorText) {
let rule = getRuleViewRule(view, selectorText);
return rule.querySelector(".ruleview-selectorhighlighter");
}
/**
* Simulate a color change in a given color picker tooltip, and optionally wait
* for a given element in the page to have its style changed as a result
@ -400,100 +180,6 @@ var simulateColorPickerChange = Task.async(function* (ruleView, colorPicker,
}
});
/**
* Get a rule-link from the rule-view given its index
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {Number} index
* The index of the link to get
* @return {DOMNode} The link if any at this index
*/
function getRuleViewLinkByIndex(view, index) {
let links = view.styleDocument.querySelectorAll(".ruleview-rule-source");
return links[index];
}
/**
* Get rule-link text from the rule-view given its index
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {Number} index
* The index of the link to get
* @return {String} The string at this index
*/
function getRuleViewLinkTextByIndex(view, index) {
let link = getRuleViewLinkByIndex(view, index);
return link.querySelector(".ruleview-rule-source-label").textContent;
}
/**
* Click on a rule-view's close brace to focus a new property name editor
*
* @param {RuleEditor} ruleEditor
* An instance of RuleEditor that will receive the new property
* @return a promise that resolves to the newly created editor when ready and
* focused
*/
var focusNewRuleViewProperty = Task.async(function* (ruleEditor) {
info("Clicking on a close ruleEditor brace to start editing a new property");
ruleEditor.closeBrace.scrollIntoView();
let editor = yield focusEditableField(ruleEditor.ruleView,
ruleEditor.closeBrace);
is(inplaceEditor(ruleEditor.newPropSpan), editor,
"Focused editor is the new property editor.");
return editor;
});
/**
* Create a new property name in the rule-view, focusing a new property editor
* by clicking on the close brace, and then entering the given text.
* Keep in mind that the rule-view knows how to handle strings with multiple
* properties, so the input text may be like: "p1:v1;p2:v2;p3:v3".
*
* @param {RuleEditor} ruleEditor
* The instance of RuleEditor that will receive the new property(ies)
* @param {String} inputValue
* The text to be entered in the new property name field
* @return a promise that resolves when the new property name has been entered
* and once the value field is focused
*/
var createNewRuleViewProperty = Task.async(function* (ruleEditor, inputValue) {
info("Creating a new property editor");
let editor = yield focusNewRuleViewProperty(ruleEditor);
info("Entering the value " + inputValue);
editor.input.value = inputValue;
info("Submitting the new value and waiting for value field focus");
let onFocus = once(ruleEditor.element, "focus", true);
EventUtils.synthesizeKey("VK_RETURN", {},
ruleEditor.element.ownerDocument.defaultView);
yield onFocus;
});
/**
* Set the search value for the rule-view filter styles search box.
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} searchValue
* The filter search value
* @return a promise that resolves when the rule-view is filtered for the
* search term
*/
var setSearchFilter = Task.async(function* (view, searchValue) {
info("Setting filter text to \"" + searchValue + "\"");
let win = view.styleWindow;
let searchField = view.searchField;
searchField.focus();
synthesizeKeys(searchValue, win);
yield view.inspector.once("ruleview-filtered");
});
/* *********************************************
* COMPUTED-VIEW
* *********************************************
@ -539,23 +225,3 @@ function getComputedViewPropertyValue(view, name, propertyName) {
return getComputedViewProperty(view, name, propertyName)
.valueSpan.textContent;
}
/**
* Open the style editor context menu and return all of it's items in a flat array
* @param {CssRuleView} view
* The instance of the rule-view panel
* @return An array of MenuItems
*/
function openStyleContextMenuAndGetAllItems(view, target) {
let menu = view._contextmenu._openMenu({target: target});
// Flatten all menu items into a single array to make searching through it easier
let allItems = [].concat.apply([], menu.items.map(function addItem(item) {
if (item.submenu) {
return addItem(item.submenu.items);
}
return item;
}));
return allItems;
}

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

@ -6,6 +6,9 @@
/* eslint no-unused-vars: [2, {"vars": "local"}] */
/* globals registerTestActor, getTestActor, Task, openToolboxForTab, gBrowser */
/* import-globals-from ../../framework/test/shared-head.js */
var {getInplaceEditorForSpan: inplaceEditor} = require("devtools/client/shared/inplace-editor");
// This file contains functions related to the inspector that are also of interest to
// other test directores as well.
@ -184,3 +187,356 @@ function manualThrottle() {
return throttle;
}
/**
* Wait for a content -> chrome message on the message manager (the window
* messagemanager is used).
*
* @param {String} name
* The message name
* @return {Promise} A promise that resolves to the response data when the
* message has been received
*/
function waitForContentMessage(name) {
info("Expecting message " + name + " from content");
let mm = gBrowser.selectedBrowser.messageManager;
let def = defer();
mm.addMessageListener(name, function onMessage(msg) {
mm.removeMessageListener(name, onMessage);
def.resolve(msg.data);
});
return def.promise;
}
/**
* Send an async message to the frame script (chrome -> content) and wait for a
* response message with the same name (content -> chrome).
*
* @param {String} name
* The message name. Should be one of the messages defined
* in doc_frame_script.js
* @param {Object} data
* Optional data to send along
* @param {Object} objects
* Optional CPOW objects to send along
* @param {Boolean} expectResponse
* If set to false, don't wait for a response with the same name
* from the content script. Defaults to true.
* @return {Promise} Resolves to the response data if a response is expected,
* immediately resolves otherwise
*/
function executeInContent(name, data = {}, objects = {},
expectResponse = true) {
info("Sending message " + name + " to content");
let mm = gBrowser.selectedBrowser.messageManager;
mm.sendAsyncMessage(name, data, objects);
if (expectResponse) {
return waitForContentMessage(name);
}
return promise.resolve();
}
/**
* Send an async message to the frame script and get back the requested
* computed style property.
*
* @param {String} selector
* The selector used to obtain the element.
* @param {String} pseudo
* pseudo id to query, or null.
* @param {String} name
* name of the property.
*/
function* getComputedStyleProperty(selector, pseudo, propName) {
return yield executeInContent("Test:GetComputedStylePropertyValue",
{selector,
pseudo,
name: propName});
}
/**
* Send an async message to the frame script and wait until the requested
* computed style property has the expected value.
*
* @param {String} selector
* The selector used to obtain the element.
* @param {String} pseudo
* pseudo id to query, or null.
* @param {String} prop
* name of the property.
* @param {String} expected
* expected value of property
* @param {String} name
* the name used in test message
*/
function* waitForComputedStyleProperty(selector, pseudo, name, expected) {
return yield executeInContent("Test:WaitForComputedStylePropertyValue",
{selector,
pseudo,
expected,
name});
}
/**
* Given an inplace editable element, click to switch it to edit mode, wait for
* focus
*
* @return a promise that resolves to the inplace-editor element when ready
*/
var focusEditableField = Task.async(function* (ruleView, editable, xOffset = 1,
yOffset = 1, options = {}) {
let onFocus = once(editable.parentNode, "focus", true);
info("Clicking on editable field to turn to edit mode");
EventUtils.synthesizeMouse(editable, xOffset, yOffset, options,
editable.ownerDocument.defaultView);
yield onFocus;
info("Editable field gained focus, returning the input field now");
let onEdit = inplaceEditor(editable.ownerDocument.activeElement);
return onEdit;
});
/**
* Get the DOMNode for a css rule in the rule-view that corresponds to the given
* selector.
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view for which the rule
* object is wanted
* @param {Number} index
* If there are more than 1 rule with the same selector, you may pass a
* index to determine which of the rules you want.
* @return {DOMNode}
*/
function getRuleViewRule(view, selectorText, index = 0) {
let rule;
let pos = 0;
for (let r of view.styleDocument.querySelectorAll(".ruleview-rule")) {
let selector = r.querySelector(".ruleview-selectorcontainer, " +
".ruleview-selector-matched");
if (selector && selector.textContent === selectorText) {
if (index == pos) {
rule = r;
break;
}
pos++;
}
}
return rule;
}
/**
* Get references to the name and value span nodes corresponding to a given
* selector and property name in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for the property in
* @param {String} propertyName
* The name of the property
* @return {Object} An object like {nameSpan: DOMNode, valueSpan: DOMNode}
*/
function getRuleViewProperty(view, selectorText, propertyName) {
let prop;
let rule = getRuleViewRule(view, selectorText);
if (rule) {
// Look for the propertyName in that rule element
for (let p of rule.querySelectorAll(".ruleview-property")) {
let nameSpan = p.querySelector(".ruleview-propertyname");
let valueSpan = p.querySelector(".ruleview-propertyvalue");
if (nameSpan.textContent === propertyName) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
break;
}
}
}
return prop;
}
/**
* Get the text value of the property corresponding to a given selector and name
* in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for the property in
* @param {String} propertyName
* The name of the property
* @return {String} The property value
*/
function getRuleViewPropertyValue(view, selectorText, propertyName) {
return getRuleViewProperty(view, selectorText, propertyName)
.valueSpan.textContent;
}
/**
* Get a reference to the selector DOM element corresponding to a given selector
* in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for
* @return {DOMNode} The selector DOM element
*/
function getRuleViewSelector(view, selectorText) {
let rule = getRuleViewRule(view, selectorText);
return rule.querySelector(".ruleview-selector, .ruleview-selector-matched");
}
/**
* Get a reference to the selectorhighlighter icon DOM element corresponding to
* a given selector in the rule-view
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} selectorText
* The selector in the rule-view to look for
* @param {Number} index
* If there are more than 1 rule with the same selector, use this index
* to determine which one should be retrieved. Defaults to 0
* @return {DOMNode} The selectorhighlighter icon DOM element
*/
var getRuleViewSelectorHighlighterIcon = Task.async(function* (view,
selectorText, index = 0) {
let rule = getRuleViewRule(view, selectorText, index);
let editor = rule._ruleEditor;
if (!editor.uniqueSelector) {
yield once(editor, "selector-icon-created");
}
return rule.querySelector(".ruleview-selectorhighlighter");
});
/**
* Get a rule-link from the rule-view given its index
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {Number} index
* The index of the link to get
* @return {DOMNode} The link if any at this index
*/
function getRuleViewLinkByIndex(view, index) {
let links = view.styleDocument.querySelectorAll(".ruleview-rule-source");
return links[index];
}
/**
* Get rule-link text from the rule-view given its index
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {Number} index
* The index of the link to get
* @return {String} The string at this index
*/
function getRuleViewLinkTextByIndex(view, index) {
let link = getRuleViewLinkByIndex(view, index);
return link.querySelector(".ruleview-rule-source-label").textContent;
}
/**
* Click on a rule-view's close brace to focus a new property name editor
*
* @param {RuleEditor} ruleEditor
* An instance of RuleEditor that will receive the new property
* @return a promise that resolves to the newly created editor when ready and
* focused
*/
var focusNewRuleViewProperty = Task.async(function* (ruleEditor) {
info("Clicking on a close ruleEditor brace to start editing a new property");
// Use bottom alignment to avoid scrolling out of the parent element area.
ruleEditor.closeBrace.scrollIntoView(false);
let editor = yield focusEditableField(ruleEditor.ruleView,
ruleEditor.closeBrace);
is(inplaceEditor(ruleEditor.newPropSpan), editor,
"Focused editor is the new property editor.");
return editor;
});
/**
* Create a new property name in the rule-view, focusing a new property editor
* by clicking on the close brace, and then entering the given text.
* Keep in mind that the rule-view knows how to handle strings with multiple
* properties, so the input text may be like: "p1:v1;p2:v2;p3:v3".
*
* @param {RuleEditor} ruleEditor
* The instance of RuleEditor that will receive the new property(ies)
* @param {String} inputValue
* The text to be entered in the new property name field
* @return a promise that resolves when the new property name has been entered
* and once the value field is focused
*/
var createNewRuleViewProperty = Task.async(function* (ruleEditor, inputValue) {
info("Creating a new property editor");
let editor = yield focusNewRuleViewProperty(ruleEditor);
info("Entering the value " + inputValue);
editor.input.value = inputValue;
info("Submitting the new value and waiting for value field focus");
let onFocus = once(ruleEditor.element, "focus", true);
EventUtils.synthesizeKey("VK_RETURN", {},
ruleEditor.element.ownerDocument.defaultView);
yield onFocus;
});
/**
* Set the search value for the rule-view filter styles search box.
*
* @param {CssRuleView} view
* The instance of the rule-view panel
* @param {String} searchValue
* The filter search value
* @return a promise that resolves when the rule-view is filtered for the
* search term
*/
var setSearchFilter = Task.async(function* (view, searchValue) {
info("Setting filter text to \"" + searchValue + "\"");
let searchField = view.searchField;
searchField.focus();
for (let key of searchValue.split("")) {
EventUtils.synthesizeKey(key, {}, view.styleWindow);
}
yield view.inspector.once("ruleview-filtered");
});
/**
* Open the style editor context menu and return all of it's items in a flat array
* @param {CssRuleView} view
* The instance of the rule-view panel
* @return An array of MenuItems
*/
function openStyleContextMenuAndGetAllItems(view, target) {
let menu = view._contextmenu._openMenu({target: target});
// Flatten all menu items into a single array to make searching through it easier
let allItems = [].concat.apply([], menu.items.map(function addItem(item) {
if (item.submenu) {
return addItem(item.submenu.items);
}
return item;
}));
return allItems;
}

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

@ -224,22 +224,36 @@ ToolSidebar.prototype = {
let previousTool = this._currentTool;
if (previousTool) {
if (this._telemetry) {
this._telemetry.toolClosed(previousTool);
}
this.emit(previousTool + "-unselected");
}
this._currentTool = id;
if (this._telemetry) {
this._telemetry.toolOpened(this._currentTool);
}
this.updateTelemetryOnChange(id, previousTool);
this.emit(this._currentTool + "-selected");
this.emit("select", this._currentTool);
},
/**
* Log toolClosed and toolOpened events on telemetry.
*
* @param {String} currentToolId
* id of the tool being selected.
* @param {String} previousToolId
* id of the previously selected tool.
*/
updateTelemetryOnChange: function (currentToolId, previousToolId) {
if (currentToolId === previousToolId || !this._telemetry) {
// Skip telemetry if the tool id did not change or telemetry is unavailable.
return;
}
if (previousToolId) {
this._telemetry.toolClosed(previousToolId);
}
this._telemetry.toolOpened(currentToolId);
},
/**
* Show the sidebar.
*
@ -249,14 +263,9 @@ ToolSidebar.prototype = {
show: function (id) {
this._tabbox.removeAttribute("hidden");
// If an id is given, select the corresponding sidebar tab and record the
// tool opened.
// If an id is given, select the corresponding sidebar tab.
if (id) {
this._currentTool = id;
if (this._telemetry) {
this._telemetry.toolOpened(this._currentTool);
}
this.select(id);
}
this.emit("show");

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

@ -1,32 +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 { DOM } = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { L10N } = require("../l10n");
const Actions = require("../actions/index");
const { button } = DOM;
/*
* Clear button component
* A type of tool button is responsible for cleaning network requests.
*/
function ClearButton({ onClick }) {
return button({
id: "requests-menu-clear-button",
className: "devtools-button devtools-clear-icon",
title: L10N.getStr("netmonitor.toolbar.clear"),
onClick,
});
}
module.exports = connect(
undefined,
dispatch => ({
onClick: () => dispatch(Actions.clearRequests())
})
)(ClearButton);

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

@ -1,50 +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 { DOM, PropTypes } = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { L10N } = require("../l10n");
const Actions = require("../actions/index");
const { button, div } = DOM;
function FilterButtons({
requestFilterTypes,
toggleRequestFilterType,
}) {
const buttons = requestFilterTypes.entrySeq().map(([type, checked]) => {
let classList = ["menu-filter-button"];
checked && classList.push("checked");
return button({
id: `requests-menu-filter-${type}-button`,
key: type,
className: classList.join(" "),
"data-key": type,
onClick: toggleRequestFilterType,
onKeyDown: toggleRequestFilterType,
}, L10N.getStr(`netmonitor.toolbar.filter.${type}`));
}).toArray();
return div({ id: "requests-menu-filter-buttons" }, buttons);
}
FilterButtons.propTypes = {
requestFilterTypes: PropTypes.object.isRequired,
toggleRequestFilterType: PropTypes.func.isRequired,
};
module.exports = connect(
(state) => ({ requestFilterTypes: state.filters.requestFilterTypes }),
(dispatch) => ({
toggleRequestFilterType: (evt) => {
if (evt.type === "keydown" && (evt.key !== "" || evt.key !== "Enter")) {
return;
}
dispatch(Actions.toggleRequestFilterType(evt.target.dataset.key));
},
})
)(FilterButtons);

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

@ -3,16 +3,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'clear-button.js',
'filter-buttons.js',
'request-list-content.js',
'request-list-empty.js',
'request-list-header.js',
'request-list-item.js',
'request-list-tooltip.js',
'request-list.js',
'search-box.js',
'summary-button.js',
'toggle-button.js',
'statistics-panel.js',
'toolbar.js',
)

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

@ -1,23 +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 { connect } = require("devtools/client/shared/vendor/react-redux");
const SearchBox = require("devtools/client/shared/components/search-box");
const { L10N } = require("../l10n");
const Actions = require("../actions/index");
const { FILTER_SEARCH_DELAY } = require("../constants");
module.exports = connect(
(state) => ({
delay: FILTER_SEARCH_DELAY,
keyShortcut: L10N.getStr("netmonitor.toolbar.filterFreetext.key"),
placeholder: L10N.getStr("netmonitor.toolbar.filterFreetext.label"),
type: "filter",
}),
(dispatch) => ({
onChange: (text) => dispatch(Actions.setRequestFilterText(text)),
})
)(SearchBox);

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

@ -0,0 +1,229 @@
/* 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/. */
/* globals document */
"use strict";
const {
createClass,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { Chart } = require("devtools/client/shared/widgets/Chart");
const { PluralForm } = require("devtools/shared/plural-form");
const Actions = require("../actions/index");
const { Filters } = require("../filter-predicates");
const { L10N } = require("../l10n");
const {
getSizeWithDecimals,
getTimeWithDecimals
} = require("../utils/format-utils");
const { button, div } = DOM;
const NETWORK_ANALYSIS_PIE_CHART_DIAMETER = 200;
const BACK_BUTTON = L10N.getStr("netmonitor.backButton");
const CHARTS_CACHE_ENABLED = L10N.getStr("charts.cacheEnabled");
const CHARTS_CACHE_DISABLED = L10N.getStr("charts.cacheDisabled");
/*
* Statistics panel component
* Performance analysis tool which shows you how long the browser takes to
* download the different parts of your site.
*/
const StatisticsPanel = createClass({
displayName: "StatisticsPanel",
propTypes: {
closeStatistics: PropTypes.func.isRequired,
enableRequestFilterTypeOnly: PropTypes.func.isRequired,
requests: PropTypes.object,
},
componentDidUpdate(prevProps) {
const { requests } = this.props;
let ready = requests && requests.every((req) =>
req.contentSize !== undefined && req.mimeType && req.responseHeaders &&
req.status !== undefined && req.totalTime !== undefined
);
this.createChart({
id: "primedCacheChart",
title: CHARTS_CACHE_ENABLED,
data: ready ? this.sanitizeChartDataSource(requests, false) : null,
});
this.createChart({
id: "emptyCacheChart",
title: CHARTS_CACHE_DISABLED,
data: ready ? this.sanitizeChartDataSource(requests, true) : null,
});
},
createChart({ id, title, data }) {
// Create a new chart.
let chart = Chart.PieTable(document, {
diameter: NETWORK_ANALYSIS_PIE_CHART_DIAMETER,
title,
data,
strings: {
size: (value) =>
L10N.getFormatStr("charts.sizeKB", getSizeWithDecimals(value / 1024)),
time: (value) =>
L10N.getFormatStr("charts.totalS", getTimeWithDecimals(value / 1000)),
},
totals: {
cached: (total) => L10N.getFormatStr("charts.totalCached", total),
count: (total) => L10N.getFormatStr("charts.totalCount", total),
size: (total) =>
L10N.getFormatStr("charts.totalSize", getSizeWithDecimals(total / 1024)),
time: (total) => {
let seconds = total / 1000;
let string = getTimeWithDecimals(seconds);
return PluralForm.get(seconds,
L10N.getStr("charts.totalSeconds")).replace("#1", string);
},
},
sorted: true,
});
chart.on("click", (_, { label }) => {
// Reset FilterButtons and enable one filter exclusively
this.props.closeStatistics();
this.props.enableRequestFilterTypeOnly(label);
});
let container = this.refs[id];
// Nuke all existing charts of the specified type.
while (container.hasChildNodes()) {
container.firstChild.remove();
}
container.appendChild(chart.node);
},
sanitizeChartDataSource(requests, emptyCache) {
let data = [
"html", "css", "js", "xhr", "fonts", "images", "media", "flash", "ws", "other"
].map((type) => ({ cached: 0, count: 0, label: type, size: 0, time: 0 }));
for (let request of requests) {
let type;
if (Filters.html(request)) {
// "html"
type = 0;
} else if (Filters.css(request)) {
// "css"
type = 1;
} else if (Filters.js(request)) {
// "js"
type = 2;
} else if (Filters.fonts(request)) {
// "fonts"
type = 4;
} else if (Filters.images(request)) {
// "images"
type = 5;
} else if (Filters.media(request)) {
// "media"
type = 6;
} else if (Filters.flash(request)) {
// "flash"
type = 7;
} else if (Filters.ws(request)) {
// "ws"
type = 8;
} else if (Filters.xhr(request)) {
// Verify XHR last, to categorize other mime types in their own blobs.
// "xhr"
type = 3;
} else {
// "other"
type = 9;
}
if (emptyCache || !this.responseIsFresh(request)) {
data[type].time += request.totalTime || 0;
data[type].size += request.contentSize || 0;
} else {
data[type].cached++;
}
data[type].count++;
}
return data.filter(e => e.count > 0);
},
/**
* Checks if the "Expiration Calculations" defined in section 13.2.4 of the
* "HTTP/1.1: Caching in HTTP" spec holds true for a collection of headers.
*
* @param object
* An object containing the { responseHeaders, status } properties.
* @return boolean
* True if the response is fresh and loaded from cache.
*/
responseIsFresh({ responseHeaders, status }) {
// Check for a "304 Not Modified" status and response headers availability.
if (status != 304 || !responseHeaders) {
return false;
}
let list = responseHeaders.headers;
let cacheControl = list.find(e => e.name.toLowerCase() === "cache-control");
let expires = list.find(e => e.name.toLowerCase() === "expires");
// Check the "Cache-Control" header for a maximum age value.
if (cacheControl) {
let maxAgeMatch =
cacheControl.value.match(/s-maxage\s*=\s*(\d+)/) ||
cacheControl.value.match(/max-age\s*=\s*(\d+)/);
if (maxAgeMatch && maxAgeMatch.pop() > 0) {
return true;
}
}
// Check the "Expires" header for a valid date.
if (expires && Date.parse(expires.value)) {
return true;
}
return false;
},
render() {
const { closeStatistics } = this.props;
return (
div({ className: "statistics-panel" },
button({
className: "back-button devtools-toolbarbutton",
"data-text-only": "true",
title: BACK_BUTTON,
onClick: closeStatistics,
}, BACK_BUTTON),
div({ className: "charts-container devtools-responsive-container" },
div({ ref: "primedCacheChart", className: "charts primed-cache-chart" }),
div({ className: "splitter devtools-side-splitter" }),
div({ ref: "emptyCacheChart", className: "charts empty-cache-chart" }),
),
)
);
}
});
module.exports = connect(
(state) => ({
requests: state.requests.requests.valueSeq(),
}),
(dispatch) => ({
closeStatistics: () => dispatch(Actions.openStatistics(false)),
enableRequestFilterTypeOnly: (label) =>
dispatch(Actions.enableRequestFilterTypeOnly(label)),
})
)(StatisticsPanel);

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

@ -1,54 +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 { DOM, PropTypes } = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { PluralForm } = require("devtools/shared/plural-form");
const { L10N } = require("../l10n");
const { getDisplayedRequestsSummary } = require("../selectors/index");
const Actions = require("../actions/index");
const {
getSizeWithDecimals,
getTimeWithDecimals,
} = require("../utils/format-utils");
const { button, span } = DOM;
function SummaryButton({
summary,
triggerSummary,
}) {
let { count, bytes, millis } = summary;
const text = (count === 0) ? L10N.getStr("networkMenu.empty") :
PluralForm.get(count, L10N.getStr("networkMenu.summary"))
.replace("#1", count)
.replace("#2", getSizeWithDecimals(bytes / 1024))
.replace("#3", getTimeWithDecimals(millis / 1000));
return button({
id: "requests-menu-network-summary-button",
className: "devtools-button",
title: count ? text : L10N.getStr("netmonitor.toolbar.perf"),
onClick: triggerSummary,
},
span({ className: "summary-info-icon" }),
span({ className: "summary-info-text" }, text));
}
SummaryButton.propTypes = {
summary: PropTypes.object.isRequired,
};
module.exports = connect(
(state) => ({
summary: getDisplayedRequestsSummary(state),
}),
(dispatch) => ({
triggerSummary: () => {
dispatch(Actions.openStatistics(true));
},
})
)(SummaryButton);

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

@ -1,51 +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 { DOM, PropTypes } = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { L10N } = require("../l10n");
const Actions = require("../actions/index");
const { isSidebarToggleButtonDisabled } = require("../selectors/index");
const { button } = DOM;
function ToggleButton({
disabled,
open,
onToggle,
}) {
let className = ["devtools-button"];
if (!open) {
className.push("pane-collapsed");
}
const title = open ? L10N.getStr("collapseDetailsPane") :
L10N.getStr("expandDetailsPane");
return button({
id: "details-pane-toggle",
className: className.join(" "),
title,
disabled,
tabIndex: "0",
onMouseDown: onToggle,
});
}
ToggleButton.propTypes = {
disabled: PropTypes.bool.isRequired,
onToggle: PropTypes.func.isRequired,
};
module.exports = connect(
(state) => ({
disabled: isSidebarToggleButtonDisabled(state),
open: state.ui.sidebarOpen,
}),
(dispatch) => ({
onToggle: () => dispatch(Actions.toggleSidebar())
})
)(ToggleButton);

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

@ -7,31 +7,150 @@
const {
createFactory,
DOM,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const ClearButton = createFactory(require("./clear-button"));
const FilterButtons = createFactory(require("./filter-buttons"));
const ToolbarSearchBox = createFactory(require("./search-box"));
const SummaryButton = createFactory(require("./summary-button"));
const ToggleButton = createFactory(require("./toggle-button"));
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { PluralForm } = require("devtools/shared/plural-form");
const Actions = require("../actions/index");
const { L10N } = require("../l10n");
const {
getDisplayedRequestsSummary,
isSidebarToggleButtonDisabled,
} = require("../selectors/index");
const {
getSizeWithDecimals,
getTimeWithDecimals,
} = require("../utils/format-utils");
const { FILTER_SEARCH_DELAY } = require("../constants");
const { span } = DOM;
// Components
const SearchBox = createFactory(require("devtools/client/shared/components/search-box"));
const { button, div, span } = DOM;
const COLLPASE_DETAILS_PANE = L10N.getStr("collapseDetailsPane");
const EXPAND_DETAILS_PANE = L10N.getStr("expandDetailsPane");
const SEARCH_KEY_SHORTCUT = L10N.getStr("netmonitor.toolbar.filterFreetext.key");
const SEARCH_PLACE_HOLDER = L10N.getStr("netmonitor.toolbar.filterFreetext.label");
const TOOLBAR_CLEAR = L10N.getStr("netmonitor.toolbar.clear");
/*
* Network monitor toolbar component
* Toolbar contains a set of useful tools to control network requests
*/
function Toolbar() {
return span({ className: "devtools-toolbar devtools-toolbar-container" },
span({ className: "devtools-toolbar-group" },
ClearButton(),
FilterButtons()
),
span({ className: "devtools-toolbar-group" },
SummaryButton(),
ToolbarSearchBox(),
ToggleButton()
function Toolbar({
clearRequests,
openStatistics,
requestFilterTypes,
setRequestFilterText,
sidebarToggleDisabled,
sidebarOpen,
summary,
toggleRequestFilterType,
toggleSidebar,
}) {
let toggleButtonClassName = ["devtools-button"];
if (!sidebarOpen) {
toggleButtonClassName.push("pane-collapsed");
}
let { count, bytes, millis } = summary;
const text = (count === 0) ? L10N.getStr("networkMenu.empty") :
PluralForm.get(count, L10N.getStr("networkMenu.summary"))
.replace("#1", count)
.replace("#2", getSizeWithDecimals(bytes / 1024))
.replace("#3", getTimeWithDecimals(millis / 1000));
const buttons = requestFilterTypes.entrySeq().map(([type, checked]) => {
let classList = ["menu-filter-button"];
checked && classList.push("checked");
return (
button({
id: `requests-menu-filter-${type}-button`,
key: type,
className: classList.join(" "),
"data-key": type,
onClick: toggleRequestFilterType,
onKeyDown: toggleRequestFilterType,
},
L10N.getStr(`netmonitor.toolbar.filter.${type}`)
)
);
}).toArray();
return (
span({ className: "devtools-toolbar devtools-toolbar-container" },
span({ className: "devtools-toolbar-group" },
button({
id: "requests-menu-clear-button",
className: "devtools-button devtools-clear-icon",
title: TOOLBAR_CLEAR,
onClick: clearRequests,
}),
div({ id: "requests-menu-filter-buttons" }, buttons),
),
span({ className: "devtools-toolbar-group" },
button({
id: "requests-menu-network-summary-button",
className: "devtools-button",
title: count ? text : L10N.getStr("netmonitor.toolbar.perf"),
onClick: openStatistics,
},
span({ className: "summary-info-icon" }),
span({ className: "summary-info-text" }, text),
),
SearchBox({
delay: FILTER_SEARCH_DELAY,
keyShortcut: SEARCH_KEY_SHORTCUT,
placeholder: SEARCH_PLACE_HOLDER,
type: "filter",
onChange: setRequestFilterText,
}),
button({
id: "details-pane-toggle",
className: toggleButtonClassName.join(" "),
title: sidebarOpen ? COLLPASE_DETAILS_PANE : EXPAND_DETAILS_PANE,
disabled: sidebarToggleDisabled,
tabIndex: "0",
onMouseDown: toggleSidebar,
}),
)
)
);
}
module.exports = Toolbar;
Toolbar.displayName = "Toolbar";
Toolbar.propTypes = {
clearRequests: PropTypes.func.isRequired,
openStatistics: PropTypes.func.isRequired,
requestFilterTypes: PropTypes.object.isRequired,
setRequestFilterText: PropTypes.func.isRequired,
sidebarToggleDisabled: PropTypes.bool.isRequired,
sidebarOpen: PropTypes.bool.isRequired,
summary: PropTypes.object.isRequired,
toggleRequestFilterType: PropTypes.func.isRequired,
toggleSidebar: PropTypes.func.isRequired,
};
module.exports = connect(
(state) => ({
sidebarToggleDisabled: isSidebarToggleButtonDisabled(state),
sidebarOpen: state.ui.sidebarOpen,
requestFilterTypes: state.filters.requestFilterTypes,
summary: getDisplayedRequestsSummary(state),
}),
(dispatch) => ({
clearRequests: () => dispatch(Actions.clearRequests()),
openStatistics: () => dispatch(Actions.openStatistics(true)),
setRequestFilterText: (text) => dispatch(Actions.setRequestFilterText(text)),
toggleRequestFilterType: (evt) => {
if (evt.type === "keydown" && (evt.key !== "" || evt.key !== "Enter")) {
return;
}
dispatch(Actions.toggleRequestFilterType(evt.target.dataset.key));
},
toggleSidebar: () => dispatch(Actions.toggleSidebar()),
})
)(Toolbar);

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

@ -28,9 +28,7 @@ DevToolsModules(
'requests-menu-view.js',
'sidebar-view.js',
'sort-predicates.js',
'statistics-view.js',
'store.js',
'toolbar-view.js',
'waterfall-background.js',
)

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

@ -2,36 +2,26 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-disable mozilla/reject-some-requires */
/* globals $, gStore, NetMonitorController, dumpn */
"use strict";
const { testing: isTesting } = require("devtools/shared/flags");
const { Task } = require("devtools/shared/task");
const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
const { RequestsMenuView } = require("./requests-menu-view");
const { CustomRequestView } = require("./custom-request-view");
const { ToolbarView } = require("./toolbar-view");
const { SidebarView } = require("./sidebar-view");
const { StatisticsView } = require("./statistics-view");
const { ACTIVITY_TYPE } = require("./constants");
const { Prefs } = require("./prefs");
const { createFactory } = require("devtools/client/shared/vendor/react");
const Actions = require("./actions/index");
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
// Components
const DetailsPanel = createFactory(require("./shared/components/details-panel"));
// ms
const WDA_DEFAULT_VERIFY_INTERVAL = 50;
// Use longer timeout during testing as the tests need this process to succeed
// and two seconds is quite short on slow debug builds. The timeout here should
// be at least equal to the general mochitest timeout of 45 seconds so that this
// never gets hit during testing.
// ms
const WDA_DEFAULT_GIVE_UP_TIMEOUT = isTesting ? 45000 : 2000;
const StatisticsPanel = createFactory(require("./components/statistics-panel"));
const Toolbar = createFactory(require("./components/toolbar"));
/**
* Object defining the network monitor view components.
@ -43,11 +33,6 @@ var NetMonitorView = {
initialize: function () {
this._initializePanes();
this.Toolbar.initialize(gStore);
this.RequestsMenu.initialize(gStore);
this.CustomRequest.initialize();
this.Statistics.initialize(gStore);
this.detailsPanel = $("#react-details-panel-hook");
ReactDOM.render(Provider(
@ -55,6 +40,23 @@ var NetMonitorView = {
DetailsPanel({ toolbox: NetMonitorController._toolbox }),
), this.detailsPanel);
this.statisticsPanel = $("#statistics-panel");
ReactDOM.render(Provider(
{ store: gStore },
StatisticsPanel(),
), this.statisticsPanel);
this.toolbar = $("#react-toolbar-hook");
ReactDOM.render(Provider(
{ store: gStore },
Toolbar(),
), this.toolbar);
this.RequestsMenu.initialize(gStore);
this.CustomRequest.initialize();
// Store watcher here is for observing the statisticsOpen state change.
// It should be removed once we migrate to react and apply react/redex binding.
this.unsubscribeStore = gStore.subscribe(storeWatcher(
@ -69,11 +71,11 @@ var NetMonitorView = {
*/
destroy: function () {
this._isDestroyed = true;
this.Toolbar.destroy();
this.RequestsMenu.destroy();
this.CustomRequest.destroy();
this.Statistics.destroy();
ReactDOM.unmountComponentAtNode(this.detailsPanel);
ReactDOM.unmountComponentAtNode(this.statisticsPanel);
ReactDOM.unmountComponentAtNode(this.toolbar);
this.unsubscribeStore();
this._destroyPanes();
@ -141,10 +143,6 @@ var NetMonitorView = {
}
},
/**
* Gets the current mode for this tool.
* @return string (e.g, "network-inspector-view" or "network-statistics-view")
*/
get currentFrontendMode() {
// The getter may be called from a timeout after the panel is destroyed.
if (!this._body.selectedPanel) {
@ -153,9 +151,6 @@ var NetMonitorView = {
return this._body.selectedPanel.id;
},
/**
* Toggles between the frontend view modes ("Inspector" vs. "Statistics").
*/
toggleFrontendMode: function () {
if (gStore.getState().ui.statisticsOpen) {
this.showNetworkStatisticsView();
@ -164,45 +159,13 @@ var NetMonitorView = {
}
},
/**
* Switches to the "Inspector" frontend view mode.
*/
showNetworkInspectorView: function () {
this._body.selectedPanel = $("#network-inspector-view");
this._body.selectedPanel = $("#inspector-panel");
},
/**
* Switches to the "Statistics" frontend view mode.
*/
showNetworkStatisticsView: function () {
this._body.selectedPanel = $("#network-statistics-view");
let controller = NetMonitorController;
let requestsView = this.RequestsMenu;
let statisticsView = this.Statistics;
Task.spawn(function* () {
statisticsView.displayPlaceholderCharts();
yield controller.triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_ENABLED);
try {
// • The response headers and status code are required for determining
// whether a response is "fresh" (cacheable).
// • The response content size and request total time are necessary for
// populating the statistics view.
// • The response mime type is used for categorization.
yield whenDataAvailable(requestsView.store, [
"responseHeaders", "status", "contentSize", "mimeType", "totalTime"
]);
} catch (ex) {
// Timed out while waiting for data. Continue with what we have.
console.error(ex);
}
const requests = requestsView.store.getState().requests.requests.valueSeq();
statisticsView.createPrimedCacheChart(requests);
statisticsView.createEmptyCacheChart(requests);
});
this._body.selectedPanel = $("#statistics-panel");
NetMonitorController.triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_ENABLED);
},
reloadPage: function () {
@ -214,41 +177,6 @@ var NetMonitorView = {
_detailsPane: null,
};
/**
* Makes sure certain properties are available on all objects in a data store.
*
* @param Store dataStore
* A Redux store for which to check the availability of properties.
* @param array mandatoryFields
* A list of strings representing properties of objects in dataStore.
* @return object
* A promise resolved when all objects in dataStore contain the
* properties defined in mandatoryFields.
*/
function whenDataAvailable(dataStore, mandatoryFields) {
return new Promise((resolve, reject) => {
let interval = setInterval(() => {
const { requests } = dataStore.getState().requests;
const allFieldsPresent = !requests.isEmpty() && requests.every(
item => mandatoryFields.every(
field => item.get(field) !== undefined
)
);
if (allFieldsPresent) {
clearInterval(interval);
clearTimeout(timer);
resolve();
}
}, WDA_DEFAULT_VERIFY_INTERVAL);
let timer = setTimeout(() => {
clearInterval(interval);
reject(new Error("Timed out while waiting for data"));
}, WDA_DEFAULT_GIVE_UP_TIMEOUT);
});
}
// A smart store watcher to notify store changes as necessary
function storeWatcher(initialValue, reduceValue, onChange) {
let currentValue = initialValue;
@ -265,10 +193,8 @@ function storeWatcher(initialValue, reduceValue, onChange) {
/**
* Preliminary setup for the NetMonitorView object.
*/
NetMonitorView.Toolbar = new ToolbarView();
NetMonitorView.Sidebar = new SidebarView();
NetMonitorView.RequestsMenu = new RequestsMenuView();
NetMonitorView.CustomRequest = new CustomRequestView();
NetMonitorView.Statistics = new StatisticsView();
exports.NetMonitorView = NetMonitorView;

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

@ -19,7 +19,7 @@
flex="1"
data-localization-bundle="devtools/client/locales/netmonitor.properties">
<vbox id="network-inspector-view" flex="1">
<vbox id="inspector-panel" flex="1">
<html:div xmlns="http://www.w3.org/1999/xhtml"
id="react-toolbar-hook"/>
<hbox id="network-table-and-sidebar"
@ -101,19 +101,8 @@
</vbox>
<html:div id="network-statistics-view">
<html:div id="network-statistics-toolbar"
class="devtools-toolbar">
<html:div xmlns="http://www.w3.org/1999/xhtml"
id="react-statistics-back-hook"/>
</html:div>
<html:div id="network-statistics-charts"
class="devtools-responsive-container">
<html:div id="primed-cache-chart"/>
<html:div id="network-statistics-view-splitter"
class="split-box devtools-side-splitter"/>
<html:div id="empty-cache-chart"/>
</html:div>
<html:div xmlns="http://www.w3.org/1999/xhtml"
id="statistics-panel">
</html:div>
</deck>

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

@ -112,7 +112,7 @@ const PropertiesView = createClass({
// 2. the `value` object has a `value` property, only happend in Cookies panel
// Put 2 here to not dup this method
if (member.level === 0 ||
(typeof member.value === "object" && member.value.value)) {
(typeof member.value === "object" && member.value && member.value.value)) {
return null;
}

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

@ -1,288 +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/. */
/* eslint-disable mozilla/reject-some-requires */
/* globals $, window, document */
"use strict";
const { PluralForm } = require("devtools/shared/plural-form");
const { Filters } = require("./filter-predicates");
const { L10N } = require("./l10n");
const { EVENTS } = require("./events");
const { DOM } = require("devtools/client/shared/vendor/react");
const { button } = DOM;
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const Actions = require("./actions/index");
const { Chart } = require("devtools/client/shared/widgets/Chart");
const {
getSizeWithDecimals,
getTimeWithDecimals
} = require("./utils/format-utils");
// px
const NETWORK_ANALYSIS_PIE_CHART_DIAMETER = 200;
/**
* Functions handling the performance statistics view.
*/
function StatisticsView() {
}
StatisticsView.prototype = {
/**
* Initialization function, called when the statistics view is started.
*/
initialize: function (store) {
this.store = store;
this.Chart = Chart;
this._backButton = $("#react-statistics-back-hook");
let backStr = L10N.getStr("netmonitor.backButton");
ReactDOM.render(button({
id: "network-statistics-back-button",
className: "devtools-toolbarbutton",
"data-text-only": "true",
title: backStr,
onClick: () => {
this.store.dispatch(Actions.openStatistics(false));
},
}, backStr), this._backButton);
},
/**
* Destruction function, called when the statistics view is closed.
*/
destroy: function () {
ReactDOM.unmountComponentAtNode(this._backButton);
},
/**
* Initializes and displays empty charts in this container.
*/
displayPlaceholderCharts: function () {
this._createChart({
id: "#primed-cache-chart",
title: "charts.cacheEnabled"
});
this._createChart({
id: "#empty-cache-chart",
title: "charts.cacheDisabled"
});
window.emit(EVENTS.PLACEHOLDER_CHARTS_DISPLAYED);
},
/**
* Populates and displays the primed cache chart in this container.
*
* @param array items
* @see this._sanitizeChartDataSource
*/
createPrimedCacheChart: function (items) {
this._createChart({
id: "#primed-cache-chart",
title: "charts.cacheEnabled",
data: this._sanitizeChartDataSource(items),
strings: this._commonChartStrings,
totals: this._commonChartTotals,
sorted: true
});
window.emit(EVENTS.PRIMED_CACHE_CHART_DISPLAYED);
},
/**
* Populates and displays the empty cache chart in this container.
*
* @param array items
* @see this._sanitizeChartDataSource
*/
createEmptyCacheChart: function (items) {
this._createChart({
id: "#empty-cache-chart",
title: "charts.cacheDisabled",
data: this._sanitizeChartDataSource(items, true),
strings: this._commonChartStrings,
totals: this._commonChartTotals,
sorted: true
});
window.emit(EVENTS.EMPTY_CACHE_CHART_DISPLAYED);
},
/**
* Common stringifier predicates used for items and totals in both the
* "primed" and "empty" cache charts.
*/
_commonChartStrings: {
size: value => {
let string = getSizeWithDecimals(value / 1024);
return L10N.getFormatStr("charts.sizeKB", string);
},
time: value => {
let string = getTimeWithDecimals(value / 1000);
return L10N.getFormatStr("charts.totalS", string);
}
},
_commonChartTotals: {
size: total => {
let string = getSizeWithDecimals(total / 1024);
return L10N.getFormatStr("charts.totalSize", string);
},
time: total => {
let seconds = total / 1000;
let string = getTimeWithDecimals(seconds);
return PluralForm.get(seconds,
L10N.getStr("charts.totalSeconds")).replace("#1", string);
},
cached: total => {
return L10N.getFormatStr("charts.totalCached", total);
},
count: total => {
return L10N.getFormatStr("charts.totalCount", total);
}
},
/**
* Adds a specific chart to this container.
*
* @param object
* An object containing all or some the following properties:
* - id: either "#primed-cache-chart" or "#empty-cache-chart"
* - title/data/strings/totals/sorted: @see Chart.js for details
*/
_createChart: function ({ id, title, data, strings, totals, sorted }) {
let container = $(id);
// Nuke all existing charts of the specified type.
while (container.hasChildNodes()) {
container.firstChild.remove();
}
// Create a new chart.
let chart = this.Chart.PieTable(document, {
diameter: NETWORK_ANALYSIS_PIE_CHART_DIAMETER,
title: L10N.getStr(title),
data: data,
strings: strings,
totals: totals,
sorted: sorted
});
chart.on("click", (_, item) => {
// Reset FilterButtons and enable one filter exclusively
this.store.dispatch(Actions.enableRequestFilterTypeOnly(item.label));
this.store.dispatch(Actions.openStatistics(false));
});
container.appendChild(chart.node);
},
/**
* Sanitizes the data source used for creating charts, to follow the
* data format spec defined in Chart.js.
*
* @param array items
* A collection of request items used as the data source for the chart.
* @param boolean emptyCache
* True if the cache is considered enabled, false for disabled.
*/
_sanitizeChartDataSource: function (items, emptyCache) {
let data = [
"html", "css", "js", "xhr", "fonts", "images", "media", "flash", "ws", "other"
].map(e => ({
cached: 0,
count: 0,
label: e,
size: 0,
time: 0
}));
for (let requestItem of items) {
let details = requestItem;
let type;
if (Filters.html(details)) {
// "html"
type = 0;
} else if (Filters.css(details)) {
// "css"
type = 1;
} else if (Filters.js(details)) {
// "js"
type = 2;
} else if (Filters.fonts(details)) {
// "fonts"
type = 4;
} else if (Filters.images(details)) {
// "images"
type = 5;
} else if (Filters.media(details)) {
// "media"
type = 6;
} else if (Filters.flash(details)) {
// "flash"
type = 7;
} else if (Filters.ws(details)) {
// "ws"
type = 8;
} else if (Filters.xhr(details)) {
// Verify XHR last, to categorize other mime types in their own blobs.
// "xhr"
type = 3;
} else {
// "other"
type = 9;
}
if (emptyCache || !responseIsFresh(details)) {
data[type].time += details.totalTime || 0;
data[type].size += details.contentSize || 0;
} else {
data[type].cached++;
}
data[type].count++;
}
return data.filter(e => e.count > 0);
},
};
/**
* Checks if the "Expiration Calculations" defined in section 13.2.4 of the
* "HTTP/1.1: Caching in HTTP" spec holds true for a collection of headers.
*
* @param object
* An object containing the { responseHeaders, status } properties.
* @return boolean
* True if the response is fresh and loaded from cache.
*/
function responseIsFresh({ responseHeaders, status }) {
// Check for a "304 Not Modified" status and response headers availability.
if (status != 304 || !responseHeaders) {
return false;
}
let list = responseHeaders.headers;
let cacheControl = list.find(e => e.name.toLowerCase() == "cache-control");
let expires = list.find(e => e.name.toLowerCase() == "expires");
// Check the "Cache-Control" header for a maximum age value.
if (cacheControl) {
let maxAgeMatch =
cacheControl.value.match(/s-maxage\s*=\s*(\d+)/) ||
cacheControl.value.match(/max-age\s*=\s*(\d+)/);
if (maxAgeMatch && maxAgeMatch.pop() > 0) {
return true;
}
}
// Check the "Expires" header for a valid date.
if (expires && Date.parse(expires.value)) {
return true;
}
return false;
}
exports.StatisticsView = StatisticsView;

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

@ -17,6 +17,7 @@ support-files =
html_filter-test-page.html
html_infinite-get-page.html
html_json-b64.html
html_json-basic.html
html_json-custom-mime-test-page.html
html_json-long-test-page.html
html_json-malformed-test-page.html
@ -41,6 +42,7 @@ support-files =
sjs_cors-test-server.sjs
sjs_https-redirect-test-server.sjs
sjs_hsts-test-server.sjs
sjs_json-test-server.sjs
sjs_simple-test-server.sjs
sjs_sorting-test-server.sjs
sjs_status-codes-test-server.sjs
@ -107,6 +109,7 @@ skip-if = (os == 'linux' && debug && bits == 32) # Bug 1303439
[browser_net_icon-preview.js]
[browser_net_image-tooltip.js]
[browser_net_json-b64.js]
[browser_net_json-null.js]
[browser_net_json-long.js]
[browser_net_json-malformed.js]
[browser_net_json_custom_mime.js]

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

@ -11,8 +11,8 @@ add_task(function* () {
let { monitor } = yield initNetMonitor(SIMPLE_URL);
info("Starting test... ");
let { document, NetMonitorView } = monitor.panelWin;
const { Chart } = NetMonitorView.Statistics;
let { document, windowRequire } = monitor.panelWin;
let { Chart } = windowRequire("devtools/client/shared/widgets/Chart");
let pie = Chart.Pie(document, {
width: 100,

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

@ -14,8 +14,8 @@ add_task(function* () {
let { monitor } = yield initNetMonitor(SIMPLE_URL);
info("Starting test... ");
let { document, NetMonitorView } = monitor.panelWin;
let { Chart } = NetMonitorView.Statistics;
let { document, windowRequire } = monitor.panelWin;
let { Chart } = windowRequire("devtools/client/shared/widgets/Chart");
let pie = Chart.Pie(document, {
data: null,

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

@ -13,8 +13,8 @@ add_task(function* () {
let { monitor } = yield initNetMonitor(SIMPLE_URL);
info("Starting test... ");
let { document, NetMonitorView } = monitor.panelWin;
let { Chart } = NetMonitorView.Statistics;
let { document, windowRequire } = monitor.panelWin;
let { Chart } = windowRequire("devtools/client/shared/widgets/Chart");
let table = Chart.Table(document, {
title: "Table title",

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

@ -14,8 +14,8 @@ add_task(function* () {
let { monitor } = yield initNetMonitor(SIMPLE_URL);
info("Starting test... ");
let { document, NetMonitorView } = monitor.panelWin;
let { Chart } = NetMonitorView.Statistics;
let { document, windowRequire } = monitor.panelWin;
let { Chart } = windowRequire("devtools/client/shared/widgets/Chart");
let table = Chart.Table(document, {
title: "Table title",

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