This commit is contained in:
Wes Kocher 2016-09-15 16:40:23 -07:00
Родитель 395fa9e2ed 447769a520
Коммит 9013078b1e
87 изменённых файлов: 3308 добавлений и 823 удалений

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

@ -192,7 +192,6 @@ devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
devtools/server/tests/unit/setBreakpoint*
# mobile/android/ exclusions
mobile/android/chrome/content
mobile/android/tests/
# Uses `#filter substitution`
@ -208,6 +207,7 @@ mobile/android/installer/
mobile/android/locales/
# Non-standard `(catch ex if ...)`
mobile/android/chrome/content/browser.js
mobile/android/components/Snippets.js
# Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression"

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

@ -104,7 +104,7 @@ tasks:
--pushlog-id='{{pushlog_id}}'
--pushdate='{{pushdate}}'
--project='{{project}}'
--message='{{comment}}'
--message={{#shellquote}}{{{comment}}}{{/shellquote}}
--owner='{{owner}}'
--level='{{level}}'
--base-repository='https://hg.mozilla.org/mozilla-central'

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

@ -1517,4 +1517,9 @@ pref("browser.crashReports.unsubmittedCheck.enabled", false);
pref("browser.crashReports.unsubmittedCheck.enabled", true);
#endif
// chancesUntilSuppress is how many times we'll show the unsubmitted
// crash report notification across different days and shutdown
// without a user choice before we suppress the notification for
// some number of days.
pref("browser.crashReports.unsubmittedCheck.chancesUntilSuppress", 4);
pref("browser.crashReports.unsubmittedCheck.autoSubmit", false);

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

@ -355,6 +355,7 @@ skip-if = buildapp == 'mulet'
[browser_page_style_menu.js]
[browser_page_style_menu_update.js]
[browser_parsable_css.js]
skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug
[browser_parsable_script.js]
skip-if = asan || (os == 'linux' && !debug && (bits == 32)) # disabled on asan because of timeouts, and bug 1172468 for the linux 32-bit pgo issue.
[browser_permissions.js]

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

@ -33,6 +33,38 @@ let whitelist = [
isFromDevTools: true},
];
// Platform can be "linux", "macosx" or "win". If omitted, the exception applies to all platforms.
let allowedImageReferences = [
// Bug 1302759
{file: "chrome://browser/skin/customizableui/customize-titleBar-toggle.png",
from: "chrome://browser/skin/browser.css",
platforms: ["linux"],
isFromDevTools: false},
{file: "chrome://browser/skin/customizableui/customize-titleBar-toggle@2x.png",
from: "chrome://browser/skin/browser.css",
platforms: ["linux"],
isFromDevTools: false},
// Bug 1302691
{file: "chrome://devtools/skin/images/dock-bottom-minimize@2x.png",
from: "chrome://devtools/skin/toolbox.css",
isFromDevTools: true},
{file: "chrome://devtools/skin/images/dock-bottom-maximize@2x.png",
from: "chrome://devtools/skin/toolbox.css",
isFromDevTools: true},
// Bug 1302708
{file: "chrome/devtools/modules/devtools/client/themes/images/filter.svg",
from: "chrome/devtools/modules/devtools/client/themes/common.css",
isFromDevTools: true},
// Bug 1302890
{file: "chrome://global/skin/icons/warning-32.png",
from: "chrome://devtools/skin/tooltips.css",
platforms: ["linux", "win"],
isFromDevTools: true},
];
var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
var {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
@ -163,6 +195,65 @@ function messageIsCSSError(msg) {
return false;
}
let imageURIsToReferencesMap = new Map();
function processCSSRules(sheet) {
for (let rule of sheet.cssRules) {
if (rule instanceof CSSMediaRule) {
processCSSRules(rule);
continue;
}
if (!(rule instanceof CSSStyleRule))
continue;
// Extract urls from the css text.
// Note: CSSStyleRule.cssText always has double quotes around URLs even
// when the original CSS file didn't.
let urls = rule.cssText.match(/url\("[^"]*"\)/g);
if (!urls)
continue;
for (let url of urls) {
// Remove the url(" prefix and the ") suffix.
url = url.replace(/url\("(.*)"\)/, "$1");
if (url.startsWith("data:"))
continue;
// Make the url absolute and remove the ref.
let baseURI = Services.io.newURI(rule.parentStyleSheet.href, null, null);
url = Services.io.newURI(url, null, baseURI).specIgnoringRef;
// Store the image url along with the css file referencing it.
let baseUrl = baseURI.spec.split("?always-parse-css")[0];
if (!imageURIsToReferencesMap.has(url)) {
imageURIsToReferencesMap.set(url, new Set([baseUrl]));
} else {
imageURIsToReferencesMap.get(url).add(baseUrl);
}
}
}
}
function chromeFileExists(aURI)
{
let available = 0;
try {
let channel = NetUtil.newChannel({uri: aURI, loadUsingSystemPrincipal: true});
let stream = channel.open();
let sstream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
sstream.init(stream);
available = sstream.available();
sstream.close();
} catch (e) {
if (e.result != Components.results.NS_ERROR_FILE_NOT_FOUND) {
dump("Checking " + aURI + ": " + e + "\n");
Cu.reportError(e);
}
}
return available > 0;
}
add_task(function* checkAllTheCSS() {
let appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
// This asynchronously produces a list of URLs (sadly, mostly sync on our
@ -209,6 +300,7 @@ add_task(function* checkAllTheCSS() {
linkEl.setAttribute("rel", "stylesheet");
let promiseForThisSpec = Promise.defer();
let onLoad = (e) => {
processCSSRules(linkEl.sheet);
promiseForThisSpec.resolve();
linkEl.removeEventListener("load", onLoad);
linkEl.removeEventListener("error", onError);
@ -231,6 +323,26 @@ add_task(function* checkAllTheCSS() {
// Wait for all the files to have actually loaded:
yield Promise.all(allPromises);
// Check if all the files referenced from CSS actually exist.
for (let [image, references] of imageURIsToReferencesMap) {
if (!chromeFileExists(image)) {
for (let ref of references) {
let ignored = false;
for (let item of allowedImageReferences) {
if (image.endsWith(item.file) && ref.endsWith(item.from) &&
isDevtools == item.isFromDevTools &&
(!item.platforms || item.platforms.includes(AppConstants.platform))) {
item.used = true;
ignored = true;
break;
}
}
if (!ignored)
ok(false, "missing " + image + " referenced from " + ref);
}
}
}
let messages = Services.console.getMessageArray();
// Count errors (the test output will list actual issues for us, as well
// as the ok(false) in messageIsCSSError.
@ -246,6 +358,16 @@ add_task(function* checkAllTheCSS() {
}
}
// Confirm that all file whitelist rules have been used.
for (let item of allowedImageReferences) {
if (!item.used && isDevtools == item.isFromDevTools &&
(!item.platforms || item.platforms.includes(AppConstants.platform))) {
ok(false, "Unused file whitelist item. " +
" file: " + item.file +
" from: " + item.from);
}
}
// Clean up to avoid leaks:
iframe.remove();
doc.head.innerHTML = '';
@ -253,4 +375,5 @@ add_task(function* checkAllTheCSS() {
iframe = null;
windowless.close();
windowless = null;
imageURIsToReferencesMap = null;
});

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

@ -87,18 +87,16 @@ add_task(function* () {
yield BrowserTestUtils.closeWindow(win1);
});
function* do_test_update(background) {
function* do_test_update(background, withPermissions = true) {
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
yield focusWindow(win1);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
},
background: background,
});
let manifest = {};
if (withPermissions) {
manifest.permissions = ["tabs"];
}
let extension = ExtensionTestUtils.loadExtension({manifest, background});
yield Promise.all([
yield extension.startup(),
@ -177,4 +175,23 @@ add_task(function* test_url() {
});
});
add_task(function* test_without_tabs_permission() {
yield do_test_update(function background() {
browser.tabs.create({url: "about:blank"}, function(tab) {
browser.tabs.onUpdated.addListener(function onUpdated(tabId, changeInfo) {
if (tabId == tab.id) {
browser.test.assertFalse("url" in changeInfo, "url should not be included without tabs permission");
browser.test.assertFalse("favIconUrl" in changeInfo, "favIconUrl should not be included without tabs permission");
if (changeInfo.status == "complete") {
browser.tabs.onUpdated.removeListener(onUpdated);
browser.tabs.remove(tabId);
browser.test.notifyPass("finish");
}
}
});
});
}, false /* withPermissions */);
});
add_task(forceGC);

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

@ -143,18 +143,11 @@ var gMainPane = {
let buttonIndex = confirmRestartPrompt(e10sCheckbox.checked, 0,
true, false);
if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
const Cc = Components.classes, Ci = Components.interfaces;
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
if (!cancelQuit.data) {
for (let prefToChange of prefsToChange) {
prefToChange.value = e10sCheckbox.checked;
}
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
for (let prefToChange of prefsToChange) {
prefToChange.value = e10sCheckbox.checked;
}
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
}
// Revert the checkbox in case we didn't quit

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

@ -242,5 +242,17 @@ function confirmRestartPrompt(aRestartToEnable, aDefaultButtonIndex,
let buttonIndex = prompts.confirmEx(window, title, msg, buttonFlags,
button0Text, button1Text, button2Text,
null, {});
// If we have the second confirmation dialog for restart, see if the user
// cancels out at that point.
if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
if (cancelQuit.data) {
buttonIndex = CONFIRM_RESTART_PROMPT_CANCEL;
}
}
return buttonIndex;
}

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

@ -439,18 +439,11 @@ var gPrivacyPane = {
let buttonIndex = confirmRestartPrompt(autoStart.checked, 1,
true, false);
if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
const Cc = Components.classes, Ci = Components.interfaces;
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
"restart");
if (!cancelQuit.data) {
pref.value = autoStart.hasAttribute('checked');
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
.getService(Ci.nsIAppStartup);
appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
return;
}
pref.value = autoStart.hasAttribute('checked');
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
.getService(Ci.nsIAppStartup);
appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
return;
}
this._shouldPromptForRestart = false;

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

@ -277,7 +277,7 @@
<checkbox id="openpageSuggestion" label="&locbar.openpage.label;"
accesskey="&locbar.openpage.accesskey;"
preference="browser.urlbar.suggest.openpage"/>
<label class="text-link" onclick="if (event.button == 0) gotoPref('search')">
<label class="text-link" onclick="gotoPref('search')">
&suggestionSettings.label;
</label>
</groupbox>

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

@ -7,6 +7,7 @@
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
var Cr = Components.results;
this.EXPORTED_SYMBOLS = [ "TabCrashHandler",
"PluginCrashReporter",
@ -38,6 +39,8 @@ XPCOMUtils.defineLazyGetter(this, "gNavigatorBundle", function() {
// We don't process crash reports older than 28 days, so don't bother
// submitting them
const PENDING_CRASH_REPORT_DAYS = 28;
const DAY = 24 * 60 * 60 * 1000; // milliseconds
const DAYS_TO_SUPPRESS = 30;
this.TabCrashHandler = {
_crashedTabCount: 0,
@ -344,6 +347,23 @@ this.TabCrashHandler = {
* the user has opted in.
*/
this.UnsubmittedCrashHandler = {
get prefs() {
delete this.prefs;
return this.prefs =
Services.prefs.getBranch("browser.crashReports.unsubmittedCheck.");
},
// showingNotification is set to true once a notification
// is successfully shown, and then set back to false if
// the notification is dismissed by an action by the user.
showingNotification: false,
// suppressed is true if we've determined that we've shown
// the notification too many times across too many days without
// user interaction, so we're suppressing the notification for
// some number of days. See the documentation for
// shouldShowPendingSubmissionsNotification().
suppressed: false,
init() {
if (this.initialized) {
return;
@ -351,22 +371,71 @@ this.UnsubmittedCrashHandler = {
this.initialized = true;
let pref = "browser.crashReports.unsubmittedCheck.enabled";
let shouldCheck = Services.prefs.getBoolPref(pref);
let shouldCheck = this.prefs.getBoolPref("enabled");
if (shouldCheck) {
if (this.prefs.prefHasUserValue("suppressUntilDate")) {
if (this.prefs.getCharPref("suppressUntilDate") > this.dateString()) {
// We'll be suppressing any notifications until after suppressedDate,
// so there's no need to do anything more.
this.suppressed = true;
return;
}
// We're done suppressing, so we don't need this pref anymore.
this.prefs.clearUserPref("suppressUntilDate");
}
Services.obs.addObserver(this, "browser-delayed-startup-finished",
false);
Services.obs.addObserver(this, "profile-before-change",
false);
}
},
observe(subject, topic, data) {
if (topic != "browser-delayed-startup-finished") {
uninit() {
if (!this.initialized) {
return;
}
Services.obs.removeObserver(this, topic);
this.checkForUnsubmittedCrashReports();
this.initialized = false;
if (this.suppressed) {
this.suppressed = false;
// No need to do any more clean-up, since we were suppressed.
return;
}
if (this.showingNotification) {
this.prefs.setBoolPref("shutdownWhileShowing", true);
this.showingNotification = false;
}
try {
Services.obs.removeObserver(this, "browser-delayed-startup-finished");
} catch (e) {
// The browser-delayed-startup-finished observer might have already
// fired and removed itself, so if this fails, it's okay.
if (e.result != Cr.NS_ERROR_FAILURE) {
throw e;
}
}
Services.obs.removeObserver(this, "profile-before-change");
},
observe(subject, topic, data) {
switch (topic) {
case "browser-delayed-startup-finished": {
Services.obs.removeObserver(this, topic);
this.checkForUnsubmittedCrashReports();
break;
}
case "profile-before-change": {
this.uninit();
break;
}
}
},
/**
@ -395,13 +464,61 @@ this.UnsubmittedCrashHandler = {
if (reportIDs.length) {
if (CrashNotificationBar.autoSubmit) {
CrashNotificationBar.submitReports(reportIDs);
} else {
} else if (this.shouldShowPendingSubmissionsNotification()) {
return this.showPendingSubmissionsNotification(reportIDs);
}
}
return null;
}),
/**
* Returns true if the notification should be shown.
* shouldShowPendingSubmissionsNotification makes this decision
* by looking at whether or not the user has seen the notification
* over several days without ever interacting with it. If this occurs
* too many times, we suppress the notification for DAYS_TO_SUPPRESS
* days.
*
* @returns bool
*/
shouldShowPendingSubmissionsNotification() {
if (!this.prefs.prefHasUserValue("shutdownWhileShowing")) {
return true;
}
let shutdownWhileShowing = this.prefs.getBoolPref("shutdownWhileShowing");
this.prefs.clearUserPref("shutdownWhileShowing");
if (!this.prefs.prefHasUserValue("lastShownDate")) {
// This isn't expected, but we're being defensive here. We'll
// opt for showing the notification in this case.
return true;
}
let lastShownDate = this.prefs.getCharPref("lastShownDate");
if (this.dateString() > lastShownDate && shutdownWhileShowing) {
// We're on a newer day then when we last showed the
// notification without closing it. We don't want to do
// this too many times, so we'll decrement a counter for
// this situation. Too many of these, and we'll assume the
// user doesn't know or care about unsubmitted notifications,
// and we'll suppress the notification for a while.
let chances = this.prefs.getIntPref("chancesUntilSuppress");
if (--chances < 0) {
// We're out of chances!
this.prefs.clearUserPref("chancesUntilSuppress");
// We'll suppress for DAYS_TO_SUPPRESS days.
let suppressUntil =
this.dateString(new Date(Date.now() + (DAY * DAYS_TO_SUPPRESS)));
this.prefs.setCharPref("suppressUntilDate", suppressUntil);
return false;
}
this.prefs.setIntPref("chancesUntilSuppress", chances);
}
return true;
},
/**
* Given an array of unsubmitted crash report IDs, try to open
* up a notification asking the user to submit them.
@ -421,11 +538,34 @@ this.UnsubmittedCrashHandler = {
let message = PluralForm.get(count, messageTemplate).replace("#1", count);
return CrashNotificationBar.show({
let notification = CrashNotificationBar.show({
notificationID: "pending-crash-reports",
message,
reportIDs,
onAction: () => {
this.showingNotification = false;
},
});
if (notification) {
this.showingNotification = true;
this.prefs.setCharPref("lastShownDate", this.dateString());
}
return notification;
},
/**
* Returns a string representation of a Date in the format
* YYYYMMDD.
*
* @param someDate (Date, optional)
* The Date to convert to the string. If not provided,
* defaults to today's date.
* @returns String
*/
dateString(someDate = new Date()) {
return someDate.toLocaleFormat("%Y%m%d");
},
};
@ -452,9 +592,15 @@ this.CrashNotificationBar = {
*
* reportIDs (Array<string>)
* The array of report IDs to offer to the user.
*
* onAction (function, optional)
* A callback to fire once the user performs an
* action on the notification bar (this includes
* dismissing the notification).
*
* @returns The <xul:notification> if one is shown. null otherwise.
*/
show({ notificationID, message, reportIDs }) {
show({ notificationID, message, reportIDs, onAction }) {
let chromeWin = RecentWindow.getMostRecentBrowserWindow();
if (!chromeWin) {
// Can't show a notification in this case. We'll hopefully
@ -473,6 +619,9 @@ this.CrashNotificationBar = {
label: gNavigatorBundle.GetStringFromName("pendingCrashReports.send"),
callback: () => {
this.submitReports(reportIDs);
if (onAction) {
onAction();
}
},
},
{
@ -480,6 +629,9 @@ this.CrashNotificationBar = {
callback: () => {
this.autoSubmit = true;
this.submitReports(reportIDs);
if (onAction) {
onAction();
}
},
},
{
@ -499,6 +651,9 @@ this.CrashNotificationBar = {
reportIDs.forEach(function(reportID) {
CrashSubmit.ignore(reportID);
});
if (onAction) {
onAction();
}
}
};

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

@ -198,6 +198,12 @@ add_task(function* setup() {
let oldServerURL = env.get("MOZ_CRASHREPORTER_URL");
env.set("MOZ_CRASHREPORTER_URL", SERVER_URL);
yield SpecialPowers.pushPrefEnv({
set: [
["browser.crashReports.unsubmittedCheck.enabled", true],
],
});
registerCleanupFunction(function() {
gNotificationBox = null;
clearPendingCrashReports();
@ -417,3 +423,244 @@ add_task(function* test_can_ignore() {
clearPendingCrashReports();
});
/**
* Tests that if the notification is shown, then the
* lastShownDate is set for today.
*/
add_task(function* test_last_shown_date() {
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
let today = new Date().toLocaleFormat("%Y%m%d");
let lastShownDate =
UnsubmittedCrashHandler.prefs.getCharPref("lastShownDate");
Assert.equal(today, lastShownDate,
"Last shown date should be today.");
UnsubmittedCrashHandler.prefs.clearUserPref("lastShownDate");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if UnsubmittedCrashHandler is uninit with a
* notification still being shown, that
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* set to true.
*/
add_task(function* test_shutdown_while_showing() {
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
UnsubmittedCrashHandler.uninit();
let shutdownWhileShowing =
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
Assert.ok(shutdownWhileShowing,
"We should have noticed that we uninitted while showing " +
"the notification.");
UnsubmittedCrashHandler.prefs.clearUserPref("shutdownWhileShowing");
UnsubmittedCrashHandler.init();
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if UnsubmittedCrashHandler is uninit after
* the notification has been closed, that
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* not set in prefs.
*/
add_task(function* test_shutdown_while_not_showing() {
let reportIDs = yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
// Dismiss the notification by clicking on the "X" button.
let anonyNodes = document.getAnonymousNodes(notification)[0];
let closeButton = anonyNodes.querySelector(".close-icon");
closeButton.click();
yield waitForIgnoredReports(reportIDs);
UnsubmittedCrashHandler.uninit();
Assert.throws(() => {
let shutdownWhileShowing =
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
}, "We should have noticed that the notification had closed before " +
"uninitting.");
UnsubmittedCrashHandler.init();
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* set and the lastShownDate is today, then we don't decrement
* browser.crashReports.unsubmittedCheck.chancesUntilSuppress.
*/
add_task(function* test_dont_decrement_chances_on_same_day() {
let initChances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.ok(initChances > 1, "We should start with at least 1 chance.");
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
UnsubmittedCrashHandler.uninit();
gNotificationBox.removeNotification(notification, true);
let shutdownWhileShowing =
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
Assert.ok(shutdownWhileShowing,
"We should have noticed that we uninitted while showing " +
"the notification.");
let today = new Date().toLocaleFormat("%Y%m%d");
let lastShownDate =
UnsubmittedCrashHandler.prefs.getCharPref("lastShownDate");
Assert.equal(today, lastShownDate,
"Last shown date should be today.");
UnsubmittedCrashHandler.init();
notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should still be a notification");
let chances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.equal(initChances, chances,
"We should not have decremented chances.");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if
* browser.crashReports.unsubmittedCheck.shutdownWhileShowing is
* set and the lastShownDate is before today, then we decrement
* browser.crashReports.unsubmittedCheck.chancesUntilSuppress.
*/
add_task(function* test_decrement_chances_on_other_day() {
let initChances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.ok(initChances > 1, "We should start with at least 1 chance.");
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should be a notification");
UnsubmittedCrashHandler.uninit();
gNotificationBox.removeNotification(notification, true);
let shutdownWhileShowing =
UnsubmittedCrashHandler.prefs.getBoolPref("shutdownWhileShowing");
Assert.ok(shutdownWhileShowing,
"We should have noticed that we uninitted while showing " +
"the notification.");
// Now pretend that the notification was shown yesterday.
let yesterday = new Date(Date.now() - DAY).toLocaleFormat("%Y%m%d");
UnsubmittedCrashHandler.prefs.setCharPref("lastShownDate", yesterday);
UnsubmittedCrashHandler.init();
notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.ok(notification, "There should still be a notification");
let chances =
UnsubmittedCrashHandler.prefs.getIntPref("chancesUntilSuppress");
Assert.equal(initChances - 1, chances,
"We should have decremented our chances.");
UnsubmittedCrashHandler.prefs.clearUserPref("chancesUntilSuppress");
gNotificationBox.removeNotification(notification, true);
clearPendingCrashReports();
});
/**
* Tests that if we've shutdown too many times showing the
* notification, and we've run out of chances, then
* browser.crashReports.unsubmittedCheck.suppressUntilDate is
* set for some days into the future.
*/
add_task(function* test_can_suppress_after_chances() {
// Pretend that a notification was shown yesterday.
let yesterday = new Date(Date.now() - DAY).toLocaleFormat("%Y%m%d");
UnsubmittedCrashHandler.prefs.setCharPref("lastShownDate", yesterday);
UnsubmittedCrashHandler.prefs.setBoolPref("shutdownWhileShowing", true);
UnsubmittedCrashHandler.prefs.setIntPref("chancesUntilSuppress", 0);
yield createPendingCrashReports(1);
let notification =
yield UnsubmittedCrashHandler.checkForUnsubmittedCrashReports();
Assert.equal(notification, null,
"There should be no notification if we've run out of chances");
// We should have set suppressUntilDate into the future
let suppressUntilDate =
UnsubmittedCrashHandler.prefs.getCharPref("suppressUntilDate");
let today = new Date().toLocaleFormat("%Y%m%d");
Assert.ok(suppressUntilDate > today,
"We should be suppressing until some days into the future.");
UnsubmittedCrashHandler.prefs.clearUserPref("chancesUntilSuppress");
UnsubmittedCrashHandler.prefs.clearUserPref("suppressUntilDate");
UnsubmittedCrashHandler.prefs.clearUserPref("lastShownDate");
clearPendingCrashReports();
});
/**
* Tests that if there's a suppression date set, then no notification
* will be shown even if there are pending crash reports.
*/
add_task(function* test_suppression() {
let future = new Date(Date.now() + (DAY * 5)).toLocaleFormat("%Y%m%d");
UnsubmittedCrashHandler.prefs.setCharPref("suppressUntilDate", future);
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
Assert.ok(UnsubmittedCrashHandler.suppressed,
"The UnsubmittedCrashHandler should be suppressed.");
UnsubmittedCrashHandler.prefs.clearUserPref("suppressUntilDate");
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
});
/**
* Tests that if there's a suppression date set, but we've exceeded
* it, then we can show the notification again.
*/
add_task(function* test_end_suppression() {
let yesterday = new Date(Date.now() - DAY).toLocaleFormat("%Y%m%d");
UnsubmittedCrashHandler.prefs.setCharPref("suppressUntilDate", yesterday);
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
Assert.ok(!UnsubmittedCrashHandler.suppressed,
"The UnsubmittedCrashHandler should not be suppressed.");
Assert.ok(!UnsubmittedCrashHandler.prefs.prefHasUserValue("suppressUntilDate"),
"The suppression date should been cleared from preferences.");
UnsubmittedCrashHandler.uninit();
UnsubmittedCrashHandler.init();
});

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

@ -115,6 +115,7 @@
skin/classic/browser/tabbrowser/tab-overflow-indicator.png (../shared/tabbrowser/tab-overflow-indicator.png)
skin/classic/browser/theme-switcher-icon.png (../shared/theme-switcher-icon.png)
skin/classic/browser/theme-switcher-icon@2x.png (../shared/theme-switcher-icon@2x.png)
skin/classic/browser/toolbarbutton-dropdown-arrow.png (../shared/toolbarbutton-dropdown-arrow.png)
skin/classic/browser/translating-16.png (../shared/translation/translating-16.png)
skin/classic/browser/translating-16@2x.png (../shared/translation/translating-16@2x.png)
skin/classic/browser/translation-16.png (../shared/translation/translation-16.png)

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

@ -52,7 +52,7 @@
.messageImage[value="plugin-hidden"] {
list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin);
filter: url(chrome://browser/skin/filters.svg#fill);
fill: currentColor;
fill: #808080;
}
/* Keep any changes to this style in sync with pluginProblem.css */

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

До

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

После

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

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

@ -59,7 +59,6 @@ browser.jar:
skin/classic/browser/Toolbar-win8.png
skin/classic/browser/Toolbar-win8@2x.png
skin/classic/browser/Toolbar-XP.png
skin/classic/browser/toolbarbutton-dropdown-arrow.png
skin/classic/browser/toolbarbutton-dropdown-arrow-XPVista7.png
skin/classic/browser/toolbarbutton-dropdown-arrow-inverted.png
skin/classic/browser/urlbar-popup-blocked.png

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

@ -55,6 +55,6 @@ add_task(function* () {
let img = document.querySelector(imgClass);
ok(img, "warning message is rendered");
yield closeAboutDebugging(tab, win);
yield closeAboutDebugging(tab);
win.close();
});

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

@ -21,7 +21,7 @@ add_task(function* () {
// Open a new tab in background and wait for its addition in the UI
let onNewTab = waitForMutation(tabsElement, { childList: true });
let newTab = yield addTab(TAB_URL, null, true);
let newTab = yield addTab(TAB_URL, { background: true });
yield onNewTab;
// Check that the new tab appears in the UI, but with an empty name

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

@ -31,7 +31,7 @@ function* openAboutDebugging(page, win) {
url += "#" + page;
}
let tab = yield addTab(url, win);
let tab = yield addTab(url, { window: win });
let browser = tab.linkedBrowser;
let document = browser.contentDocument;
@ -63,49 +63,9 @@ function openPanel(document, panelId) {
document.querySelector(".main-content"), {childList: true});
}
function closeAboutDebugging(tab, win) {
function closeAboutDebugging(tab) {
info("Closing about:debugging");
return removeTab(tab, win);
}
function addTab(url, win, backgroundTab = false) {
info("Adding tab: " + url);
return new Promise(done => {
let targetWindow = win || window;
let targetBrowser = targetWindow.gBrowser;
targetWindow.focus();
let tab = targetBrowser.addTab(url);
if (!backgroundTab) {
targetBrowser.selectedTab = tab;
}
let linkedBrowser = tab.linkedBrowser;
BrowserTestUtils.browserLoaded(linkedBrowser)
.then(function () {
info("Tab added and finished loading: " + url);
done(tab);
});
});
}
function removeTab(tab, win) {
info("Removing tab.");
return new Promise(done => {
let targetWindow = win || window;
let targetBrowser = targetWindow.gBrowser;
let tabContainer = targetBrowser.tabContainer;
tabContainer.addEventListener("TabClose", function onClose() {
tabContainer.removeEventListener("TabClose", onClose, false);
info("Tab removed and finished closing.");
done();
}, false);
targetBrowser.removeTab(tab);
});
return removeTab(tab);
}
function getSupportsFile(path) {

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

@ -1,4 +1,4 @@
// Generated from: 02b44328ac19e43705f51209237b20fb264f93f4 Merge pull request #711 from devtools-html/cleanup
// Generated from: 30002d3cfc4341840af847af9eb2c31cab18abb5 Move some of editor-select.js test into editor-highlight.js to make tests more focused (and avoid timeouts on linux debug) (#746)
var Debugger =
/******/ (function(modules) { // webpackBootstrap
@ -21282,8 +21282,8 @@ var Debugger =
var State = makeRecord({
sources: I.Map(),
selectedSource: undefined,
pendingSelectedSourceURL: undefined,
selectedLocation: undefined,
pendingSelectedLocation: undefined,
sourcesText: I.Map(),
sourceMaps: I.Map(),
tabs: I.List([])
@ -21312,19 +21312,22 @@ var Debugger =
break;
case "SELECT_SOURCE":
return state.merge({
selectedSource: action.source,
pendingSelectedSourceURL: null,
tabs: updateTabList(state, fromJS(action.source), action.options)
return state.set("selectedLocation", {
sourceId: action.source.id,
line: action.line
}).set("pendingSelectedLocation", null).merge({
tabs: updateTabList(state, fromJS(action.source), action.tabIndex)
});
case "SELECT_SOURCE_URL":
return state.merge({ pendingSelectedSourceURL: action.url });
return state.set("pendingSelectedLocation", {
url: action.url,
line: action.line
});
case "CLOSE_TAB":
return state.merge({
selectedSource: getNewSelectedSource(state, action.id),
tabs: removeSourceFromTabList(state, action.id)
return state.merge({ tabs: removeSourceFromTabList(state, action.id) }).set("selectedLocation", {
sourceId: getNewSelectedSourceId(state, action.id)
});
case "LOAD_SOURCE_TEXT":
@ -21359,9 +21362,9 @@ var Debugger =
return _updateText(state, action, [action.originalSource]);
case "NAVIGATE":
var source = state.selectedSource;
var sourceUrl = source && source.get("url");
return State().set("pendingSelectedSourceURL", sourceUrl);
var source = getSelectedSource({ sources: state });
var _url = source && source.get("url");
return State().set("pendingSelectedLocation", { url: _url });
}
return state;
@ -21402,16 +21405,16 @@ var Debugger =
/*
* Adds the new source to the tab list if it is not already there
*/
function updateTabList(state, source, options) {
function updateTabList(state, source, tabIndex) {
var tabs = state.get("tabs");
var selectedSource = state.get("selectedSource");
var selectedSource = getSelectedSource({ sources: state });
var selectedSourceIndex = tabs.indexOf(selectedSource);
var sourceIndex = tabs.indexOf(source);
var includesSource = !!tabs.find(t => t.get("id") == source.get("id"));
if (includesSource) {
if (options.position != undefined) {
return tabs.delete(sourceIndex).insert(options.position, source);
if (tabIndex != undefined) {
return tabs.delete(sourceIndex).insert(tabIndex, source);
}
return tabs;
@ -21423,13 +21426,13 @@ var Debugger =
/**
* Gets the next tab to select when a tab closes.
*/
function getNewSelectedSource(state, id) {
function getNewSelectedSourceId(state, id) {
var tabs = state.get("tabs");
var selectedSource = state.get("selectedSource");
var selectedSource = getSelectedSource({ sources: state });
// if we're not closing the selected tab return the selected tab
if (selectedSource.get("id") != id) {
return selectedSource;
return selectedSource.get("id");
}
var tabIndex = tabs.findIndex(tab => tab.get("id") == id);
@ -21441,11 +21444,11 @@ var Debugger =
// if we're closing the last tab, select the penultimate tab
if (tabIndex + 1 == numTabs) {
return tabs.get(tabIndex - 1);
return tabs.get(tabIndex - 1).get("id");
}
// return the next tab
return tabs.get(tabIndex + 1);
return tabs.get(tabIndex + 1).get("id");
}
// Selectors
@ -21484,11 +21487,15 @@ var Debugger =
}
function getSelectedSource(state) {
return state.sources.selectedSource;
return state.sources.selectedLocation && getSource(state, state.sources.selectedLocation.sourceId);
}
function getPendingSelectedSourceURL(state) {
return state.sources.pendingSelectedSourceURL;
function getSelectedLocation(state) {
return state.sources.selectedLocation;
}
function getPendingSelectedLocation(state) {
return state.sources.pendingSelectedLocation;
}
function getSourceMap(state, sourceId) {
@ -21514,7 +21521,8 @@ var Debugger =
getSourceText,
getSourceTabs,
getSelectedSource,
getPendingSelectedSourceURL,
getSelectedLocation,
getPendingSelectedLocation,
getSourceMap,
getPrettySource
};
@ -26884,11 +26892,10 @@ var Debugger =
switch (action.type) {
case constants.PAUSED:
if (action.status == "done") {
var _action$value = action.value;
var selectedFrameId = _action$value.selectedFrameId;
var frames = _action$value.frames;
var pauseInfo = _action$value.pauseInfo;
{
var selectedFrameId = action.selectedFrameId;
var frames = action.frames;
var pauseInfo = action.pauseInfo;
pauseInfo.isInterrupted = pauseInfo.why.type === "interrupted";
@ -26900,7 +26907,6 @@ var Debugger =
});
}
break;
case constants.RESUME:
return state.merge({
pause: null,
@ -27071,7 +27077,8 @@ var Debugger =
getSourceText: sources.getSourceText,
getSourceTabs: sources.getSourceTabs,
getSelectedSource: sources.getSelectedSource,
getPendingSelectedSourceURL: sources.getPendingSelectedSourceURL,
getSelectedLocation: sources.getSelectedLocation,
getPendingSelectedLocation: sources.getPendingSelectedLocation,
getSourceMap: sources.getSourceMap,
getPrettySource: sources.getPrettySource,
@ -28766,7 +28773,7 @@ var Debugger =
},
onKeyDown(e) {
if (e.key === "Escape") {
if (this.state.searchOn && e.key === "Escape") {
this.setState({ searchOn: false });
e.preventDefault();
}
@ -30166,7 +30173,7 @@ var Debugger =
var getSource = _require9.getSource;
var getSourceByURL = _require9.getSourceByURL;
var getSourceText = _require9.getSourceText;
var getPendingSelectedSourceURL = _require9.getPendingSelectedSourceURL;
var getPendingSelectedLocation = _require9.getPendingSelectedLocation;
var getSourceMap = _require9.getSourceMap;
var getSourceMapURL = _require9.getSourceMapURL;
var getFrames = _require9.getFrames;
@ -30196,9 +30203,9 @@ var Debugger =
// If a request has been made to show this source, go ahead and
// select it.
var pendingURL = getPendingSelectedSourceURL(getState());
if (pendingURL === source.url) {
dispatch(selectSource(source.id));
var pendingLocation = getPendingSelectedLocation(getState());
if (pendingLocation && pendingLocation.url === source.url) {
dispatch(selectSource(source.id, { line: pendingLocation.line }));
}
};
}
@ -30246,17 +30253,21 @@ var Debugger =
* @static
*/
function selectSourceURL(url) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
return _ref7 => {
var dispatch = _ref7.dispatch;
var getState = _ref7.getState;
var source = getSourceByURL(getState(), url);
if (source) {
dispatch(selectSource(source.get("id")));
dispatch(selectSource(source.get("id"), options));
} else {
dispatch({
type: constants.SELECT_SOURCE_URL,
url: url
url: url,
tabIndex: options.tabIndex,
line: options.line
});
}
};
@ -30288,7 +30299,8 @@ var Debugger =
dispatch({
type: constants.SELECT_SOURCE,
source: source,
options
tabIndex: options.tabIndex,
line: options.line
});
};
}
@ -30767,31 +30779,31 @@ var Debugger =
* @static
*/
function paused(pauseInfo) {
return _ref2 => {
var dispatch = _ref2.dispatch;
var getState = _ref2.getState;
var client = _ref2.client;
var frame = pauseInfo.frame;
var frames = pauseInfo.frames;
var why = pauseInfo.why;
return (() => {
var _ref2 = _asyncToGenerator(function* (_ref3) {
var dispatch = _ref3.dispatch;
var getState = _ref3.getState;
var client = _ref3.client;
var frame = pauseInfo.frame;
var frames = pauseInfo.frames;
var why = pauseInfo.why;
frames = yield updateFrameLocations(getState(), frames);
dispatch(evaluateExpressions());
return dispatch({
type: constants.PAUSED,
[PROMISE]: _asyncToGenerator(function* () {
frames = yield updateFrameLocations(getState(), frames);
dispatch(selectSource(frame.location.sourceId));
return {
pauseInfo: { why, frame },
frames: frames,
selectedFrameId: frame.id
};
})()
dispatch(evaluateExpressions());
dispatch({
type: constants.PAUSED,
pauseInfo: { why, frame },
frames: frames,
selectedFrameId: frame.id
});
dispatch(selectSource(frame.location.sourceId, { line: frame.location.line }));
});
};
return function (_x) {
return _ref2.apply(this, arguments);
};
})();
}
/**
@ -32783,7 +32795,7 @@ var Debugger =
var getSourceText = _require4.getSourceText;
var getBreakpointsForSource = _require4.getBreakpointsForSource;
var getSelectedSource = _require4.getSelectedSource;
var getSelectedLocation = _require4.getSelectedLocation;
var getSelectedFrame = _require4.getSelectedFrame;
var _require5 = __webpack_require__(194);
@ -32798,8 +32810,8 @@ var Debugger =
__webpack_require__(264);
function isSourceForFrame(source, frame) {
return source && frame && frame.location.sourceId === source.get("id");
function isTextForSource(sourceText) {
return !sourceText.get("loading") && !sourceText.get("error");
}
/**
@ -32818,7 +32830,7 @@ var Debugger =
var Editor = React.createClass({
propTypes: {
breakpoints: ImPropTypes.map.isRequired,
selectedSource: ImPropTypes.map,
selectedLocation: PropTypes.object,
sourceText: PropTypes.object,
addBreakpoint: PropTypes.func,
removeBreakpoint: PropTypes.func,
@ -32838,11 +32850,11 @@ var Debugger =
if (bp) {
this.props.removeBreakpoint({
sourceId: this.props.selectedSource.get("id"),
sourceId: this.props.selectedLocation.sourceId,
line: line + 1
});
} else {
this.props.addBreakpoint({ sourceId: this.props.selectedSource.get("id"),
this.props.addBreakpoint({ sourceId: this.props.selectedLocation.sourceId,
line: line + 1 },
// Pass in a function to get line text because the breakpoint
// may slide and it needs to compute the value at the new
@ -32851,45 +32863,52 @@ var Debugger =
}
},
clearDebugLine(line) {
this.editor.codeMirror.removeLineClass(line - 1, "line", "debug-line");
updateDebugLine(prevProps, nextProps) {
if (prevProps.selectedFrame) {
var line = prevProps.selectedFrame.location.line;
this.editor.codeMirror.removeLineClass(line - 1, "line", "debug-line");
}
if (nextProps.selectedFrame) {
var _line = nextProps.selectedFrame.location.line;
this.editor.codeMirror.addLineClass(_line - 1, "line", "debug-line");
}
},
setDebugLine(line) {
this.editor.codeMirror.addLineClass(line - 1, "line", "debug-line");
highlightLine() {
if (!this.pendingJumpLine) {
return;
}
// If the location has changed and a specific line is requested,
// move to that line and flash it.
var codeMirror = this.editor.codeMirror;
// Make sure to clean up after ourselves. Not only does this
// cancel any existing animation, but it avoids it from
// happening ever again (in case CodeMirror re-applies the
// class, etc).
if (this.lastJumpLine) {
codeMirror.removeLineClass(this.lastJumpLine - 1, "line", "highlight-line");
}
var line = this.pendingJumpLine;
this.editor.alignLine(line);
},
setSourceText(newSourceText, oldSourceText) {
if (newSourceText.get("loading")) {
this.setText("Loading...");
return;
// We only want to do the flashing animation if it's not a debug
// line, which has it's own styling.
if (!this.props.selectedFrame || this.props.selectedFrame.location.line !== line) {
this.editor.codeMirror.addLineClass(line - 1, "line", "highlight-line");
}
if (newSourceText.get("error")) {
this.setText("Error");
console.error(newSourceText.get("error"));
return;
}
this.setText(newSourceText.get("text"));
this.setMode(newSourceText);
resizeBreakpointGutter(this.editor.codeMirror);
this.lastJumpLine = line;
this.pendingJumpLine = null;
},
// Only reset the editor text if the source has changed.
// * Resetting the text will remove the breakpoints.
// * Comparing the source text is probably inneficient.
setText(text) {
if (!text || !this.editor) {
return;
}
if (text == this.editor.getText()) {
return;
}
this.editor.setText(text);
},
@ -32940,24 +32959,52 @@ var Debugger =
},
componentWillReceiveProps(nextProps) {
// Clear the currently highlighted line
if (isSourceForFrame(this.props.selectedSource, this.props.selectedFrame)) {
this.clearDebugLine(this.props.selectedFrame.location.line);
// This lifecycle method is responsible for updating the editor
// text.
var sourceText = nextProps.sourceText;
if (!sourceText) {
this.setText("");
this.editor.setMode({ name: "text" });
} else if (!isTextForSource(sourceText)) {
// There are only 2 possible states: errored or loading. Do
// nothing except put a message in the editor.
this.setText(sourceText.get("error") || "Loading...");
this.editor.setMode({ name: "text" });
} else if (this.props.sourceText !== sourceText) {
// Only update it if the `sourceText` object has actually changed.
// It is immutable so it will always change when updated.
this.setText(sourceText.get("text"));
this.setMode(sourceText);
resizeBreakpointGutter(this.editor.codeMirror);
}
},
componentDidUpdate(prevProps) {
// This is in `componentDidUpdate` so helper functions can expect
// `this.props` to be the current props. This lifecycle method is
// responsible for updating the editor annotations.
var selectedLocation = this.props.selectedLocation;
// If the location is different and a new line is requested,
// update the pending jump line. Note that if jumping to a line in
// a source where the text hasn't been loaded yet, we will set the
// line here but not jump until rendering the actual source.
if (prevProps.selectedLocation !== selectedLocation) {
if (selectedLocation && selectedLocation.line != undefined) {
this.pendingJumpLine = selectedLocation.line;
} else {
this.pendingJumpLine = null;
}
}
// Set the source text. The source text may not have been loaded
// yet. On startup, the source text may not exist yet.
if (nextProps.sourceText) {
this.setSourceText(nextProps.sourceText, this.props.sourceText);
}
if (this.props.selectedSource && !nextProps.selectedSource) {
this.editor.setText("");
}
// Highlight the paused line if necessary
if (isSourceForFrame(nextProps.selectedSource, nextProps.selectedFrame)) {
this.setDebugLine(nextProps.selectedFrame.location.line);
// Only update and jump around in real source texts. This will
// keep the jump state around until the real source text is
// loaded.
if (this.props.sourceText && isTextForSource(this.props.sourceText)) {
this.updateDebugLine(prevProps, this.props);
this.highlightLine();
}
},
@ -32979,13 +33026,13 @@ var Debugger =
});
module.exports = connect((state, props) => {
var selectedSource = getSelectedSource(state);
var selectedId = selectedSource && selectedSource.get("id");
var selectedLocation = getSelectedLocation(state);
var sourceId = selectedLocation && selectedLocation.sourceId;
return {
selectedSource,
sourceText: getSourceText(state, selectedId),
breakpoints: getBreakpointsForSource(state, selectedId),
selectedLocation,
sourceText: getSourceText(state, sourceId),
breakpoints: getBreakpointsForSource(state, sourceId),
selectedFrame: getSelectedFrame(state)
};
}, dispatch => bindActionCreators(actions, dispatch))(Editor);
@ -33231,6 +33278,13 @@ var Debugger =
var Svg = __webpack_require__(234);
var ImPropTypes = __webpack_require__(227);
var _require5 = __webpack_require__(212);
var Services = _require5.Services;
var shiftKey = Services.appinfo.OS === "Darwin" ? "\u21E7" : "Shift+";
var ctrlKey = Services.appinfo.OS === "Linux" ? "Ctrl+" : "";
var actions = __webpack_require__(213);
var Breakpoints = React.createFactory(__webpack_require__(271));
var Expressions = React.createFactory(__webpack_require__(274));
@ -33306,8 +33360,8 @@ var Debugger =
this.keyShortcutsEnabled = true;
keyShortcuts.on("F8", this.resume);
keyShortcuts.on("F10", this.stepOver);
keyShortcuts.on("F11", this.stepIn);
keyShortcuts.on("F12", this.stepOut);
keyShortcuts.on(`${ ctrlKey }F11`, this.stepIn);
keyShortcuts.on(`${ ctrlKey }Shift+F11`, this.stepOut);
},
componentWillUnmount() {
@ -33315,8 +33369,8 @@ var Debugger =
keyShortcuts.off("F8", this.resume);
keyShortcuts.off("F10", this.stepOver);
keyShortcuts.off("F11", this.stepIn);
keyShortcuts.off("F12", this.stepOut);
keyShortcuts.off(`${ ctrlKey }F11`, this.stepIn);
keyShortcuts.off(`${ ctrlKey }Shift+F11`, this.stepOut);
},
componentDidUpdate() {
@ -33325,7 +33379,7 @@ var Debugger =
renderStepButtons() {
var className = this.props.pause ? "active" : "disabled";
return [debugBtn(this.stepOver, "stepOver", className, "Step Over (F10)"), debugBtn(this.stepIn, "stepIn", className, "Step In (F11)"), debugBtn(this.stepOut, "stepOut", className, "Step Out \u21E7 (F12)")];
return [debugBtn(this.stepOver, "stepOver", className, "Step Over (F10)"), debugBtn(this.stepIn, "stepIn", className, `Step In (${ ctrlKey }F11)`), debugBtn(this.stepOut, "stepOut", className, `Step Out (${ ctrlKey }${ shiftKey }F11)`)];
},
renderPauseButton() {
@ -37722,7 +37776,7 @@ var Debugger =
key: source.get("id"),
onClick: () => {
var tabIndex = getLastVisibleTabIndex(sourceTabs, sourceTabEls);
selectSource(source.get("id"), { position: tabIndex });
selectSource(source.get("id"), { tabIndex });
this.toggleSourcesDropdown();
}
}, filename);
@ -37905,7 +37959,7 @@ var Debugger =
},
render() {
if (!this.props.selectedSource) {
if (!this.props.selectedSource || !isEnabled("prettyPrint") && !isEnabled("blackBox")) {
return null;
}
@ -37946,6 +38000,8 @@ var Debugger =
__webpack_require__(362);
var Svg = __webpack_require__(234);
var INITIAL_SELECTED_INDEX = 0;
var Autocomplete = React.createClass({
propTypes: {
selectItem: PropTypes.func,
@ -37957,7 +38013,7 @@ var Debugger =
getInitialState() {
return {
inputValue: "",
selectedIndex: -1
selectedIndex: INITIAL_SELECTED_INDEX
};
},
@ -38000,7 +38056,7 @@ var Debugger =
ref: "searchInput",
onChange: e => this.setState({
inputValue: e.target.value,
selectedIndex: -1
selectedIndex: INITIAL_SELECTED_INDEX
}),
onFocus: e => this.setState({ focused: true }),
onBlur: e => this.setState({ focused: false }),

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

@ -4,7 +4,6 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="resource://devtools/client/debugger/new/styles.css" />
<link rel="stylesheet"
type="text/css"
href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css" />
@ -14,6 +13,7 @@
<link rel="stylesheet"
type="text/css"
href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css" />
<link rel="stylesheet" type="text/css" href="resource://devtools/client/debugger/new/styles.css" />
</head>
<body>
<div id="mount"></div>

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

@ -151,7 +151,7 @@ var Debugger =
var consumer = _getConsumer(generatedSource.id);
// if there is not a consumer, then its a generated source without a map
// if there is not a consumer, then it's a generated source without a map
if (!consumer) {
return {
url: generatedSource.url,

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

@ -381,6 +381,15 @@ ul.sources-list {
display: none;
}
.highlight-line .CodeMirror-line {
animation: fade-highlight-out 1.5s normal forwards;
}
@keyframes fade-highlight-out {
0% { background-color: var(--theme-highlight-gray); }
100% { background-color: transparent; }
}
.welcomebox {
width: 100%;

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

@ -43,22 +43,29 @@
"waitForThreadEvents": false,
"waitForState": false,
"waitForPaused": false,
"waitForSources": false,
"isPaused": false,
"assertPausedLocation": false,
"assertHighlightLocation": false,
"initDebugger": false,
"invokeInTab": false,
"findSource": false,
"findElement": false,
"findAllElements": false,
"selectSource": false,
"stepOver": false,
"stepIn": false,
"stepOut": false,
"resume": false,
"reload": false,
"navigate": false,
"removeBreakpoint": false,
"addBreakpoint": false,
"toggleCallStack": false,
"isVisibleWithin": false,
"clickElement": false,
"togglePauseOnExceptions": false
"togglePauseOnExceptions": false,
"pressKey": false,
"EXAMPLE_URL": false
}
}

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

@ -6,7 +6,7 @@ support-files =
!/devtools/client/commandline/test/helpers.js
!/devtools/client/framework/test/shared-head.js
examples/doc-scripts.html
examples/doc-script-switching-01.html
examples/doc-script-switching.html
examples/doc-exceptions.html
examples/doc-iframes.html
examples/doc-debugger-statements.html
@ -20,9 +20,13 @@ support-files =
[browser_dbg-editor-gutter.js]
[browser_dbg-editor-mode.js]
[browser_dbg-editor-select.js]
[browser_dbg-editor-highlight.js]
[browser_dbg-call-stack.js]
[browser_dbg-pause-exceptions.js]
[browser_dbg-chrome-create.js]
[browser_dbg-chrome-debugging.js]
[browser_dbg-iframes.js]
[browser_dbg-debugger-buttons.js]
[browser_dbg_keyboard-shortcuts.js]
[browser_dbg-navigation.js]
[browser_dbg-console.js]

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

@ -17,7 +17,7 @@ function isFrameSelected(dbg, index, title) {
add_task(function* () {
const dbg = yield initDebugger(
"doc-script-switching-01.html",
"doc-script-switching.html",
"script-switching-01.js"
);

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

@ -0,0 +1,34 @@
// Return a promise with a reference to jsterm, opening the split
// console if necessary. This cleans up the split console pref so
// it won't pollute other tests.
function getSplitConsole(dbg) {
const { toolbox, win } = dbg;
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
});
if (!win) {
win = toolbox.win;
}
if (!toolbox.splitConsole) {
EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
}
return new Promise(resolve => {
toolbox.getPanelWhenReady("webconsole").then(() => {
ok(toolbox.splitConsole, "Split console is shown.");
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
resolve(jsterm);
});
});
}
add_task(function* () {
Services.prefs.setBoolPref("devtools.toolbox.splitconsoleEnabled", true);
const dbg = yield initDebugger("doc-script-switching.html");
yield getSplitConsole(dbg);
ok(dbg.toolbox.splitConsole, "Split console is shown.");
});

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

@ -0,0 +1,47 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the editor will always highight the right line, no
// matter if the source text doesn't exist yet or even if the source
// doesn't exist.
add_task(function* () {
const dbg = yield initDebugger("doc-scripts.html");
const { selectors: { getSourceText }, getState } = dbg;
const sourceUrl = EXAMPLE_URL + "code-long.js";
// The source itself doesn't even exist yet, and using
// `selectSourceURL` will set a pending request to load this source
// and highlight a specific line.
dbg.actions.selectSourceURL(sourceUrl, { line: 66 });
// Wait for the source text to load and make sure we're in the right
// place.
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
assertHighlightLocation(dbg, "long.js", 66);
// Jump to line 16 and make sure the editor scrolled.
yield selectSource(dbg, "long.js", 16);
assertHighlightLocation(dbg, "long.js", 16);
// Make sure only one line is ever highlighted and the flash
// animation is cancelled on old lines.
yield selectSource(dbg, "long.js", 17);
yield selectSource(dbg, "long.js", 18);
assertHighlightLocation(dbg, "long.js", 18);
is(findAllElements(dbg, "highlightLine").length, 1,
"Only 1 line is highlighted");
// Test jumping to a line in a source that exists but hasn't been
// loaded yet.
yield waitForSources(dbg, "simple1.js");
selectSource(dbg, "simple1.js", 6);
// Make sure the source is in the loading state, wait for it to be
// fully loaded, and check the highlighted line.
const simple1 = findSource(dbg, "simple1.js");
ok(getSourceText(getState(), simple1.id).get("loading"));
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
ok(getSourceText(getState(), simple1.id).get("text"));
assertHighlightLocation(dbg, "simple1.js", 6);
});

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

@ -5,10 +5,10 @@
// debugger pauses
// checks to see if the first breakpoint is visible
function isBreakpointVisible(dbg) {
const bpLine = findElement(dbg, "breakpoint");
function isElementVisible(dbg, elementName) {
const bpLine = findElement(dbg, elementName);
const cm = findElement(dbg, "codeMirror");
ok(isVisibleWithin(cm, bpLine), "CodeMirror is scrolled to line");
return bpLine && isVisibleWithin(cm, bpLine);
}
add_task(function* () {
@ -21,7 +21,7 @@ add_task(function* () {
const simple2 = findSource(dbg, "simple2.js");
// Set the initial breakpoint.
yield addBreakpoint(dbg, simple1.id, 4);
yield addBreakpoint(dbg, simple1, 4);
ok(!getSelectedSource(getState()), "No selected source");
// Call the function that we set a breakpoint in.
@ -42,11 +42,11 @@ add_task(function* () {
// Make sure that we can set a breakpoint on a line out of the
// viewport, and that pausing there scrolls the editor to it.
const longSrc = findSource(dbg, "long.js");
yield addBreakpoint(dbg, longSrc.id, 66);
let longSrc = findSource(dbg, "long.js");
yield addBreakpoint(dbg, longSrc, 66);
invokeInTab("testModel");
yield waitForPaused(dbg);
assertPausedLocation(dbg, longSrc, 66);
isBreakpointVisible(dbg);
ok(isElementVisible(dbg, "breakpoint"), "Breakpoint is visible");
});

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

@ -0,0 +1,42 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function countSources(dbg) {
const sources = dbg.selectors.getSources(dbg.getState());
return sources.size;
}
/**
* Test navigating
* navigating while paused will reset the pause state and sources
*/
add_task(function* () {
const dbg = yield initDebugger(
"doc-script-switching.html",
"script-switching-01.js"
);
invokeInTab("firstCall");
yield waitForPaused(dbg);
yield navigate(dbg, "doc-scripts.html", "simple1.js", "long.js");
yield addBreakpoint(dbg, "simple1.js", 4);
invokeInTab("main");
yield waitForPaused(dbg);
assertPausedLocation(dbg, "simple1.js", 4);
is(countSources(dbg), 4, "4 sources are loaded.");
yield navigate(dbg, "about:blank");
yield waitForDispatch(dbg, "NAVIGATE");
is(countSources(dbg), 0, "0 sources are loaded.");
yield navigate(dbg,
"doc-scripts.html",
"simple1.js",
"simple2.js",
"long.js",
"scripts.html"
);
is(countSources(dbg), 4, "4 sources are loaded.");
});

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

@ -0,0 +1,49 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test keyboard shortcuts.
*/
function pressResume(dbg) {
pressKey(dbg, "resumeKey");
return waitForPaused(dbg);
}
function pressStepOver(dbg) {
pressKey(dbg, "stepOverKey");
return waitForPaused(dbg);
}
function pressStepIn(dbg) {
pressKey(dbg, "stepInKey");
return waitForPaused(dbg);
}
function pressStepOut(dbg) {
pressKey(dbg, "stepOutKey");
return waitForPaused(dbg);
}
add_task(function*() {
const dbg = yield initDebugger(
"doc-debugger-statements.html",
"debugger-statements.html"
);
yield reload(dbg);
yield waitForPaused(dbg);
assertPausedLocation(dbg, "debugger-statements.html", 8);
yield pressResume(dbg);
assertPausedLocation(dbg, "debugger-statements.html", 12);
yield pressStepIn(dbg);
assertPausedLocation(dbg, "debugger-statements.html", 13);
yield pressStepOut(dbg);
assertPausedLocation(dbg, "debugger-statements.html", 14);
yield pressStepOver(dbg);
assertPausedLocation(dbg, "debugger-statements.html", 9);
});

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

@ -95,28 +95,54 @@ function waitForState(dbg, predicate) {
});
}
function waitForMs(time) {
return new Promise(resolve => setTimeout(resolve, time));
function waitForSources(dbg, ...sources) {
if(sources.length === 0) {
return Promise.resolve();
}
info("Waiting on sources: " + sources.join(", "));
const {selectors: {getSources}, store} = dbg;
return Promise.all(sources.map(url => {
function sourceExists(state) {
return getSources(state).some(s => s.get("url").includes(url));
}
if(!sourceExists(store.getState())) {
return waitForState(dbg, sourceExists);
}
}));
}
function assertPausedLocation(dbg, source, line) {
const { selectors: { getSelectedSource, getPause }, getState } = dbg;
source = findSource(dbg, source);
// support passing in a partial url and fetching the source
if (typeof source == "string") {
source = findSource(dbg, source);
}
// check the selected source
// Check the selected source
is(getSelectedSource(getState()).get("url"), source.url);
// check the pause location
// Check the pause location
const location = getPause(getState()).getIn(["frame", "location"]);
is(location.get("sourceId"), source.id);
is(location.get("line"), line);
// check the debug line
// Check the debug line
ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("debug-line"),
"Line is highlighted as paused");
}
function assertHighlightLocation(dbg, source, line) {
const { selectors: { getSelectedSource, getPause }, getState } = dbg;
source = findSource(dbg, source);
// Check the selected source
is(getSelectedSource(getState()).get("url"), source.url);
// Check the highlight line
const lineEl = findElement(dbg, "highlightLine");
ok(lineEl, "Line is highlighted");
ok(isVisibleWithin(findElement(dbg, "codeMirror"), lineEl),
"Highlighted line is visible");
ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("highlight-line"),
"Line is highlighted");
}
@ -125,11 +151,11 @@ function isPaused(dbg) {
return !!getPause(getState());
}
const waitForPaused = Task.async(function* (dbg) {
// We want to make sure that we get both a real paused event and
// that the state is fully populated. The client may do some more
// work (call other client methods) before populating the state.
return Promise.all([
function waitForPaused(dbg) {
return Task.spawn(function* () {
// We want to make sure that we get both a real paused event and
// that the state is fully populated. The client may do some more
// work (call other client methods) before populating the state.
yield waitForThreadEvents(dbg, "paused"),
yield waitForState(dbg, state => {
const pause = dbg.selectors.getPause(state);
@ -142,42 +168,32 @@ const waitForPaused = Task.async(function* (dbg) {
const sourceId = pause.getIn(["frame", "location", "sourceId"]);
const sourceText = dbg.selectors.getSourceText(dbg.getState(), sourceId);
return sourceText && !sourceText.get("loading");
})
]);
});
});
});
};
const initDebugger = Task.async(function* (url, ...sources) {
const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
const win = toolbox.getPanel("jsdebugger").panelWin;
const store = win.Debugger.store;
const { getSources } = win.Debugger.selectors;
function initDebugger(url, ...sources) {
return Task.spawn(function* () {
const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
const win = toolbox.getPanel("jsdebugger").panelWin;
const store = win.Debugger.store;
const { getSources } = win.Debugger.selectors;
const dbg = {
actions: win.Debugger.actions,
selectors: win.Debugger.selectors,
getState: store.getState,
store: store,
client: win.Debugger.client,
toolbox: toolbox,
win: win
};
const dbg = {
actions: win.Debugger.actions,
selectors: win.Debugger.selectors,
getState: store.getState,
store: store,
client: win.Debugger.client,
toolbox: toolbox,
win: win
};
if(sources.length) {
// TODO: Extract this out to a utility function
info("Waiting on sources: " + sources.join(", "));
yield Promise.all(sources.map(url => {
function sourceExists(state) {
return getSources(state).some(s => s.get("url").includes(url));
}
yield waitForSources(dbg, ...sources);
if(!sourceExists(store.getState())) {
return waitForState(dbg, sourceExists);
}
}));
}
return dbg;
});
return dbg;
});
};
window.resumeTest = undefined;
function pauseTest() {
@ -188,6 +204,13 @@ function pauseTest() {
// Actions
function findSource(dbg, url) {
if(typeof url !== "string") {
// Support passing in a source object itelf all APIs that use this
// function support both styles
const source = url;
return source;
}
const sources = dbg.selectors.getSources(dbg.getState());
const source = sources.find(s => s.get("url").includes(url));
@ -198,12 +221,15 @@ function findSource(dbg, url) {
return source.toJS();
}
function selectSource(dbg, url) {
function selectSource(dbg, url, line) {
info("Selecting source: " + url);
const source = findSource(dbg, url);
dbg.actions.selectSource(source.id);
const hasText = !!dbg.selectors.getSourceText(dbg.getState(), source.id);
dbg.actions.selectSource(source.id, { line });
return waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
if(!hasText) {
return waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
}
}
function stepOver(dbg) {
@ -234,10 +260,21 @@ function reload(dbg) {
return dbg.client.reload();
}
function addBreakpoint(dbg, sourceId, line, col) {
function navigate(dbg, url, ...sources) {
dbg.client.navigate(url);
return waitForSources(dbg, ...sources)
}
function addBreakpoint(dbg, source, line, col) {
source = findSource(dbg, source);
const sourceId = source.id;
return dbg.actions.addBreakpoint({ sourceId, line, col });
}
function removeBreakpoint(dbg, sourceId, line, col) {
return dbg.actions.removeBreakpoint({ sourceId, line, col });
}
function togglePauseOnExceptions(dbg,
pauseOnExceptions, ignoreCaughtExceptions) {
@ -256,11 +293,30 @@ function togglePauseOnExceptions(dbg,
// Helpers
// invoke a global function in the debugged tab
function invokeInTab(fnc) {
info(`Invoking function ${fnc} in tab`);
return ContentTask.spawn(gBrowser.selectedBrowser, fnc, function* (fnc) {
content.wrappedJSObject[fnc](); // eslint-disable-line mozilla/no-cpows-in-tests, max-len
});
}
const isLinux = Services.appinfo.OS === "Linux";
const keyMappings = {
pauseKey: { code: "VK_F8" },
resumeKey: { code: "VK_F8" },
stepOverKey: { code: "VK_F10" },
stepInKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux } },
stepOutKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux, shiftKey: true } }
};
function pressKey(dbg, keyName) {
let keyEvent = keyMappings[keyName];
const { code, modifiers } = keyEvent;
return EventUtils.synthesizeKey(
code,
modifiers || {},
dbg.win
);
}
function isVisibleWithin(outerEl, innerEl) {
const innerRect = innerEl.getBoundingClientRect();
@ -275,12 +331,13 @@ const selectors = {
gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`,
pauseOnExceptions: ".pause-exceptions",
breakpoint: ".CodeMirror-code > .new-breakpoint",
highlightLine: ".CodeMirror-code > .highlight-line",
codeMirror: ".CodeMirror",
resume: ".resume.active",
stepOver: ".stepOver.active",
stepOut: ".stepOut.active",
stepIn: ".stepIn.active"
}
};
function getSelector(elementName, ...args) {
let selector = selectors[elementName];
@ -300,6 +357,11 @@ function findElement(dbg, elementName, ...args) {
return dbg.win.document.querySelector(selector);
}
function findAllElements(dbg, elementName, ...args) {
const selector = getSelector(elementName, ...args);
return dbg.win.document.querySelectorAll(selector);
}
// click an element in the debugger
function clickElement(dbg, elementName, ...args) {
const selector = getSelector(elementName, ...args);

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

@ -27,7 +27,7 @@ var test = Task.async(function* () {
});
const paused = waitForThreadEvents(panel, "paused");
reloadActiveTab(panel);
yield reloadActiveTab(panel, panel.panelWin.EVENTS.SOURCE_SHOWN);
const packet = yield paused;
is(packet.why.type, "breakpoint",
@ -35,6 +35,5 @@ var test = Task.async(function* () {
is(packet.frame.where.line, 10,
"Should have stopped at line 10, where we set the breakpoint");
yield waitForDebuggerEvents(panel, panel.panelWin.EVENTS.SOURCE_SHOWN);
yield resumeDebuggerThenCloseAndFinish(panel);
});

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

@ -32,7 +32,7 @@ function test() {
const startedLoading = waitForNextDispatch(gDebugger.DebuggerController,
constants.LOAD_SOURCE_TEXT);
navigateActiveTabTo(gPanel, TAB_URL_2);
navigateActiveTabTo(gPanel, TAB_URL_2, gDebugger.EVENTS.SOURCE_SHOWN);
yield startedLoading;
isnot(gDebugger.gThreadClient.state, "paused",

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

@ -31,8 +31,8 @@ function test() {
finished.then(testSourceIsPretty)
.then(() => {
const finished = waitForCaretUpdated(gPanel, 7);
reloadActiveTab(gPanel);
return finished;
const reloaded = reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
return Promise.all([finished, reloaded]);
})
.then(testSourceIsPretty)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))

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

@ -107,13 +107,22 @@ registerCleanupFunction(function* cleanup() {
/**
* Add a new test tab in the browser and load the given url.
* @param {String} url The url to be loaded in the new tab
* @param {Object} options Object with various optional fields:
* - {Boolean} background If true, open the tab in background
* - {ChromeWindow} window Firefox top level window we should use to open the tab
* @return a promise that resolves to the tab object when the url is loaded
*/
var addTab = Task.async(function* (url) {
var addTab = Task.async(function* (url, options = { background: false, window: window }) {
info("Adding a new tab with URL: " + url);
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
let { background } = options;
let { gBrowser } = options.window ? options.window : window;
let tab = gBrowser.addTab(url);
if (!background) {
gBrowser.selectedTab = tab;
}
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
info("Tab added and finished loading");
@ -128,6 +137,7 @@ var addTab = Task.async(function* (url) {
var removeTab = Task.async(function* (tab) {
info("Removing tab.");
let { gBrowser } = tab.ownerDocument.defaultView;
let onClose = once(gBrowser.tabContainer, "TabClose");
gBrowser.removeTab(tab);
yield onClose;

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

@ -42,18 +42,6 @@ table.headers.cookies.expires=Expires on
table.headers.cookies.value=Value
table.headers.cookies.lastAccessed=Last accessed on
table.headers.cookies.creationTime=Created on
# LOCALIZATION NOTE (table.headers.cookies.isHttpOnly):
# This string is used in the header for the column which denotes whether a
# cookie is HTTP only or not.
table.headers.cookies.isHttpOnly=isHttpOnly
# LOCALIZATION NOTE (table.headers.cookies.isSecure):
# This string is used in the header for the column which denotes whether a
# cookie can be accessed via a secure channel only or not.
table.headers.cookies.isSecure=isSecure
# LOCALIZATION NOTE (table.headers.cookies.isDomain):
# This string is used in the header for the column which denotes whether a
# cookie is a domain cookie only or not.
table.headers.cookies.isDomain=isDomain
table.headers.localStorage.name=Key
table.headers.localStorage.value=Value

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

@ -73,23 +73,21 @@
/* Close button */
.notificationbox .messageCloseButton {
/* Use odd value for the width so, the icon can be nicely h-centered.
This also means that the button is not perfect circle (its using
10x border radius), but it's less visible visual discrepency
than wrong centering of the icon */
width: 19px;
width: 20px;
height: 20px;
margin: 4px;
margin-inline-end: 8px;
background-image: url("chrome://devtools/skin/images/close.svg");
background-position: 3px center;
background-position: 3.45px 2.5px;
background-color: transparent;
background-repeat: no-repeat;
border-radius: 10px;
border-radius: 11px;
filter: invert(0);
}
.notificationbox .messageCloseButton:hover {
background-color: rgba(170, 170, 170, .2); /* --toolbar-tab-hover */
background-color: gray;
filter: invert(1);
}
.notificationbox .messageCloseButton:active {

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

@ -18,7 +18,7 @@ add_task(function* () {
// test that value is something initially
let initialValue = [[
{name: "c1", value: "1.2.3.4.5.6.7"},
{name: "c1.path", value: "/browser"}
{name: "c1.Path", value: "/browser"}
], [
{name: "c1", value: "Array"},
{name: "c1.0", value: "1"},
@ -28,7 +28,7 @@ add_task(function* () {
// test that value is something initially
let finalValue = [[
{name: "c1", value: '{"foo": 4,"bar":6}'},
{name: "c1.path", value: "/browser"}
{name: "c1.Path", value: "/browser"}
], [
{name: "c1", value: "Object"},
{name: "c1.foo", value: "4"},

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

@ -19,21 +19,21 @@ const LONG_WORD = "a".repeat(1000);
const testCases = [
["cs2", [
{name: "cs2", value: "sessionCookie"},
{name: "cs2.path", value: "/"},
{name: "cs2.isDomain", value: "true"},
{name: "cs2.isHttpOnly", value: "false"},
{name: "cs2.host", value: ".example.org"},
{name: "cs2.expires", value: "Session"},
{name: "cs2.isSecure", value: "false"},
{name: "cs2.Path", value: "/"},
{name: "cs2.HostOnly", value: "false"},
{name: "cs2.HttpOnly", value: "false"},
{name: "cs2.Domain", value: ".example.org"},
{name: "cs2.Expires", value: "Session"},
{name: "cs2.Secure", value: "false"},
]],
["c1", [
{name: "c1", value: JSON.stringify(["foo", "Bar", {foo: "Bar"}])},
{name: "c1.path", value: "/browser"},
{name: "c1.isDomain", value: "false"},
{name: "c1.isHttpOnly", value: "false"},
{name: "c1.host", value: "test1.example.org"},
{name: "c1.expires", value: new Date(2000000000000).toUTCString()},
{name: "c1.isSecure", value: "false"},
{name: "c1.Path", value: "/browser"},
{name: "c1.HostOnly", value: "true"},
{name: "c1.HttpOnly", value: "false"},
{name: "c1.Domain", value: "test1.example.org"},
{name: "c1.Expires", value: new Date(2000000000000).toUTCString()},
{name: "c1.Secure", value: "false"},
]],
[null, [
{name: "c1", value: "Array"},

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

@ -50,6 +50,17 @@ const REASON = {
UPDATE: "update"
};
const COOKIE_KEY_MAP = {
path: "Path",
host: "Domain",
expires: "Expires",
isSecure: "Secure",
isHttpOnly: "HttpOnly",
isDomain: "HostOnly",
creationTime: "CreationTime",
lastAccessed: "LastAccessed"
};
// Maximum length of item name to show in context menu label - will be
// trimmed with ellipsis if it's longer.
const ITEM_NAME_MAX_LENGTH = 32;
@ -607,7 +618,9 @@ StorageUI.prototype = {
let otherProps = itemProps.filter(
e => !["name", "value", "valueActor"].includes(e));
for (let prop of otherProps) {
rawObject[prop] = item[prop];
let cookieProp = COOKIE_KEY_MAP[prop] || prop;
// The pseduo property of HostOnly refers to converse of isDomain property
rawObject[cookieProp] = (prop === "isDomain") ? !item[prop] : item[prop];
}
itemVar.populate(rawObject, {sorted: true});
itemVar.twisty = true;
@ -777,11 +790,17 @@ StorageUI.prototype = {
}
columns[f.name] = f.name;
let columnName;
try {
columns[f.name] = L10N.getStr("table.headers." + type + "." + f.name);
columnName = L10N.getStr("table.headers." + type + "." + f.name);
} catch (e) {
console.error("Unable to localize table header type:" + type +
" key:" + f.name);
columnName = COOKIE_KEY_MAP[f.name];
}
if (!columnName) {
console.error("Unable to localize table header type:" + type + " key:" + f.name);
} else {
columns[f.name] = columnName;
}
});

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

@ -591,9 +591,9 @@ checkbox:-moz-focusring {
margin-right: 0;
}
.devtools-searchbox > .devtools-textinput:-moz-focusring,
.devtools-searchbox > .devtools-searchinput:-moz-focusring,
.devtools-searchbox > .devtools-filterinput:-moz-focusring {
.devtools-textinput:focus,
.devtools-searchinput:focus,
.devtools-filterinput:focus {
border-color: var(--theme-focus-border-color-textbox);
box-shadow: var(--theme-focus-box-shadow-textbox);
transition: all 0.2s ease-in-out;

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

@ -1,6 +1,6 @@
<!-- 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 width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#0b0b0b">
<svg width="17" height="17" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill="#0b0b0b">
<path d="M8.707 8l4.23 4.23a.5.5 0 1 1-.707.707L8 8.707l-4.23 4.23a.5.5 0 1 1-.707-.707L7.293 8l-4.23-4.23a.5.5 0 1 1 .707-.707L8 7.293l4.23-4.23a.5.5 0 0 1 .707.707L8.707 8z" fill-rule="evenodd"/>
</svg>

До

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

После

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

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

@ -169,6 +169,8 @@
.devtools-responsiveui-close > image {
filter: invert(1);
padding-inline-start: 3px;
padding-top: 2px;
}
.devtools-responsiveui-rotate {

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

@ -983,7 +983,8 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return {
error: "wrongState",
message: "Can't resume when debuggee isn't paused. Current state is '"
+ this._state + "'"
+ this._state + "'",
state: this._state
};
}

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

@ -145,7 +145,8 @@ function eventSource(aProto) {
const ThreadStateTypes = {
"paused": "paused",
"resumed": "attached",
"detached": "detached"
"detached": "detached",
"running": "attached"
};
/**
@ -1739,6 +1740,7 @@ ThreadClient.prototype = {
// Put the client in a tentative "resuming" state so we can prevent
// further requests that should only be sent in the paused state.
this._previousState = this._state;
this._state = "resuming";
if (this._pauseOnExceptions) {
@ -1753,10 +1755,17 @@ ThreadClient.prototype = {
return aPacket;
},
after: function (aResponse) {
if (aResponse.error) {
// There was an error resuming, back to paused state.
this._state = "paused";
if (aResponse.error && this._state == "resuming") {
// There was an error resuming, update the state to the new one
// reported by the server, if given (only on wrongState), otherwise
// reset back to the previous state.
if (aResponse.state) {
this._state = ThreadStateTypes[aResponse.state];
} else {
this._state = this._previousState;
}
}
delete this._previousState;
return aResponse;
},
}),

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

@ -102,12 +102,13 @@ AudioCaptureStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
AudioSegment output;
for (uint32_t i = 0; i < inputCount; i++) {
MediaStream* s = mInputs[i]->GetSource();
StreamTracks::TrackIter tracks(s->GetStreamTracks(), MediaSegment::AUDIO);
while (!tracks.IsEnded()) {
AudioSegment* inputSegment = tracks->Get<AudioSegment>();
for (StreamTracks::TrackIter track(s->GetStreamTracks(),
MediaSegment::AUDIO);
!track.IsEnded(); track.Next()) {
AudioSegment* inputSegment = track->Get<AudioSegment>();
StreamTime inputStart = s->GraphTimeToStreamTimeWithBlocking(aFrom);
StreamTime inputEnd = s->GraphTimeToStreamTimeWithBlocking(aTo);
if (tracks->IsEnded() && inputSegment->GetDuration() <= inputEnd) {
if (track->IsEnded() && inputSegment->GetDuration() <= inputEnd) {
// If the input track has ended and we have consumed all its data it
// can be ignored.
continue;
@ -119,7 +120,6 @@ AudioCaptureStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
toMix.AppendNullData((aTo - aFrom) - (inputEnd - inputStart));
}
toMix.Mix(mMixer, MONO, Graph()->GraphRate());
tracks.Next();
}
}
// This calls MixerCallback below

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

@ -149,6 +149,16 @@ H264Converter::IsHardwareAccelerated(nsACString& aFailureReason) const
return MediaDataDecoder::IsHardwareAccelerated(aFailureReason);
}
void
H264Converter::SetSeekThreshold(const media::TimeUnit& aTime)
{
if (mDecoder) {
mDecoder->SetSeekThreshold(aTime);
} else {
MediaDataDecoder::SetSeekThreshold(aTime);
}
}
nsresult
H264Converter::CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics)
{

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

@ -38,6 +38,7 @@ public:
}
return "H264Converter decoder (pending)";
}
void SetSeekThreshold(const media::TimeUnit& aTime) override;
nsresult GetLastError() const { return mLastError; }

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

@ -2160,6 +2160,10 @@ XULDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber)
for (i = 0; i < count; ++i) {
mPrototypes[i]->TraceProtos(aTrc, aGCNumber);
}
if (mCurrentPrototype) {
mCurrentPrototype->TraceProtos(aTrc, aGCNumber);
}
}
//----------------------------------------------------------------------

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

@ -51,7 +51,7 @@ struct SurfaceDescriptorX11 {
MOZ_INIT_OUTSIDE_CTOR Drawable mId;
MOZ_INIT_OUTSIDE_CTOR XID mFormat; // either a PictFormat or VisualID
gfx::IntSize mSize;
MOZ_INIT_OUTSIDE_CTOR gfx::IntSize mSize;
MOZ_INIT_OUTSIDE_CTOR Drawable mGLXPixmap; // used to prevent multiple bindings to the same GLXPixmap in-process
};

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

@ -790,11 +790,6 @@ XPCJSContext::FinalizeCallback(JSFreeOp* fop,
// Do the marking...
XPCWrappedNativeScope::MarkAllWrappedNativesAndProtos();
for (auto i = self->mDetachedWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) {
auto entry = static_cast<XPCWrappedNativeProtoMap::Entry*>(i.Get());
static_cast<const XPCWrappedNativeProto*>(entry->key)->Mark();
}
// Mark the sets used in the call contexts. There is a small
// chance that a wrapper's set will change *while* a call is
// happening which uses that wrapper's old interfface set. So,
@ -1495,15 +1490,6 @@ CompartmentPrivate::SizeOfIncludingThis(MallocSizeOf mallocSizeOf)
/***************************************************************************/
void XPCJSContext::SystemIsBeingShutDown()
{
for (auto i = mDetachedWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) {
auto entry = static_cast<XPCWrappedNativeProtoMap::Entry*>(i.Get());
auto proto = const_cast<XPCWrappedNativeProto*>(static_cast<const XPCWrappedNativeProto*>(entry->key));
proto->SystemIsBeingShutDown();
}
}
#define JS_OPTIONS_DOT_STR "javascript.options."
static void
@ -1644,9 +1630,6 @@ XPCJSContext::~XPCJSContext()
delete mDyingWrappedNativeProtoMap;
mDyingWrappedNativeProtoMap = nullptr;
delete mDetachedWrappedNativeProtoMap;
mDetachedWrappedNativeProtoMap = nullptr;
#ifdef MOZ_ENABLE_PROFILER_SPS
// Tell the profiler that the context is gone
if (PseudoStack* stack = mozilla_get_pseudo_stack())
@ -3318,7 +3301,6 @@ XPCJSContext::XPCJSContext()
mThisTranslatorMap(IID2ThisTranslatorMap::newMap(XPC_THIS_TRANSLATOR_MAP_LENGTH)),
mNativeScriptableSharedMap(XPCNativeScriptableSharedMap::newMap(XPC_NATIVE_JSCLASS_MAP_LENGTH)),
mDyingWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DYING_NATIVE_PROTO_MAP_LENGTH)),
mDetachedWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DETACHED_NATIVE_PROTO_MAP_LENGTH)),
mGCIsRunning(false),
mNativesToReleaseArray(),
mDoingFinalization(false),

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

@ -122,7 +122,6 @@ XPCWrappedNativeProto::JSProtoObjectFinalized(js::FreeOp* fop, JSObject* obj)
if (map->Find(mClassInfo) == this)
map->Remove(mClassInfo);
GetContext()->GetDetachedWrappedNativeProtoMap()->Remove(this);
GetContext()->GetDyingWrappedNativeProtoMap()->Add(this);
mJSProtoObject.finalize(js::CastToJSFreeOp(fop)->runtime());

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

@ -83,7 +83,6 @@ nsXPConnect::~nsXPConnect()
mShuttingDown = true;
XPCWrappedNativeScope::SystemIsBeingShutDown();
mContext->SystemIsBeingShutDown();
// The above causes us to clean up a bunch of XPConnect data structures,
// after which point we need to GC to clean everything up. We need to do

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

@ -178,7 +178,6 @@
#define XPC_NATIVE_MAP_LENGTH 8
#define XPC_NATIVE_PROTO_MAP_LENGTH 8
#define XPC_DYING_NATIVE_PROTO_MAP_LENGTH 8
#define XPC_DETACHED_NATIVE_PROTO_MAP_LENGTH 16
#define XPC_NATIVE_INTERFACE_MAP_LENGTH 32
#define XPC_NATIVE_SET_MAP_LENGTH 32
#define XPC_NATIVE_JSCLASS_MAP_LENGTH 16
@ -455,9 +454,6 @@ public:
XPCWrappedNativeProtoMap* GetDyingWrappedNativeProtoMap() const
{return mDyingWrappedNativeProtoMap;}
XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const
{return mDetachedWrappedNativeProtoMap;}
bool JSContextInitialized(JSContext* cx);
virtual bool
@ -565,8 +561,6 @@ public:
void DebugDump(int16_t depth);
void SystemIsBeingShutDown();
bool GCIsRunning() const {return mGCIsRunning;}
~XPCJSContext();
@ -619,7 +613,6 @@ private:
IID2ThisTranslatorMap* mThisTranslatorMap;
XPCNativeScriptableSharedMap* mNativeScriptableSharedMap;
XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap;
bool mGCIsRunning;
nsTArray<nsISupports*> mNativesToReleaseArray;
bool mDoingFinalization;

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

@ -0,0 +1,18 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Test reference</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:ecoal95@gmail.com">
<style>
:root {
color: green;
}
</style>
<p>Should be green
<p>Should be green
<p>Should be green
<p>Should be green
<p>Should be green
<p>Should be green
<p>Should be green
<p>Should be green
<p>Should be green

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

@ -0,0 +1,50 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS Test: child-indexed selectors should match without a parent element.</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:ecoal95@gmail.com">
<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
<link rel="match" href="child-index-no-parent-01-ref.html">
<style>
:root:first-child #a {
color: green;
}
:root:nth-child(n) #b {
color: green;
}
:root:first-of-type #c {
color: green;
}
:root:nth-of-type(1) #d {
color: green;
}
:root:last-of-type #e {
color: green;
}
:root:last-child #f {
color: green;
}
:root:nth-last-child(1) #g {
color: green;
}
:root:nth-last-of-type(n) #h {
color: green;
}
#i {
color: green;
}
/* NB: not matching intentionally */
:root:nth-last-child(2) #i {
color: red;
}
</style>
<p id="a">Should be green
<p id="b">Should be green
<p id="c">Should be green
<p id="d">Should be green
<p id="e">Should be green
<p id="f">Should be green
<p id="g">Should be green
<p id="h">Should be green
<p id="i">Should be green

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

@ -5,3 +5,4 @@
== dir-style-03a.html dir-style-03-ref.html
== dir-style-03b.html dir-style-03-ref.html
== dir-style-04.html dir-style-04-ref.html
== child-index-no-parent-01.html child-index-no-parent-01-ref.html

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

@ -1463,12 +1463,8 @@ static inline bool
edgeChildMatches(Element* aElement, TreeMatchContext& aTreeMatchContext,
bool checkFirst, bool checkLast)
{
nsIContent *parent = aElement->GetParent();
if (!parent) {
return false;
}
if (aTreeMatchContext.mForStyling)
nsIContent* parent = aElement->GetParent();
if (parent && aTreeMatchContext.mForStyling)
parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
return (!checkFirst ||
@ -1485,12 +1481,8 @@ nthChildGenericMatches(Element* aElement,
nsPseudoClassList* pseudoClass,
bool isOfType, bool isFromEnd)
{
nsIContent *parent = aElement->GetParent();
if (!parent) {
return false;
}
if (aTreeMatchContext.mForStyling) {
nsIContent* parent = aElement->GetParent();
if (parent && aTreeMatchContext.mForStyling) {
if (isFromEnd)
parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
else
@ -1527,11 +1519,7 @@ edgeOfTypeMatches(Element* aElement, TreeMatchContext& aTreeMatchContext,
bool checkFirst, bool checkLast)
{
nsIContent *parent = aElement->GetParent();
if (!parent) {
return false;
}
if (aTreeMatchContext.mForStyling) {
if (parent && aTreeMatchContext.mForStyling) {
if (checkLast)
parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
else
@ -1943,7 +1931,7 @@ static bool SelectorMatches(Element* aElement,
if (parent) {
if (aTreeMatchContext.mForStyling)
parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
uint32_t index = parent->GetChildCount();
do {
lastNode = parent->GetChildAt(--index);

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

@ -73,13 +73,11 @@ int32_t
nsNthIndexCache::GetNthIndex(Element* aChild, bool aIsOfType,
bool aIsFromEnd, bool aCheckEdgeOnly)
{
NS_ASSERTION(aChild->GetParent(), "caller should check GetParent()");
if (aChild->IsRootOfAnonymousSubtree()) {
return 0;
}
Cache &cache = mCaches[aIsOfType][aIsFromEnd];
Cache& cache = mCaches[aIsOfType][aIsFromEnd];
if (!cache.initialized() && !cache.init()) {
// Give up and just don't match.
@ -94,11 +92,11 @@ nsNthIndexCache::GetNthIndex(Element* aChild, bool aIsOfType,
return 0;
}
int32_t &slot = entry->value();
int32_t& slot = entry->value();
if (slot != -2 && (slot != -1 || aCheckEdgeOnly)) {
return slot;
}
int32_t result = 1;
if (aCheckEdgeOnly) {
// The caller only cares whether or not the result is 1, so we can

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

@ -9,6 +9,7 @@ import re
import sys
import warnings
import which
from argparse import Namespace
from mozbuild.base import (
MachCommandBase,
@ -61,6 +62,8 @@ Add 'ENABLE_MARIONETTE=1' to your mozconfig file and re-build the application.
Your currently active mozconfig is %s.
'''.lstrip()
parser = None
class ReftestRunner(MozbuildObject):
"""Easily run reftests.
@ -82,16 +85,16 @@ class ReftestRunner(MozbuildObject):
def _make_shell_string(self, s):
return "'%s'" % re.sub("'", r"'\''", s)
def _setup_objdir(self, **kwargs):
def _setup_objdir(self, args):
# reftest imports will happen from the objdir
sys.path.insert(0, self.reftest_dir)
if not kwargs["tests"]:
if not args.tests:
test_subdir = {
"reftest": os.path.join('layout', 'reftests'),
"crashtest": os.path.join('layout', 'crashtest'),
}[kwargs['suite']]
kwargs["tests"] = [test_subdir]
}[args.suite]
args.tests = [test_subdir]
tests = os.path.join(self.reftest_dir, 'tests')
if not os.path.isdir(tests):
@ -110,76 +113,80 @@ class ReftestRunner(MozbuildObject):
suite is the type of reftest to run. It can be one of ('reftest',
'crashtest').
"""
if kwargs["suite"] not in ('reftest', 'crashtest'):
args = Namespace(**kwargs)
if args.suite not in ('reftest', 'crashtest'):
raise Exception('None or unrecognized reftest suite type.')
self._setup_objdir(**kwargs)
self._setup_objdir(args)
import runreftestb2g
for i, path in enumerate(kwargs["tests"]):
for i, path in enumerate(args.tests):
# Non-absolute paths are relative to the packaged directory, which
# has an extra tests/ at the start
if os.path.exists(os.path.abspath(path)):
path = os.path.relpath(path, os.path.join(self.topsrcdir))
kwargs["tests"][i] = os.path.join('tests', path)
args.tests[i] = os.path.join('tests', path)
try:
which.which('adb')
except which.WhichError:
# TODO Find adb automatically if it isn't on the path
raise Exception(ADB_NOT_FOUND % ('%s-remote' % kwargs["suite"], b2g_home))
raise Exception(ADB_NOT_FOUND % ('%s-remote' % args.suite, b2g_home))
kwargs["b2gPath"] = b2g_home
kwargs["logdir"] = self.reftest_dir
kwargs["httpdPath"] = os.path.join(self.topsrcdir, 'netwerk', 'test', 'httpserver')
kwargs["xrePath"] = xre_path
kwargs["ignoreWindowSize"] = True
args.b2gPath = b2g_home
args.logdir = self.reftest_dir
args.httpdPath = os.path.join(self.topsrcdir, 'netwerk', 'test', 'httpserver')
args.xrePath = xre_path
args.ignoreWindowSize = True
# Don't enable oop for crashtest until they run oop in automation
if kwargs["suite"] == 'reftest':
kwargs["oop"] = True
if args.suite == 'reftest':
args.oop = True
return runreftestb2g.run(**kwargs)
return runreftestb2g.run_test_harness(parser, args)
def run_mulet_test(self, **kwargs):
"""Runs a mulet reftest."""
self._setup_objdir(**kwargs)
args = Namespace(**kwargs)
self._setup_objdir(args)
import runreftestmulet
if self.substs.get('ENABLE_MARIONETTE') != '1':
print(MARIONETTE_DISABLED % self.mozconfig['path'])
return 1
if not kwargs["profile"]:
if not args.profile:
gaia_profile = os.environ.get('GAIA_PROFILE')
if not gaia_profile:
print(GAIA_PROFILE_NOT_FOUND)
return 1
kwargs["profile"] = gaia_profile
args.profile = gaia_profile
if os.path.isfile(os.path.join(kwargs["profile"], 'extensions',
if os.path.isfile(os.path.join(args.profile, 'extensions',
'httpd@gaiamobile.org')):
print(GAIA_PROFILE_IS_DEBUG % kwargs["profile"])
print(GAIA_PROFILE_IS_DEBUG % args.profile)
return 1
kwargs['app'] = self.get_binary_path()
kwargs['mulet'] = True
kwargs['oop'] = True
args.app = self.get_binary_path()
args.mulet = True
args.oop = True
if kwargs['oop']:
kwargs['browser_arg'] = '-oop'
if not kwargs['app'].endswith('-bin'):
kwargs['app'] = '%s-bin' % kwargs['app']
if not os.path.isfile(kwargs['app']):
kwargs['app'] = kwargs['app'][:-len('-bin')]
if args.oop:
args.browser_arg = '-oop'
if not args.app.endswith('-bin'):
args.app = '%s-bin' % args.app
if not os.path.isfile(args.app):
args.app = args.app[:-len('-bin')]
return runreftestmulet.run(**kwargs)
return runreftestmulet.run_test_harness(parser, args)
def run_desktop_test(self, **kwargs):
"""Runs a reftest, in desktop Firefox."""
import runreftest
if kwargs["suite"] not in ('reftest', 'crashtest', 'jstestbrowser'):
args = Namespace(**kwargs)
if args.suite not in ('reftest', 'crashtest', 'jstestbrowser'):
raise Exception('None or unrecognized reftest suite type.')
default_manifest = {
@ -189,20 +196,20 @@ class ReftestRunner(MozbuildObject):
"jstests.list")
}
kwargs["extraProfileFiles"].append(os.path.join(self.topobjdir, "dist", "plugins"))
kwargs["symbolsPath"] = os.path.join(self.topobjdir, "crashreporter-symbols")
args.extraProfileFiles.append(os.path.join(self.topobjdir, "dist", "plugins"))
args.symbolsPath = os.path.join(self.topobjdir, "crashreporter-symbols")
if not kwargs["tests"]:
kwargs["tests"] = [os.path.join(*default_manifest[kwargs["suite"]])]
if not args.tests:
args.tests = [os.path.join(*default_manifest[args.suite])]
if kwargs["suite"] == "jstestbrowser":
kwargs["extraProfileFiles"].append(os.path.join(self.topobjdir, "dist",
if args.suite == "jstestbrowser":
args.extraProfileFiles.append(os.path.join(self.topobjdir, "dist",
"test-stage", "jsreftest",
"tests", "user.js"))
self.log_manager.enable_unstructured()
try:
rv = runreftest.run(**kwargs)
rv = runreftest.run_test_harness(parser, args)
finally:
self.log_manager.disable_unstructured()
@ -210,23 +217,26 @@ class ReftestRunner(MozbuildObject):
def run_android_test(self, **kwargs):
"""Runs a reftest, in Firefox for Android."""
import runreftest
if kwargs["suite"] not in ('reftest', 'crashtest', 'jstestbrowser'):
args = Namespace(**kwargs)
if args.suite not in ('reftest', 'crashtest', 'jstestbrowser'):
raise Exception('None or unrecognized reftest suite type.')
if "ipc" in kwargs.keys():
if hasattr(args, 'ipc'):
raise Exception('IPC tests not supported on Android.')
self._setup_objdir(args)
import remotereftest
default_manifest = {
"reftest": (self.topsrcdir, "layout", "reftests", "reftest.list"),
"crashtest": (self.topsrcdir, "testing", "crashtest", "crashtests.list"),
"jstestbrowser": ("jsreftest", "tests", "jstests.list")
}
if not kwargs["tests"]:
kwargs["tests"] = [os.path.join(*default_manifest[kwargs["suite"]])]
if not args.tests:
args.tests = [os.path.join(*default_manifest[args.suite])]
kwargs["extraProfileFiles"].append(
args.extraProfileFiles.append(
os.path.join(self.topsrcdir, "mobile", "android", "fonts"))
hyphenation_path = os.path.join(self.topsrcdir, "intl", "locales")
@ -234,21 +244,21 @@ class ReftestRunner(MozbuildObject):
for (dirpath, dirnames, filenames) in os.walk(hyphenation_path):
for filename in filenames:
if filename.endswith('.dic'):
kwargs["extraProfileFiles"].append(os.path.join(dirpath, filename))
args.extraProfileFiles.append(os.path.join(dirpath, filename))
if not kwargs["httpdPath"]:
kwargs["httpdPath"] = os.path.join(self.tests_dir, "modules")
if not kwargs["symbolsPath"]:
kwargs["symbolsPath"] = os.path.join(self.topobjdir, "crashreporter-symbols")
if not kwargs["xrePath"]:
kwargs["xrePath"] = os.environ.get("MOZ_HOST_BIN")
if not kwargs["app"]:
kwargs["app"] = self.substs["ANDROID_PACKAGE_NAME"]
if not kwargs["utilityPath"]:
kwargs["utilityPath"] = kwargs["xrePath"]
kwargs["dm_trans"] = "adb"
kwargs["ignoreWindowSize"] = True
kwargs["printDeviceInfo"] = False
if not args.httpdPath:
args.httpdPath = os.path.join(self.tests_dir, "modules")
if not args.symbolsPath:
args.symbolsPath = os.path.join(self.topobjdir, "crashreporter-symbols")
if not args.xrePath:
args.xrePath = os.environ.get("MOZ_HOST_BIN")
if not args.app:
args.app = self.substs["ANDROID_PACKAGE_NAME"]
if not args.utilityPath:
args.utilityPath = args.xrePath
args.dm_trans = "adb"
args.ignoreWindowSize = True
args.printDeviceInfo = False
from mozrunner.devices.android_device import grant_runtime_permissions
grant_runtime_permissions(self)
@ -256,40 +266,26 @@ class ReftestRunner(MozbuildObject):
# A symlink and some path manipulations are required so that test
# manifests can be found both locally and remotely (via a url)
# using the same relative path.
if kwargs["suite"] == "jstestbrowser":
if args.suite == "jstestbrowser":
staged_js_dir = os.path.join(self.topobjdir, "dist", "test-stage", "jsreftest")
tests = os.path.join(self.reftest_dir, 'jsreftest')
if not os.path.isdir(tests):
os.symlink(staged_js_dir, tests)
kwargs["extraProfileFiles"].append(os.path.join(staged_js_dir, "tests", "user.js"))
args.extraProfileFiles.append(os.path.join(staged_js_dir, "tests", "user.js"))
else:
tests = os.path.join(self.reftest_dir, "tests")
if not os.path.isdir(tests):
os.symlink(self.topsrcdir, tests)
for i, path in enumerate(kwargs["tests"]):
for i, path in enumerate(args.tests):
# Non-absolute paths are relative to the packaged directory, which
# has an extra tests/ at the start
if os.path.exists(os.path.abspath(path)):
path = os.path.relpath(path, os.path.join(self.topsrcdir))
kwargs["tests"][i] = os.path.join('tests', path)
# Need to chdir to reftest_dir otherwise imports fail below.
os.chdir(self.reftest_dir)
# The imp module can spew warnings if the modules below have
# already been imported, ignore them.
with warnings.catch_warnings():
warnings.simplefilter('ignore')
import imp
path = os.path.join(self.reftest_dir, 'remotereftest.py')
with open(path, 'r') as fh:
imp.load_module('reftest', fh, path, ('.py', 'r', imp.PY_SOURCE))
import reftest
args.tests[i] = os.path.join('tests', path)
self.log_manager.enable_unstructured()
try:
rv = reftest.run(**kwargs)
rv = remotereftest.run_test_harness(parser, args)
finally:
self.log_manager.disable_unstructured()
@ -309,14 +305,16 @@ def process_test_objects(kwargs):
def get_parser():
global parser
here = os.path.abspath(os.path.dirname(__file__))
build_obj = MozbuildObject.from_environment(cwd=here)
if conditions.is_android(build_obj):
return reftestcommandline.RemoteArgumentsParser()
parser = reftestcommandline.RemoteArgumentsParser()
elif conditions.is_mulet(build_obj):
return reftestcommandline.B2GArgumentParser()
parser = reftestcommandline.B2GArgumentParser()
else:
return reftestcommandline.DesktopArgumentsParser()
parser = reftestcommandline.DesktopArgumentsParser()
return parser
@CommandProvider
@ -396,7 +394,7 @@ class B2GCommands(MachCommandBase):
@Command('reftest-remote', category='testing',
description='Run a remote reftest (b2g layout and graphics correctness, remote device).',
conditions=[conditions.is_b2g, is_emulator],
parser=reftestcommandline.B2GArgumentParser)
parser=get_parser)
def run_reftest_remote(self, **kwargs):
kwargs["suite"] = "reftest"
return self._run_reftest(**kwargs)
@ -404,7 +402,7 @@ class B2GCommands(MachCommandBase):
@Command('crashtest-remote', category='testing',
description='Run a remote crashtest (Check if b2g crashes on a page, remote device).',
conditions=[conditions.is_b2g, is_emulator],
parser=reftestcommandline.B2GArgumentParser)
parser=get_parser)
def run_crashtest_remote(self, test_file, **kwargs):
kwargs["suite"] = "crashtest"
return self._run_reftest(**kwargs)

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

@ -5,6 +5,7 @@
from __future__ import unicode_literals
import os
from argparse import Namespace
from functools import partial
from mach.decorators import (
@ -12,28 +13,69 @@ from mach.decorators import (
Command,
)
here = os.path.abspath(os.path.dirname(__file__))
def run_reftest(context, **kwargs):
kwargs['app'] = kwargs['app'] or context.firefox_bin
kwargs['e10s'] = context.mozharness_config.get('e10s', kwargs['e10s'])
kwargs['certPath'] = context.certs_dir
kwargs['utilityPath'] = context.bin_dir
kwargs['extraProfileFiles'].append(os.path.join(context.bin_dir, 'plugins'))
import mozinfo
if not kwargs['tests']:
kwargs['tests'] = [os.path.join('layout', 'reftests', 'reftest.list')]
args = Namespace(**kwargs)
args.e10s = context.mozharness_config.get('e10s', args.e10s)
if not args.tests:
args.tests = [os.path.join('layout', 'reftests', 'reftest.list')]
test_root = os.path.join(context.package_root, 'reftest', 'tests')
normalize = partial(context.normalize_test_path, test_root)
kwargs['tests'] = map(normalize, kwargs['tests'])
args.tests = map(normalize, args.tests)
from runreftest import run as run_test_harness
return run_test_harness(**kwargs)
if mozinfo.info['buildapp'] == 'mobile/android':
return run_reftest_android(context, args)
return run_reftest_desktop(context, args)
def run_reftest_desktop(context, args):
from runreftest import run_test_harness
args.app = args.app or context.firefox_bin
args.extraProfileFiles.append(os.path.join(context.bin_dir, 'plugins'))
args.utilityPath = context.bin_dir
return run_test_harness(parser, args)
def run_reftest_android(context, args):
from remotereftest import run_test_harness
args.app = args.app or 'org.mozilla.fennec'
args.utilityPath = context.hostutils
args.xrePath = context.hostutils
args.httpdPath = context.module_dir
args.dm_trans = 'adb'
args.ignoreWindowSize = True
args.printDeviceInfo = False
config = context.mozharness_config
if config:
args.remoteWebServer = config['remote_webserver']
args.httpPort = config['emulator']['http_port']
args.sslPort = config['emulator']['ssl_port']
args.adb_path = config['exes']['adb'] % {'abs_work_dir': context.mozharness_workdir}
return run_test_harness(parser, args)
def setup_argument_parser():
from reftestcommandline import DesktopArgumentsParser
return DesktopArgumentsParser()
import mozinfo
import reftestcommandline
global parser
mozinfo.find_and_update_from_json(os.path.dirname(here))
if mozinfo.info.get('buildapp') == 'mobile/android':
parser = reftestcommandline.RemoteArgumentsParser()
else:
parser = reftestcommandline.DesktopArgumentsParser()
return parser
@CommandProvider

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

@ -599,6 +599,13 @@ class RemoteArgumentsParser(ReftestArgumentsParser):
dest="remoteAppPath",
help="Path to remote executable relative to device root using only forward slashes. Either this or app must be specified, but not both.")
self.add_argument("--adbpath",
action="store",
type=str,
dest="adb_path",
default="adb",
help="path to adb")
self.add_argument("--deviceIP",
action="store",
type=str,

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

@ -320,29 +320,36 @@ class RemoteReftest(RefTest):
except:
print "Warning: cleaning up pidfile '%s' was unsuccessful from the test harness" % self.pidFile
def runTests(options, parser):
if (options.dm_trans == 'sut' and options.deviceIP == None):
def run_test_harness(parser, options):
if options.dm_trans == 'sut' and options.deviceIP == None:
print "Error: If --dm_trans = sut, you must provide a device IP to connect to via the --deviceIP option"
return 1
dm_args = {
'deviceRoot': options.remoteTestRoot,
'host': options.deviceIP,
'port': options.devicePort,
}
dm_cls = mozdevice.DroidSUT
if options.dm_trans == 'adb':
dm_args['adbPath'] = options.adb_path
if not dm_args['host']:
dm_args['deviceSerial'] = options.deviceSerial
dm_cls = mozdevice.DroidADB
try:
if (options.dm_trans == "adb"):
if (options.deviceIP):
dm = mozdevice.DroidADB(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
elif (options.deviceSerial):
dm = mozdevice.DroidADB(None, None, deviceSerial=options.deviceSerial, deviceRoot=options.remoteTestRoot)
else:
dm = mozdevice.DroidADB(None, None, deviceRoot=options.remoteTestRoot)
else:
dm = mozdevice.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
dm = dm_cls(**dm_args)
except mozdevice.DMError:
traceback.print_exc()
print "Automation Error: exception while initializing devicemanager. Most likely the device is not in a testable state."
return 1
automation = RemoteAutomation(None)
automation.setDeviceManager(dm)
if (options.remoteProductName != None):
if options.remoteProductName:
automation.setProduct(options.remoteProductName)
# Set up the defaults and ensure options are set
@ -398,20 +405,8 @@ def runTests(options, parser):
return retVal
def run(**kwargs):
# Mach gives us kwargs; this is a way to turn them back into an
# options object
parser = reftestcommandline.RemoteArgumentsParser()
parser.set_defaults(**kwargs)
options = parser.parse_args(kwargs["tests"])
retVal = runTests(options, parser)
return retVal
def main():
parser = reftestcommandline.RemoteArgumentsParser()
options = parser.parse_args()
retVal = runTests(options, parser)
return retVal
if __name__ == "__main__":
sys.exit(main())
parser = reftestcommandline.RemoteArgumentsParser()
options = parser.parse_args()
sys.exit(run_test_harness(parser, options))

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

@ -713,18 +713,7 @@ class RefTest(object):
continue
def run(**kwargs):
parser = reftestcommandline.DesktopArgumentsParser()
# Mach gives us kwargs; this is a way to turn them back into an
# options object
parser.set_defaults(**kwargs)
if 'tests' in kwargs:
options = parser.parse_args(kwargs["tests"])
else:
options = parser.parse_args()
def run_test_harness(parser, options):
reftest = RefTest()
parser.validate(options, reftest)
@ -746,4 +735,6 @@ def run(**kwargs):
if __name__ == "__main__":
sys.exit(run())
parser = reftestcommandline.DesktopArgumentsParser()
options = parser.parse_args()
sys.exit(run_test_harness(parser, options))

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

@ -325,7 +325,10 @@ class B2GRemoteReftest(RefTest):
return status
def run_remote_reftests(parser, options):
def run_test_harness(parser, options):
if options.mulet:
return run_mulet_reftests(parser, options)
auto = B2GRemoteAutomation(None, "fennec")
# create our Marionette instance
@ -420,23 +423,7 @@ def run_remote_reftests(parser, options):
return retVal
def run(**kwargs):
# Mach gives us kwargs; this is a way to turn them back into an
# options object
parser = reftestcommandline.B2GArgumentParser()
parser.set_defaults(**kwargs)
options = parser.parse_args(kwargs["tests"])
return run_remote_reftests(parser, options)
def main(args=sys.argv[1:]):
parser = reftestcommandline.B2GArgumentParser()
options = parser.parse_args(args)
if options.mulet:
return run_mulet_reftests(parser, options)
return run_remote_reftests(parser, options)
if __name__ == "__main__":
sys.exit(main())
parser = reftestcommandline.B2GArgumentParser()
options = parser.parse_args()
sys.exit(run_test_harness(parser, options))

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

@ -201,13 +201,4 @@ def run_test_harness(parser, options):
if options.mulet and not options.profile:
raise Exception("must specify --profile when specifying --mulet")
sys.exit(reftest.run_tests(options.tests, options))
def run(**kwargs):
# Mach gives us kwargs; this is a way to turn them back into an
# options object
parser = reftestcommandline.B2GArgumentParser()
parser.set_defaults(**kwargs)
options = parser.parse_args(kwargs['tests'])
return run_test_harness(parser, options)
return reftest.run_tests(options.tests, options)

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

@ -85,12 +85,12 @@ var ContextMenus = {
Addons.setEnabled(true, this.target.addon);
this.target = null;
},
disable: function (event) {
Addons.setEnabled(false, this.target.addon);
this.target = null;
},
uninstall: function (event) {
Addons.uninstall(this.target.addon);
this.target = null;
@ -225,6 +225,16 @@ var Addons = {
let updateable = (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) > 0;
let uninstallable = (aAddon.permissions & AddonManager.PERM_CAN_UNINSTALL) > 0;
// TODO(matt): Add support for OPTIONS_TYPE_INLINE_BROWSER once bug 1302504 lands.
let optionsURL;
switch (aAddon.optionsType) {
case AddonManager.OPTIONS_TYPE_INLINE:
optionsURL = aAddon.optionsURL || "";
break;
default:
optionsURL = "";
}
let blocked = "";
switch(aAddon.blocklistState) {
case Ci.nsIBlocklistService.STATE_BLOCKED:
@ -245,7 +255,7 @@ var Addons = {
item.setAttribute("updateable", updateable);
if (blocked)
item.setAttribute("blockedStatus", blocked);
item.setAttribute("optionsURL", aAddon.optionsURL || "");
item.setAttribute("optionsURL", optionsURL);
item.addon = aAddon;
return item;

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

@ -174,6 +174,9 @@ def docker_worker_setup(config, test, taskdesc):
if 'actions' in mozharness:
env['MOZHARNESS_ACTIONS'] = ' '.join(mozharness['actions'])
if config.params['project'] == 'try':
env['TRY_COMMIT_MSG'] = config.params['message']
# handle some of the mozharness-specific options
if mozharness['tooltool-downloads']:

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

@ -23,6 +23,7 @@ import json
import os
import pwd
import re
import stat
import subprocess
import sys
import urllib2
@ -187,20 +188,33 @@ def main(args):
# Find all groups to which this user is a member.
gids = [g.gr_gid for g in grp.getgrall() if args.group in g.gr_mem]
wanted_dir_mode = stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
def set_dir_permissions(path, uid, gid):
st = os.lstat(path)
if st.st_uid != uid or st.st_gid != gid:
os.chown(path, uid, gid)
# Also make sure dirs are writable in case we need to delete
# them.
if st.st_mode & wanted_dir_mode != wanted_dir_mode:
os.chmod(path, st.st_mode | wanted_dir_mode)
# Change ownership of requested paths.
# FUTURE: parse argument values for user/group if we don't want to
# use --user/--group.
for path in args.chown or []:
print_line(b'chown', b'changing ownership of %s to %s:%s\n' % (
path, user.pw_name, group.gr_name))
os.chown(path, uid, gid)
set_dir_permissions(path, uid, gid)
for path in args.chown_recursive or []:
print_line(b'chown', b'recursively changing ownership of %s to %s:%s\n' %
(path, user.pw_name, group.gr_name))
for root, dirs, files in os.walk(path):
for d in dirs:
os.chown(os.path.join(root, d), uid, gid)
set_dir_permissions(os.path.join(root, d), uid, gid)
for f in files:
os.chown(os.path.join(root, f), uid, gid)

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

@ -78,6 +78,8 @@ class TryToolsMixin(TransferMixin):
msg = None
if "try_message" in self.config and self.config["try_message"]:
msg = self.config["try_message"]
elif 'TRY_COMMIT_MSG' in os.environ:
msg = os.environ['TRY_COMMIT_MSG']
elif self._is_try():
if self.buildbot_config['sourcestamp']['changes']:
msg = self.buildbot_config['sourcestamp']['changes'][-1]['comments']
@ -154,7 +156,8 @@ class TryToolsMixin(TransferMixin):
repo_path = None
if self.buildbot_config and 'properties' in self.buildbot_config:
repo_path = self.buildbot_config['properties'].get('branch')
return self.config.get('branch', repo_path) == 'try'
return (self.config.get('branch', repo_path) == 'try' or
'TRY_COMMIT_MSG' in os.environ)
@PostScriptAction('download-and-extract')
def set_extra_try_arguments(self, action, success=None):

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

@ -58,19 +58,10 @@ class PushAPK(BaseScript, GooglePlayMixin, VirtualenvMixin):
"dest": "apk_file_x86",
"help": "The path to the x86 APK file",
}],
[["--apk-armv7-v9"], {
"dest": "apk_file_armv7_v9",
"help": "The path to the ARM v7 API v9 APK file",
}],
[["--apk-armv7-v15"], {
"dest": "apk_file_armv7_v15",
"help": "The path to the ARM v7 API v15 APK file",
}],
[["--apk-armv6"], {
"dest": "apk_file_armv6",
"help": "The path to the ARM v6 APK file",
}],
]
@ -128,15 +119,9 @@ class PushAPK(BaseScript, GooglePlayMixin, VirtualenvMixin):
if not os.path.isfile(self.config['apk_file_x86']):
self.fatal("Could not find " + self.config['apk_file_x86'])
if self.config.get('apk_file_armv7_v9') and not os.path.isfile(self.config['apk_file_armv7_v9']):
self.fatal("Could not find " + self.config['apk_file_armv7_v9'])
if not os.path.isfile(self.config['apk_file_armv7_v15']):
self.fatal("Could not find " + self.config['apk_file_armv7_v15'])
if self.config.get('apk_file_armv6') and not os.path.isfile(self.config['apk_file_armv6']):
self.fatal("Could not find " + self.config['apk_file_armv6'])
if not os.path.isfile(self.config['google_play_credentials_file']):
self.fatal("Could not find " + self.config['google_play_credentials_file'])
@ -172,26 +157,10 @@ class PushAPK(BaseScript, GooglePlayMixin, VirtualenvMixin):
versions.append(apk_response['versionCode'])
locales = self.translationMgmt.get_list_locales(package_code)
locales.append(u'en-US')
nb_locales = 0
for locale in locales:
translation = self.translationMgmt.get_translation(package_code, locale)
whatsnew = translation.get("whatsnew")
if locale == "en-GB":
self.log("Ignoring en-GB as locale")
continue
locale = self.translationMgmt.locale_mapping(locale)
self.log('Locale "%s" what\'s new has been updated to "%s"'
% (locale, whatsnew))
listing_response = service.edits().apklistings().update(
editId=edit_id, packageName=self.config['package_name'], language=locale,
apkVersionCode=apk_response['versionCode'],
body={'recentChanges': whatsnew}).execute()
self.log('Listing for language %s was updated.'
% listing_response['language'])
if 'aurora' in self.config['package_name']:
self.warning('Aurora is not supported by store_l10n. Skipping what\'s new.')
else:
self._push_whats_new(package_code, service, edit_id, apk_response)
except client.AccessTokenRefreshError:
self.log('The credentials have been revoked or expired,'
@ -211,15 +180,32 @@ class PushAPK(BaseScript, GooglePlayMixin, VirtualenvMixin):
editId=edit_id, packageName=self.config['package_name']).execute()
self.log('Edit "%s" has been committed' % (commit_request['id']))
def _push_whats_new(self, package_code, service, edit_id, apk_response):
locales = self.translationMgmt.get_list_locales(package_code)
locales.append(u'en-US')
for locale in locales:
translation = self.translationMgmt.get_translation(package_code, locale)
whatsnew = translation.get("whatsnew")
if locale == "en-GB":
self.log("Ignoring en-GB as locale")
continue
locale = self.translationMgmt.locale_mapping(locale)
self.log('Locale "%s" what\'s new has been updated to "%s"'
% (locale, whatsnew))
listing_response = service.edits().apklistings().update(
editId=edit_id, packageName=self.config['package_name'], language=locale,
apkVersionCode=apk_response['versionCode'],
body={'recentChanges': whatsnew}).execute()
self.log('Listing for language %s was updated.' % listing_response['language'])
def push_apk(self):
""" Upload the APK files """
self.check_argument()
service = self.connect_to_play()
apks = [self.config['apk_file_armv7_v15'], self.config['apk_file_x86']]
if self.config.get('apk_file_armv6'):
apks.append(self.config['apk_file_armv6'])
if self.config.get('apk_file_armv7_v9'):
apks.append(self.config['apk_file_armv7_v9'])
self.upload_apks(service, apks)
def test(self):

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

@ -37380,6 +37380,12 @@
"url": "/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm"
}
],
"editing/other/delete.html": [
{
"path": "editing/other/delete.html",
"url": "/editing/other/delete.html"
}
],
"editing/other/restoration.html": [
{
"path": "editing/other/restoration.html",
@ -37446,6 +37452,30 @@
"url": "/html/semantics/scripting-1/the-script-element/script-onload-insertion-point.html"
}
],
"html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html": [
{
"path": "html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html",
"url": "/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html"
}
],
"html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html": [
{
"path": "html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html",
"url": "/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html"
}
],
"html/semantics/scripting-1/the-script-element/script-onload-insertion-point.html": [
{
"path": "html/semantics/scripting-1/the-script-element/script-onload-insertion-point.html",
"url": "/html/semantics/scripting-1/the-script-element/script-onload-insertion-point.html"
}
],
"selectors/child-indexed-pseudo-class.html": [
{
"path": "selectors/child-indexed-pseudo-class.html",
"url": "/selectors/child-indexed-pseudo-class.html"
}
],
"svg/linking/scripted/href-animate-element.html": [
{
"path": "svg/linking/scripted/href-animate-element.html",

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

@ -0,0 +1,42 @@
<!doctype html>
<meta charset=utf-8>
<title>Matching of child-indexed pseudo-classes</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:ecoal95@gmail.com">
<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
test(function() {
var check = function(element, selectors) {
for (var i = 0; i < selectors.length; ++i) {
var selector = selectors[i][0];
var expected = selectors[i][1];
assert_equals(expected, element.matches(selector),
"Expected " + element.tagName + " element to " +
(expected ? "match " : "not match ") + selector);
}
}
var rootOfSubtreeSelectors = [
[ ":first-child", true ],
[ ":last-child", true ],
[ ":first-of-type", true ],
[ ":last-of-type", true ],
[ ":nth-child(1)", true ],
[ ":nth-child(n)", true ],
[ ":nth-last-child(1)", true ],
[ ":nth-last-child(n)", true ],
[ ":nth-of-type(1)", true ],
[ ":nth-of-type(n)", true ],
[ ":nth-last-of-type(1)", true ],
[ ":nth-last-of-type(n)", true ],
[ ":nth-child(2)", false ],
[ ":nth-last-child(2)", false],
[ ":nth-of-type(2)", false ],
[ ":nth-last-of-type(2)", false],
];
check(document.documentElement, rootOfSubtreeSelectors);
check(document.createElement('div'), rootOfSubtreeSelectors);
}, "child-indexed pseudo-classes should match without a parent")
</script>

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

@ -401,17 +401,17 @@ PendingLookup::IsBinaryFile()
//StringEndsWith(fileName, NS_LITERAL_STRING(".001")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".7z")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".ace")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".action")) || // Mac script
StringEndsWith(fileName, NS_LITERAL_STRING(".ad")) || // AppleDouble encoded file
//StringEndsWith(fileName, NS_LITERAL_STRING(".action")) || // Mac script
//StringEndsWith(fileName, NS_LITERAL_STRING(".ad")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".ade")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".adp")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".apk")) || // Android package
StringEndsWith(fileName, NS_LITERAL_STRING(".app")) || // Mac app
//StringEndsWith(fileName, NS_LITERAL_STRING(".application")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".appref-ms")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".app")) || // Executable application
StringEndsWith(fileName, NS_LITERAL_STRING(".application")) || // MS ClickOnce
StringEndsWith(fileName, NS_LITERAL_STRING(".appref-ms")) || // MS ClickOnce
//StringEndsWith(fileName, NS_LITERAL_STRING(".arc")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".arj")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".as")) || // Adobe Flash
StringEndsWith(fileName, NS_LITERAL_STRING(".as")) || // Mac archive
StringEndsWith(fileName, NS_LITERAL_STRING(".asp")) || // Windows Server script
StringEndsWith(fileName, NS_LITERAL_STRING(".asx")) || // Windows Media Player
//StringEndsWith(fileName, NS_LITERAL_STRING(".b64")) ||
@ -420,46 +420,46 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".bash")) || // Linux shell
StringEndsWith(fileName, NS_LITERAL_STRING(".bat")) || // Windows shell
//StringEndsWith(fileName, NS_LITERAL_STRING(".bhx")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".bin")) || // Generic binary
//StringEndsWith(fileName, NS_LITERAL_STRING(".bz")) || // Linux archive (bzip)
//StringEndsWith(fileName, NS_LITERAL_STRING(".bin")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".bz")) || // Linux archive (bzip)
StringEndsWith(fileName, NS_LITERAL_STRING(".bz2")) || // Linux archive (bzip2)
StringEndsWith(fileName, NS_LITERAL_STRING(".bzip2")) || // Linux archive (bzip2)
StringEndsWith(fileName, NS_LITERAL_STRING(".cab")) || // Windows archive
//StringEndsWith(fileName, NS_LITERAL_STRING(".cdr")) || // Audio CD image
//StringEndsWith(fileName, NS_LITERAL_STRING(".cfg")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".cdr")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".cfg")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".chi")) || // Windows Help
StringEndsWith(fileName, NS_LITERAL_STRING(".chm")) || // Windows Help
StringEndsWith(fileName, NS_LITERAL_STRING(".class")) || // Java
StringEndsWith(fileName, NS_LITERAL_STRING(".cmd")) || // Windows executable
StringEndsWith(fileName, NS_LITERAL_STRING(".com")) || // Windows executable
StringEndsWith(fileName, NS_LITERAL_STRING(".command")) || // Mac script
//StringEndsWith(fileName, NS_LITERAL_STRING(".cpgz")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".cpgz")) || // Mac archive
//StringEndsWith(fileName, NS_LITERAL_STRING(".cpio")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".cpl")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".crt")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".cpl")) || // Windows executable
StringEndsWith(fileName, NS_LITERAL_STRING(".crt")) || // Windows signed certificate
StringEndsWith(fileName, NS_LITERAL_STRING(".crx")) || // Chrome extensions
StringEndsWith(fileName, NS_LITERAL_STRING(".csh")) || // Linux shell
StringEndsWith(fileName, NS_LITERAL_STRING(".dart")) || // Dart script
StringEndsWith(fileName, NS_LITERAL_STRING(".dart")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".dc42")) || // Apple DiskCopy Image
StringEndsWith(fileName, NS_LITERAL_STRING(".deb")) || // Linux package
StringEndsWith(fileName, NS_LITERAL_STRING(".dex")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".dex")) || // Android
StringEndsWith(fileName, NS_LITERAL_STRING(".diskcopy42")) || // Apple DiskCopy Image
StringEndsWith(fileName, NS_LITERAL_STRING(".dll")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".dll")) || // Windows executable
StringEndsWith(fileName, NS_LITERAL_STRING(".dmg")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".dmgpart")) || // Mac disk image
//StringEndsWith(fileName, NS_LITERAL_STRING(".docb")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".docm")) || // MS Word
StringEndsWith(fileName, NS_LITERAL_STRING(".docx")) || // MS Word
StringEndsWith(fileName, NS_LITERAL_STRING(".dotm")) || // MS Word
//StringEndsWith(fileName, NS_LITERAL_STRING(".dott")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".docb")) || // MS Office
//StringEndsWith(fileName, NS_LITERAL_STRING(".docm")) || // MS Word
//StringEndsWith(fileName, NS_LITERAL_STRING(".docx")) || // MS Word
//StringEndsWith(fileName, NS_LITERAL_STRING(".dotm")) || // MS Word
//StringEndsWith(fileName, NS_LITERAL_STRING(".dott")) || // MS Office
StringEndsWith(fileName, NS_LITERAL_STRING(".drv")) || // Windows driver
//StringEndsWith(fileName, NS_LITERAL_STRING(".dvdr")) || // DVD image
StringEndsWith(fileName, NS_LITERAL_STRING(".dvdr")) || // Mac Disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".efi")) || // Firmware
StringEndsWith(fileName, NS_LITERAL_STRING(".eml")) || // Email
StringEndsWith(fileName, NS_LITERAL_STRING(".eml")) || // MS Outlook
StringEndsWith(fileName, NS_LITERAL_STRING(".exe")) || // Windows executable
//StringEndsWith(fileName, NS_LITERAL_STRING(".fat")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".fon")) || // Windows font
//StringEndsWith(fileName, NS_LITERAL_STRING(".fxp")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".fxp")) || // MS FoxPro
StringEndsWith(fileName, NS_LITERAL_STRING(".gadget")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".grp")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".gz")) || // Linux archive (gzip)
@ -467,26 +467,26 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".hfs")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".hlp")) || // Windows Help
StringEndsWith(fileName, NS_LITERAL_STRING(".hqx")) || // Mac archive
StringEndsWith(fileName, NS_LITERAL_STRING(".hta")) || // HTML program file
StringEndsWith(fileName, NS_LITERAL_STRING(".hta")) || // HTML trusted application
StringEndsWith(fileName, NS_LITERAL_STRING(".htt")) || // MS HTML template
StringEndsWith(fileName, NS_LITERAL_STRING(".img")) || // Generic image
StringEndsWith(fileName, NS_LITERAL_STRING(".img")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".imgpart")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".inf")) || // Windows installer
//StringEndsWith(fileName, NS_LITERAL_STRING(".ini")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".ins")) || // InstallShield
StringEndsWith(fileName, NS_LITERAL_STRING(".inx")) || // InstallShield
StringEndsWith(fileName, NS_LITERAL_STRING(".ini")) || // Generic config file
StringEndsWith(fileName, NS_LITERAL_STRING(".ins")) || // IIS config
//StringEndsWith(fileName, NS_LITERAL_STRING(".inx")) || // InstallShield
StringEndsWith(fileName, NS_LITERAL_STRING(".iso")) || // CD image
//StringEndsWith(fileName, NS_LITERAL_STRING(".isp")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".isu")) || // InstallShield
StringEndsWith(fileName, NS_LITERAL_STRING(".isp")) || // IIS config
//StringEndsWith(fileName, NS_LITERAL_STRING(".isu")) || // InstallShield
StringEndsWith(fileName, NS_LITERAL_STRING(".jar")) || // Java
StringEndsWith(fileName, NS_LITERAL_STRING(".jnlp")) || // Java
StringEndsWith(fileName, NS_LITERAL_STRING(".job")) || // Windows
//StringEndsWith(fileName, NS_LITERAL_STRING(".job")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".js")) || // JavaScript script
StringEndsWith(fileName, NS_LITERAL_STRING(".jse")) || // JScript
StringEndsWith(fileName, NS_LITERAL_STRING(".ksh")) || // Linux shell
//StringEndsWith(fileName, NS_LITERAL_STRING(".lha")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".lnk")) || // Windows
//StringEndsWith(fileName, NS_LITERAL_STRING(".local")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".local")) || // Windows
//StringEndsWith(fileName, NS_LITERAL_STRING(".lpaq1")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".lpaq5")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".lpaq8")) ||
@ -496,12 +496,12 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".maf")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".mag")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".mam")) || // MS Access
//StringEndsWith(fileName, NS_LITERAL_STRING(".manifest")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".manifest")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".maq")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".mar")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".mas")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".mat")) || // MS Access
//StringEndsWith(fileName, NS_LITERAL_STRING(".mau")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".mau")) || // Media attachment
StringEndsWith(fileName, NS_LITERAL_STRING(".mav")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".maw")) || // MS Access
StringEndsWith(fileName, NS_LITERAL_STRING(".mda")) || // MS Access
@ -514,10 +514,10 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".mhtml")) || // MS HTML
StringEndsWith(fileName, NS_LITERAL_STRING(".mim")) || // MS Mail
StringEndsWith(fileName, NS_LITERAL_STRING(".mmc")) || // MS Office
//StringEndsWith(fileName, NS_LITERAL_STRING(".mof")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".mpkg")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".msc")) || // MS Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".msg")) || // Email
StringEndsWith(fileName, NS_LITERAL_STRING(".mof")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".mpkg")) || // Mac installer
StringEndsWith(fileName, NS_LITERAL_STRING(".msc")) || // Windows executable
StringEndsWith(fileName, NS_LITERAL_STRING(".msg")) || // MS Outlook
StringEndsWith(fileName, NS_LITERAL_STRING(".msh")) || // Windows shell
StringEndsWith(fileName, NS_LITERAL_STRING(".msh1")) || // Windows shell
StringEndsWith(fileName, NS_LITERAL_STRING(".msh1xml")) || // Windows shell
@ -531,30 +531,29 @@ PendingLookup::IsBinaryFile()
//StringEndsWith(fileName, NS_LITERAL_STRING(".ntfs")) || // 7z
StringEndsWith(fileName, NS_LITERAL_STRING(".ocx")) || // ActiveX
StringEndsWith(fileName, NS_LITERAL_STRING(".ops")) || // MS Office
StringEndsWith(fileName, NS_LITERAL_STRING(".osx")) || // Mac PowerPC executable
StringEndsWith(fileName, NS_LITERAL_STRING(".out")) || // Linux binary
StringEndsWith(fileName, NS_LITERAL_STRING(".paf")) || // PortableApps package
//StringEndsWith(fileName, NS_LITERAL_STRING(".out")) || // Linux binary
//StringEndsWith(fileName, NS_LITERAL_STRING(".paf")) || // PortableApps package
//StringEndsWith(fileName, NS_LITERAL_STRING(".paq8f")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".paq8jd")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".paq8l")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".paq8o")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".partial")) || // Downloads
//StringEndsWith(fileName, NS_LITERAL_STRING(".pax")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".pcd")) || // Kodak Picture CD
StringEndsWith(fileName, NS_LITERAL_STRING(".pax")) || // Mac archive
StringEndsWith(fileName, NS_LITERAL_STRING(".pcd")) || // Microsoft Visual Test
StringEndsWith(fileName, NS_LITERAL_STRING(".pdf")) || // Adobe Acrobat
//StringEndsWith(fileName, NS_LITERAL_STRING(".pea")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".pet")) || // Linux package
StringEndsWith(fileName, NS_LITERAL_STRING(".pif")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".pkg")) || // Mac installer
StringEndsWith(fileName, NS_LITERAL_STRING(".pl")) || // Perl script
//StringEndsWith(fileName, NS_LITERAL_STRING(".plg")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".potx")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".ppam")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".ppsx")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".pptm")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".pptx")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".plg")) || // MS Visual Studio
//StringEndsWith(fileName, NS_LITERAL_STRING(".potx")) || // MS PowerPoint
//StringEndsWith(fileName, NS_LITERAL_STRING(".ppam")) || // MS PowerPoint
//StringEndsWith(fileName, NS_LITERAL_STRING(".ppsx")) || // MS PowerPoint
//StringEndsWith(fileName, NS_LITERAL_STRING(".pptm")) || // MS PowerPoint
//StringEndsWith(fileName, NS_LITERAL_STRING(".pptx")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".prf")) || // MS Outlook
//StringEndsWith(fileName, NS_LITERAL_STRING(".prg")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".prg")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".ps1")) || // Windows shell
StringEndsWith(fileName, NS_LITERAL_STRING(".ps1xml")) || // Windows shell
StringEndsWith(fileName, NS_LITERAL_STRING(".ps2")) || // Windows shell
@ -599,12 +598,12 @@ PendingLookup::IsBinaryFile()
//StringEndsWith(fileName, NS_LITERAL_STRING(".r29")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".rar")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".rb")) || // Ruby script
StringEndsWith(fileName, NS_LITERAL_STRING(".reg")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".reg")) || // Windows Registry
StringEndsWith(fileName, NS_LITERAL_STRING(".rels")) || // MS Office
StringEndsWith(fileName, NS_LITERAL_STRING(".rgs")) || // InstallShield
//StringEndsWith(fileName, NS_LITERAL_STRING(".rgs")) || // Windows Registry
StringEndsWith(fileName, NS_LITERAL_STRING(".rpm")) || // Linux package
StringEndsWith(fileName, NS_LITERAL_STRING(".rtf")) || // MS Office
StringEndsWith(fileName, NS_LITERAL_STRING(".run")) || // Linux shell
//StringEndsWith(fileName, NS_LITERAL_STRING(".rtf")) || // MS Office
//StringEndsWith(fileName, NS_LITERAL_STRING(".run")) || // Linux shell
StringEndsWith(fileName, NS_LITERAL_STRING(".scf")) || // Windows shell
StringEndsWith(fileName, NS_LITERAL_STRING(".scr")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".sct")) || // Windows shell
@ -613,13 +612,13 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".shar")) || // Linux shell
StringEndsWith(fileName, NS_LITERAL_STRING(".shb")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".shs")) || // Windows shell
StringEndsWith(fileName, NS_LITERAL_STRING(".sldm")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".sldx")) || // MS PowerPoint
//StringEndsWith(fileName, NS_LITERAL_STRING(".sldm")) || // MS PowerPoint
//StringEndsWith(fileName, NS_LITERAL_STRING(".sldx")) || // MS PowerPoint
StringEndsWith(fileName, NS_LITERAL_STRING(".slp")) || // Linux package
StringEndsWith(fileName, NS_LITERAL_STRING(".smi")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".sparsebundle")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".sparseimage")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".spl")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".spl")) || // Adobe Flash
//StringEndsWith(fileName, NS_LITERAL_STRING(".squashfs")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".svg")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".swf")) || // Adobe Flash
@ -631,12 +630,12 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".tbz2")) || // Linux archive (bzip2)
StringEndsWith(fileName, NS_LITERAL_STRING(".tcsh")) || // Linux shell
StringEndsWith(fileName, NS_LITERAL_STRING(".tgz")) || // Linux archive (gzip)
//StringEndsWith(fileName, NS_LITERAL_STRING(".toast")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".toast")) || // Roxio disk image
//StringEndsWith(fileName, NS_LITERAL_STRING(".torrent")) || // Bittorrent
StringEndsWith(fileName, NS_LITERAL_STRING(".tpz")) || // Linux archive (gzip)
StringEndsWith(fileName, NS_LITERAL_STRING(".txz")) || // Linux archive (xz)
StringEndsWith(fileName, NS_LITERAL_STRING(".tz")) || // Linux archive (gzip)
//StringEndsWith(fileName, NS_LITERAL_STRING(".u3p")) ||
//StringEndsWith(fileName, NS_LITERAL_STRING(".u3p")) || // U3 Smart Apps
StringEndsWith(fileName, NS_LITERAL_STRING(".udf")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".udif")) || // Mac disk image
StringEndsWith(fileName, NS_LITERAL_STRING(".url")) || // Windows
@ -645,7 +644,7 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".vb")) || // Visual Basic script
StringEndsWith(fileName, NS_LITERAL_STRING(".vbe")) || // Visual Basic script
StringEndsWith(fileName, NS_LITERAL_STRING(".vbs")) || // Visual Basic script
StringEndsWith(fileName, NS_LITERAL_STRING(".vbscript")) || // Visual Basic script
//StringEndsWith(fileName, NS_LITERAL_STRING(".vbscript")) || // Visual Basic script
StringEndsWith(fileName, NS_LITERAL_STRING(".vhd")) || // Windows virtual hard drive
StringEndsWith(fileName, NS_LITERAL_STRING(".vhdx")) || // Windows virtual hard drive
StringEndsWith(fileName, NS_LITERAL_STRING(".vmdk")) || // VMware virtual disk
@ -654,21 +653,21 @@ PendingLookup::IsBinaryFile()
StringEndsWith(fileName, NS_LITERAL_STRING(".vss")) || // MS Visio
StringEndsWith(fileName, NS_LITERAL_STRING(".vst")) || // MS Visio
StringEndsWith(fileName, NS_LITERAL_STRING(".vsw")) || // MS Visio
StringEndsWith(fileName, NS_LITERAL_STRING(".website")) || // MSIE
StringEndsWith(fileName, NS_LITERAL_STRING(".website")) || // Windows
StringEndsWith(fileName, NS_LITERAL_STRING(".wim")) || // Windows Imaging
StringEndsWith(fileName, NS_LITERAL_STRING(".workflow")) || // Mac Automator
//StringEndsWith(fileName, NS_LITERAL_STRING(".workflow")) || // Mac Automator
//StringEndsWith(fileName, NS_LITERAL_STRING(".wrc")) || // FreeArc archive
StringEndsWith(fileName, NS_LITERAL_STRING(".ws")) || // Windows script
StringEndsWith(fileName, NS_LITERAL_STRING(".wsc")) || // Windows script
StringEndsWith(fileName, NS_LITERAL_STRING(".wsf")) || // Windows script
StringEndsWith(fileName, NS_LITERAL_STRING(".wsh")) || // Windows script
StringEndsWith(fileName, NS_LITERAL_STRING(".xar")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".xbap")) || // MS Silverlight
//StringEndsWith(fileName, NS_LITERAL_STRING(".xip")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".xlsm")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".xlsx")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".xltm")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".xltx")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".xbap")) || // XAML Browser Application
StringEndsWith(fileName, NS_LITERAL_STRING(".xip")) || // Mac archive
//StringEndsWith(fileName, NS_LITERAL_STRING(".xlsm")) || // MS Excel
//StringEndsWith(fileName, NS_LITERAL_STRING(".xlsx")) || // MS Excel
//StringEndsWith(fileName, NS_LITERAL_STRING(".xltm")) || // MS Excel
//StringEndsWith(fileName, NS_LITERAL_STRING(".xltx")) || // MS Excel
StringEndsWith(fileName, NS_LITERAL_STRING(".xml")) ||
StringEndsWith(fileName, NS_LITERAL_STRING(".xnk")) || // MS Exchange
StringEndsWith(fileName, NS_LITERAL_STRING(".xrm-ms")) || // Windows
@ -705,7 +704,6 @@ PendingLookup::GetDownloadType(const nsAString& aFilename) {
StringEndsWith(aFilename, NS_LITERAL_STRING(".iso")) ||
StringEndsWith(aFilename, NS_LITERAL_STRING(".mpkg")) ||
StringEndsWith(aFilename, NS_LITERAL_STRING(".ndif")) ||
StringEndsWith(aFilename, NS_LITERAL_STRING(".osx")) ||
StringEndsWith(aFilename, NS_LITERAL_STRING(".pkg")) ||
StringEndsWith(aFilename, NS_LITERAL_STRING(".smi")) ||
StringEndsWith(aFilename, NS_LITERAL_STRING(".sparsebundle")) ||

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

@ -36,6 +36,7 @@ void protobuf_ShutdownFile_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2e
delete ClientDownloadRequest_MachOHeaders_LoadCommand::default_instance_;
delete ClientDownloadRequest_ImageHeaders::default_instance_;
delete ClientDownloadRequest_ArchivedBinary::default_instance_;
delete ClientDownloadRequest_URLChainEntry::default_instance_;
delete ClientDownloadResponse::default_instance_;
delete ClientDownloadResponse_MoreInfo::default_instance_;
delete ClientDownloadReport::default_instance_;
@ -109,6 +110,7 @@ void protobuf_AddDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto
ClientDownloadRequest_MachOHeaders_LoadCommand::default_instance_ = new ClientDownloadRequest_MachOHeaders_LoadCommand();
ClientDownloadRequest_ImageHeaders::default_instance_ = new ClientDownloadRequest_ImageHeaders();
ClientDownloadRequest_ArchivedBinary::default_instance_ = new ClientDownloadRequest_ArchivedBinary();
ClientDownloadRequest_URLChainEntry::default_instance_ = new ClientDownloadRequest_URLChainEntry();
ClientDownloadResponse::default_instance_ = new ClientDownloadResponse();
ClientDownloadResponse_MoreInfo::default_instance_ = new ClientDownloadResponse_MoreInfo();
ClientDownloadReport::default_instance_ = new ClientDownloadReport();
@ -168,6 +170,7 @@ void protobuf_AddDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto
ClientDownloadRequest_MachOHeaders_LoadCommand::default_instance_->InitAsDefaultInstance();
ClientDownloadRequest_ImageHeaders::default_instance_->InitAsDefaultInstance();
ClientDownloadRequest_ArchivedBinary::default_instance_->InitAsDefaultInstance();
ClientDownloadRequest_URLChainEntry::default_instance_->InitAsDefaultInstance();
ClientDownloadResponse::default_instance_->InitAsDefaultInstance();
ClientDownloadResponse_MoreInfo::default_instance_->InitAsDefaultInstance();
ClientDownloadReport::default_instance_->InitAsDefaultInstance();
@ -5776,6 +5779,499 @@ void ClientDownloadRequest_ArchivedBinary::Swap(ClientDownloadRequest_ArchivedBi
}
// -------------------------------------------------------------------
bool ClientDownloadRequest_URLChainEntry_URLType_IsValid(int value) {
switch(value) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
return true;
default:
return false;
}
}
#ifndef _MSC_VER
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::DOWNLOAD_URL;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::DOWNLOAD_REFERRER;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::LANDING_PAGE;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::LANDING_REFERRER;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::CLIENT_REDIRECT;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::SERVER_REDIRECT;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::URLType_MIN;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::URLType_MAX;
const int ClientDownloadRequest_URLChainEntry::URLType_ARRAYSIZE;
#endif // _MSC_VER
#ifndef _MSC_VER
const int ClientDownloadRequest_URLChainEntry::kUrlFieldNumber;
const int ClientDownloadRequest_URLChainEntry::kTypeFieldNumber;
const int ClientDownloadRequest_URLChainEntry::kIpAddressFieldNumber;
const int ClientDownloadRequest_URLChainEntry::kReferrerFieldNumber;
const int ClientDownloadRequest_URLChainEntry::kMainFrameReferrerFieldNumber;
const int ClientDownloadRequest_URLChainEntry::kIsRetargetingFieldNumber;
const int ClientDownloadRequest_URLChainEntry::kIsUserInitiatedFieldNumber;
const int ClientDownloadRequest_URLChainEntry::kTimestampInMillisecFieldNumber;
#endif // !_MSC_VER
ClientDownloadRequest_URLChainEntry::ClientDownloadRequest_URLChainEntry()
: ::google::protobuf::MessageLite() {
SharedCtor();
// @@protoc_insertion_point(constructor:safe_browsing.ClientDownloadRequest.URLChainEntry)
}
void ClientDownloadRequest_URLChainEntry::InitAsDefaultInstance() {
}
ClientDownloadRequest_URLChainEntry::ClientDownloadRequest_URLChainEntry(const ClientDownloadRequest_URLChainEntry& from)
: ::google::protobuf::MessageLite() {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:safe_browsing.ClientDownloadRequest.URLChainEntry)
}
void ClientDownloadRequest_URLChainEntry::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
url_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
type_ = 1;
ip_address_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
referrer_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
main_frame_referrer_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
is_retargeting_ = false;
is_user_initiated_ = false;
timestamp_in_millisec_ = 0;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
ClientDownloadRequest_URLChainEntry::~ClientDownloadRequest_URLChainEntry() {
// @@protoc_insertion_point(destructor:safe_browsing.ClientDownloadRequest.URLChainEntry)
SharedDtor();
}
void ClientDownloadRequest_URLChainEntry::SharedDtor() {
if (url_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete url_;
}
if (ip_address_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete ip_address_;
}
if (referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete referrer_;
}
if (main_frame_referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete main_frame_referrer_;
}
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
if (this != &default_instance()) {
#else
if (this != default_instance_) {
#endif
}
}
void ClientDownloadRequest_URLChainEntry::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ClientDownloadRequest_URLChainEntry& ClientDownloadRequest_URLChainEntry::default_instance() {
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
protobuf_AddDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto();
#else
if (default_instance_ == NULL) protobuf_AddDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto();
#endif
return *default_instance_;
}
ClientDownloadRequest_URLChainEntry* ClientDownloadRequest_URLChainEntry::default_instance_ = NULL;
ClientDownloadRequest_URLChainEntry* ClientDownloadRequest_URLChainEntry::New() const {
return new ClientDownloadRequest_URLChainEntry;
}
void ClientDownloadRequest_URLChainEntry::Clear() {
#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
&reinterpret_cast<ClientDownloadRequest_URLChainEntry*>(16)->f) - \
reinterpret_cast<char*>(16))
#define ZR_(first, last) do { \
size_t f = OFFSET_OF_FIELD_(first); \
size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
::memset(&first, 0, n); \
} while (0)
if (_has_bits_[0 / 32] & 255) {
ZR_(is_retargeting_, timestamp_in_millisec_);
if (has_url()) {
if (url_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
url_->clear();
}
}
type_ = 1;
if (has_ip_address()) {
if (ip_address_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
ip_address_->clear();
}
}
if (has_referrer()) {
if (referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
referrer_->clear();
}
}
if (has_main_frame_referrer()) {
if (main_frame_referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
main_frame_referrer_->clear();
}
}
}
#undef OFFSET_OF_FIELD_
#undef ZR_
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->clear();
}
bool ClientDownloadRequest_URLChainEntry::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
::google::protobuf::uint32 tag;
::google::protobuf::io::StringOutputStream unknown_fields_string(
mutable_unknown_fields());
::google::protobuf::io::CodedOutputStream unknown_fields_stream(
&unknown_fields_string);
// @@protoc_insertion_point(parse_start:safe_browsing.ClientDownloadRequest.URLChainEntry)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string url = 1;
case 1: {
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_url()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(16)) goto parse_type;
break;
}
// optional .safe_browsing.ClientDownloadRequest.URLChainEntry.URLType type = 2;
case 2: {
if (tag == 16) {
parse_type:
int value;
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
input, &value)));
if (::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType_IsValid(value)) {
set_type(static_cast< ::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType >(value));
} else {
unknown_fields_stream.WriteVarint32(tag);
unknown_fields_stream.WriteVarint32(value);
}
} else {
goto handle_unusual;
}
if (input->ExpectTag(26)) goto parse_ip_address;
break;
}
// optional string ip_address = 3;
case 3: {
if (tag == 26) {
parse_ip_address:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_ip_address()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(34)) goto parse_referrer;
break;
}
// optional string referrer = 4;
case 4: {
if (tag == 34) {
parse_referrer:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_referrer()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(42)) goto parse_main_frame_referrer;
break;
}
// optional string main_frame_referrer = 5;
case 5: {
if (tag == 42) {
parse_main_frame_referrer:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_main_frame_referrer()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(48)) goto parse_is_retargeting;
break;
}
// optional bool is_retargeting = 6;
case 6: {
if (tag == 48) {
parse_is_retargeting:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
input, &is_retargeting_)));
set_has_is_retargeting();
} else {
goto handle_unusual;
}
if (input->ExpectTag(56)) goto parse_is_user_initiated;
break;
}
// optional bool is_user_initiated = 7;
case 7: {
if (tag == 56) {
parse_is_user_initiated:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
input, &is_user_initiated_)));
set_has_is_user_initiated();
} else {
goto handle_unusual;
}
if (input->ExpectTag(65)) goto parse_timestamp_in_millisec;
break;
}
// optional double timestamp_in_millisec = 8;
case 8: {
if (tag == 65) {
parse_timestamp_in_millisec:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
input, &timestamp_in_millisec_)));
set_has_timestamp_in_millisec();
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
default: {
handle_unusual:
if (tag == 0 ||
::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
goto success;
}
DO_(::google::protobuf::internal::WireFormatLite::SkipField(
input, tag, &unknown_fields_stream));
break;
}
}
}
success:
// @@protoc_insertion_point(parse_success:safe_browsing.ClientDownloadRequest.URLChainEntry)
return true;
failure:
// @@protoc_insertion_point(parse_failure:safe_browsing.ClientDownloadRequest.URLChainEntry)
return false;
#undef DO_
}
void ClientDownloadRequest_URLChainEntry::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// @@protoc_insertion_point(serialize_start:safe_browsing.ClientDownloadRequest.URLChainEntry)
// optional string url = 1;
if (has_url()) {
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->url(), output);
}
// optional .safe_browsing.ClientDownloadRequest.URLChainEntry.URLType type = 2;
if (has_type()) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
2, this->type(), output);
}
// optional string ip_address = 3;
if (has_ip_address()) {
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
3, this->ip_address(), output);
}
// optional string referrer = 4;
if (has_referrer()) {
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
4, this->referrer(), output);
}
// optional string main_frame_referrer = 5;
if (has_main_frame_referrer()) {
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
5, this->main_frame_referrer(), output);
}
// optional bool is_retargeting = 6;
if (has_is_retargeting()) {
::google::protobuf::internal::WireFormatLite::WriteBool(6, this->is_retargeting(), output);
}
// optional bool is_user_initiated = 7;
if (has_is_user_initiated()) {
::google::protobuf::internal::WireFormatLite::WriteBool(7, this->is_user_initiated(), output);
}
// optional double timestamp_in_millisec = 8;
if (has_timestamp_in_millisec()) {
::google::protobuf::internal::WireFormatLite::WriteDouble(8, this->timestamp_in_millisec(), output);
}
output->WriteRaw(unknown_fields().data(),
unknown_fields().size());
// @@protoc_insertion_point(serialize_end:safe_browsing.ClientDownloadRequest.URLChainEntry)
}
int ClientDownloadRequest_URLChainEntry::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string url = 1;
if (has_url()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->url());
}
// optional .safe_browsing.ClientDownloadRequest.URLChainEntry.URLType type = 2;
if (has_type()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
}
// optional string ip_address = 3;
if (has_ip_address()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->ip_address());
}
// optional string referrer = 4;
if (has_referrer()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->referrer());
}
// optional string main_frame_referrer = 5;
if (has_main_frame_referrer()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->main_frame_referrer());
}
// optional bool is_retargeting = 6;
if (has_is_retargeting()) {
total_size += 1 + 1;
}
// optional bool is_user_initiated = 7;
if (has_is_user_initiated()) {
total_size += 1 + 1;
}
// optional double timestamp_in_millisec = 8;
if (has_timestamp_in_millisec()) {
total_size += 1 + 8;
}
}
total_size += unknown_fields().size();
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void ClientDownloadRequest_URLChainEntry::CheckTypeAndMergeFrom(
const ::google::protobuf::MessageLite& from) {
MergeFrom(*::google::protobuf::down_cast<const ClientDownloadRequest_URLChainEntry*>(&from));
}
void ClientDownloadRequest_URLChainEntry::MergeFrom(const ClientDownloadRequest_URLChainEntry& from) {
GOOGLE_CHECK_NE(&from, this);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_url()) {
set_url(from.url());
}
if (from.has_type()) {
set_type(from.type());
}
if (from.has_ip_address()) {
set_ip_address(from.ip_address());
}
if (from.has_referrer()) {
set_referrer(from.referrer());
}
if (from.has_main_frame_referrer()) {
set_main_frame_referrer(from.main_frame_referrer());
}
if (from.has_is_retargeting()) {
set_is_retargeting(from.is_retargeting());
}
if (from.has_is_user_initiated()) {
set_is_user_initiated(from.is_user_initiated());
}
if (from.has_timestamp_in_millisec()) {
set_timestamp_in_millisec(from.timestamp_in_millisec());
}
}
mutable_unknown_fields()->append(from.unknown_fields());
}
void ClientDownloadRequest_URLChainEntry::CopyFrom(const ClientDownloadRequest_URLChainEntry& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
bool ClientDownloadRequest_URLChainEntry::IsInitialized() const {
return true;
}
void ClientDownloadRequest_URLChainEntry::Swap(ClientDownloadRequest_URLChainEntry* other) {
if (other != this) {
std::swap(url_, other->url_);
std::swap(type_, other->type_);
std::swap(ip_address_, other->ip_address_);
std::swap(referrer_, other->referrer_);
std::swap(main_frame_referrer_, other->main_frame_referrer_);
std::swap(is_retargeting_, other->is_retargeting_);
std::swap(is_user_initiated_, other->is_user_initiated_);
std::swap(timestamp_in_millisec_, other->timestamp_in_millisec_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.swap(other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);
}
}
::std::string ClientDownloadRequest_URLChainEntry::GetTypeName() const {
return "safe_browsing.ClientDownloadRequest.URLChainEntry";
}
// -------------------------------------------------------------------
#ifndef _MSC_VER
@ -5795,6 +6291,7 @@ const int ClientDownloadRequest::kArchiveValidFieldNumber;
const int ClientDownloadRequest::kSkippedUrlWhitelistFieldNumber;
const int ClientDownloadRequest::kSkippedCertificateWhitelistFieldNumber;
const int ClientDownloadRequest::kAlternateExtensionsFieldNumber;
const int ClientDownloadRequest::kUrlChainFieldNumber;
#endif // !_MSC_VER
ClientDownloadRequest::ClientDownloadRequest()
@ -5955,6 +6452,7 @@ void ClientDownloadRequest::Clear() {
resources_.Clear();
archived_binary_.Clear();
alternate_extensions_.Clear();
url_chain_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->clear();
}
@ -6183,20 +6681,34 @@ bool ClientDownloadRequest::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(258)) goto parse_alternate_extensions;
if (input->ExpectTag(282)) goto parse_alternate_extensions;
break;
}
// repeated string alternate_extensions = 32;
case 32: {
if (tag == 258) {
// repeated string alternate_extensions = 35;
case 35: {
if (tag == 282) {
parse_alternate_extensions:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->add_alternate_extensions()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(258)) goto parse_alternate_extensions;
if (input->ExpectTag(282)) goto parse_alternate_extensions;
if (input->ExpectTag(290)) goto parse_url_chain;
break;
}
// repeated .safe_browsing.ClientDownloadRequest.URLChainEntry url_chain = 36;
case 36: {
if (tag == 290) {
parse_url_chain:
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
input, add_url_chain()));
} else {
goto handle_unusual;
}
if (input->ExpectTag(290)) goto parse_url_chain;
if (input->ExpectAtEnd()) goto success;
break;
}
@ -6311,10 +6823,16 @@ void ClientDownloadRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(31, this->skipped_certificate_whitelist(), output);
}
// repeated string alternate_extensions = 32;
// repeated string alternate_extensions = 35;
for (int i = 0; i < this->alternate_extensions_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteString(
32, this->alternate_extensions(i), output);
35, this->alternate_extensions(i), output);
}
// repeated .safe_browsing.ClientDownloadRequest.URLChainEntry url_chain = 36;
for (int i = 0; i < this->url_chain_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessage(
36, this->url_chain(i), output);
}
output->WriteRaw(unknown_fields().data(),
@ -6427,13 +6945,21 @@ int ClientDownloadRequest::ByteSize() const {
this->archived_binary(i));
}
// repeated string alternate_extensions = 32;
// repeated string alternate_extensions = 35;
total_size += 2 * this->alternate_extensions_size();
for (int i = 0; i < this->alternate_extensions_size(); i++) {
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
this->alternate_extensions(i));
}
// repeated .safe_browsing.ClientDownloadRequest.URLChainEntry url_chain = 36;
total_size += 2 * this->url_chain_size();
for (int i = 0; i < this->url_chain_size(); i++) {
total_size +=
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->url_chain(i));
}
total_size += unknown_fields().size();
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
@ -6452,6 +6978,7 @@ void ClientDownloadRequest::MergeFrom(const ClientDownloadRequest& from) {
resources_.MergeFrom(from.resources_);
archived_binary_.MergeFrom(from.archived_binary_);
alternate_extensions_.MergeFrom(from.alternate_extensions_);
url_chain_.MergeFrom(from.url_chain_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_url()) {
set_url(from.url());
@ -6536,6 +7063,7 @@ void ClientDownloadRequest::Swap(ClientDownloadRequest* other) {
std::swap(skipped_url_whitelist_, other->skipped_url_whitelist_);
std::swap(skipped_certificate_whitelist_, other->skipped_certificate_whitelist_);
alternate_extensions_.Swap(&other->alternate_extensions_);
url_chain_.Swap(&other->url_chain_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.swap(other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);
@ -6919,7 +7447,7 @@ bool ClientDownloadResponse::MergePartialFromCodedStream(
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// required .safe_browsing.ClientDownloadResponse.Verdict verdict = 1;
// optional .safe_browsing.ClientDownloadResponse.Verdict verdict = 1 [default = SAFE];
case 1: {
if (tag == 8) {
int value;
@ -6990,7 +7518,7 @@ failure:
void ClientDownloadResponse::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// @@protoc_insertion_point(serialize_start:safe_browsing.ClientDownloadResponse)
// required .safe_browsing.ClientDownloadResponse.Verdict verdict = 1;
// optional .safe_browsing.ClientDownloadResponse.Verdict verdict = 1 [default = SAFE];
if (has_verdict()) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
1, this->verdict(), output);
@ -7017,7 +7545,7 @@ int ClientDownloadResponse::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// required .safe_browsing.ClientDownloadResponse.Verdict verdict = 1;
// optional .safe_browsing.ClientDownloadResponse.Verdict verdict = 1 [default = SAFE];
if (has_verdict()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->verdict());
@ -7074,7 +7602,6 @@ void ClientDownloadResponse::CopyFrom(const ClientDownloadResponse& from) {
}
bool ClientDownloadResponse::IsInitialized() const {
if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
return true;
}
@ -7660,9 +8187,6 @@ bool ClientDownloadReport::IsInitialized() const {
if (has_download_request()) {
if (!this->download_request().IsInitialized()) return false;
}
if (has_download_response()) {
if (!this->download_response().IsInitialized()) return false;
}
return true;
}

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

@ -52,6 +52,7 @@ class ClientDownloadRequest_MachOHeaders;
class ClientDownloadRequest_MachOHeaders_LoadCommand;
class ClientDownloadRequest_ImageHeaders;
class ClientDownloadRequest_ArchivedBinary;
class ClientDownloadRequest_URLChainEntry;
class ClientDownloadResponse;
class ClientDownloadResponse_MoreInfo;
class ClientDownloadReport;
@ -102,6 +103,19 @@ const ChromeUserPopulation_UserPopulation ChromeUserPopulation_UserPopulation_Us
const ChromeUserPopulation_UserPopulation ChromeUserPopulation_UserPopulation_UserPopulation_MAX = ChromeUserPopulation_UserPopulation_EXTENDED_REPORTING;
const int ChromeUserPopulation_UserPopulation_UserPopulation_ARRAYSIZE = ChromeUserPopulation_UserPopulation_UserPopulation_MAX + 1;
enum ClientDownloadRequest_URLChainEntry_URLType {
ClientDownloadRequest_URLChainEntry_URLType_DOWNLOAD_URL = 1,
ClientDownloadRequest_URLChainEntry_URLType_DOWNLOAD_REFERRER = 2,
ClientDownloadRequest_URLChainEntry_URLType_LANDING_PAGE = 3,
ClientDownloadRequest_URLChainEntry_URLType_LANDING_REFERRER = 4,
ClientDownloadRequest_URLChainEntry_URLType_CLIENT_REDIRECT = 5,
ClientDownloadRequest_URLChainEntry_URLType_SERVER_REDIRECT = 6
};
bool ClientDownloadRequest_URLChainEntry_URLType_IsValid(int value);
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry_URLType_URLType_MIN = ClientDownloadRequest_URLChainEntry_URLType_DOWNLOAD_URL;
const ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry_URLType_URLType_MAX = ClientDownloadRequest_URLChainEntry_URLType_SERVER_REDIRECT;
const int ClientDownloadRequest_URLChainEntry_URLType_URLType_ARRAYSIZE = ClientDownloadRequest_URLChainEntry_URLType_URLType_MAX + 1;
enum ClientDownloadRequest_ResourceType {
ClientDownloadRequest_ResourceType_DOWNLOAD_URL = 0,
ClientDownloadRequest_ResourceType_DOWNLOAD_REDIRECT = 1,
@ -2676,6 +2690,204 @@ class ClientDownloadRequest_ArchivedBinary : public ::google::protobuf::MessageL
};
// -------------------------------------------------------------------
class ClientDownloadRequest_URLChainEntry : public ::google::protobuf::MessageLite {
public:
ClientDownloadRequest_URLChainEntry();
virtual ~ClientDownloadRequest_URLChainEntry();
ClientDownloadRequest_URLChainEntry(const ClientDownloadRequest_URLChainEntry& from);
inline ClientDownloadRequest_URLChainEntry& operator=(const ClientDownloadRequest_URLChainEntry& from) {
CopyFrom(from);
return *this;
}
inline const ::std::string& unknown_fields() const {
return _unknown_fields_;
}
inline ::std::string* mutable_unknown_fields() {
return &_unknown_fields_;
}
static const ClientDownloadRequest_URLChainEntry& default_instance();
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
// Returns the internal default instance pointer. This function can
// return NULL thus should not be used by the user. This is intended
// for Protobuf internal code. Please use default_instance() declared
// above instead.
static inline const ClientDownloadRequest_URLChainEntry* internal_default_instance() {
return default_instance_;
}
#endif
void Swap(ClientDownloadRequest_URLChainEntry* other);
// implements Message ----------------------------------------------
ClientDownloadRequest_URLChainEntry* New() const;
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
void CopyFrom(const ClientDownloadRequest_URLChainEntry& from);
void MergeFrom(const ClientDownloadRequest_URLChainEntry& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
void DiscardUnknownFields();
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
public:
::std::string GetTypeName() const;
// nested types ----------------------------------------------------
typedef ClientDownloadRequest_URLChainEntry_URLType URLType;
static const URLType DOWNLOAD_URL = ClientDownloadRequest_URLChainEntry_URLType_DOWNLOAD_URL;
static const URLType DOWNLOAD_REFERRER = ClientDownloadRequest_URLChainEntry_URLType_DOWNLOAD_REFERRER;
static const URLType LANDING_PAGE = ClientDownloadRequest_URLChainEntry_URLType_LANDING_PAGE;
static const URLType LANDING_REFERRER = ClientDownloadRequest_URLChainEntry_URLType_LANDING_REFERRER;
static const URLType CLIENT_REDIRECT = ClientDownloadRequest_URLChainEntry_URLType_CLIENT_REDIRECT;
static const URLType SERVER_REDIRECT = ClientDownloadRequest_URLChainEntry_URLType_SERVER_REDIRECT;
static inline bool URLType_IsValid(int value) {
return ClientDownloadRequest_URLChainEntry_URLType_IsValid(value);
}
static const URLType URLType_MIN =
ClientDownloadRequest_URLChainEntry_URLType_URLType_MIN;
static const URLType URLType_MAX =
ClientDownloadRequest_URLChainEntry_URLType_URLType_MAX;
static const int URLType_ARRAYSIZE =
ClientDownloadRequest_URLChainEntry_URLType_URLType_ARRAYSIZE;
// accessors -------------------------------------------------------
// optional string url = 1;
inline bool has_url() const;
inline void clear_url();
static const int kUrlFieldNumber = 1;
inline const ::std::string& url() const;
inline void set_url(const ::std::string& value);
inline void set_url(const char* value);
inline void set_url(const char* value, size_t size);
inline ::std::string* mutable_url();
inline ::std::string* release_url();
inline void set_allocated_url(::std::string* url);
// optional .safe_browsing.ClientDownloadRequest.URLChainEntry.URLType type = 2;
inline bool has_type() const;
inline void clear_type();
static const int kTypeFieldNumber = 2;
inline ::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType type() const;
inline void set_type(::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType value);
// optional string ip_address = 3;
inline bool has_ip_address() const;
inline void clear_ip_address();
static const int kIpAddressFieldNumber = 3;
inline const ::std::string& ip_address() const;
inline void set_ip_address(const ::std::string& value);
inline void set_ip_address(const char* value);
inline void set_ip_address(const char* value, size_t size);
inline ::std::string* mutable_ip_address();
inline ::std::string* release_ip_address();
inline void set_allocated_ip_address(::std::string* ip_address);
// optional string referrer = 4;
inline bool has_referrer() const;
inline void clear_referrer();
static const int kReferrerFieldNumber = 4;
inline const ::std::string& referrer() const;
inline void set_referrer(const ::std::string& value);
inline void set_referrer(const char* value);
inline void set_referrer(const char* value, size_t size);
inline ::std::string* mutable_referrer();
inline ::std::string* release_referrer();
inline void set_allocated_referrer(::std::string* referrer);
// optional string main_frame_referrer = 5;
inline bool has_main_frame_referrer() const;
inline void clear_main_frame_referrer();
static const int kMainFrameReferrerFieldNumber = 5;
inline const ::std::string& main_frame_referrer() const;
inline void set_main_frame_referrer(const ::std::string& value);
inline void set_main_frame_referrer(const char* value);
inline void set_main_frame_referrer(const char* value, size_t size);
inline ::std::string* mutable_main_frame_referrer();
inline ::std::string* release_main_frame_referrer();
inline void set_allocated_main_frame_referrer(::std::string* main_frame_referrer);
// optional bool is_retargeting = 6;
inline bool has_is_retargeting() const;
inline void clear_is_retargeting();
static const int kIsRetargetingFieldNumber = 6;
inline bool is_retargeting() const;
inline void set_is_retargeting(bool value);
// optional bool is_user_initiated = 7;
inline bool has_is_user_initiated() const;
inline void clear_is_user_initiated();
static const int kIsUserInitiatedFieldNumber = 7;
inline bool is_user_initiated() const;
inline void set_is_user_initiated(bool value);
// optional double timestamp_in_millisec = 8;
inline bool has_timestamp_in_millisec() const;
inline void clear_timestamp_in_millisec();
static const int kTimestampInMillisecFieldNumber = 8;
inline double timestamp_in_millisec() const;
inline void set_timestamp_in_millisec(double value);
// @@protoc_insertion_point(class_scope:safe_browsing.ClientDownloadRequest.URLChainEntry)
private:
inline void set_has_url();
inline void clear_has_url();
inline void set_has_type();
inline void clear_has_type();
inline void set_has_ip_address();
inline void clear_has_ip_address();
inline void set_has_referrer();
inline void clear_has_referrer();
inline void set_has_main_frame_referrer();
inline void clear_has_main_frame_referrer();
inline void set_has_is_retargeting();
inline void clear_has_is_retargeting();
inline void set_has_is_user_initiated();
inline void clear_has_is_user_initiated();
inline void set_has_timestamp_in_millisec();
inline void clear_has_timestamp_in_millisec();
::std::string _unknown_fields_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::std::string* url_;
::std::string* ip_address_;
::std::string* referrer_;
::std::string* main_frame_referrer_;
int type_;
bool is_retargeting_;
bool is_user_initiated_;
double timestamp_in_millisec_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
friend void protobuf_AddDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto_impl();
#else
friend void protobuf_AddDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto();
#endif
friend void protobuf_AssignDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto();
friend void protobuf_ShutdownFile_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto();
void InitAsDefaultInstance();
static ClientDownloadRequest_URLChainEntry* default_instance_;
};
// -------------------------------------------------------------------
class ClientDownloadRequest : public ::google::protobuf::MessageLite {
public:
ClientDownloadRequest();
@ -2744,6 +2956,7 @@ class ClientDownloadRequest : public ::google::protobuf::MessageLite {
typedef ClientDownloadRequest_MachOHeaders MachOHeaders;
typedef ClientDownloadRequest_ImageHeaders ImageHeaders;
typedef ClientDownloadRequest_ArchivedBinary ArchivedBinary;
typedef ClientDownloadRequest_URLChainEntry URLChainEntry;
typedef ClientDownloadRequest_ResourceType ResourceType;
static const ResourceType DOWNLOAD_URL = ClientDownloadRequest_ResourceType_DOWNLOAD_URL;
@ -2924,10 +3137,10 @@ class ClientDownloadRequest : public ::google::protobuf::MessageLite {
inline bool skipped_certificate_whitelist() const;
inline void set_skipped_certificate_whitelist(bool value);
// repeated string alternate_extensions = 32;
// repeated string alternate_extensions = 35;
inline int alternate_extensions_size() const;
inline void clear_alternate_extensions();
static const int kAlternateExtensionsFieldNumber = 32;
static const int kAlternateExtensionsFieldNumber = 35;
inline const ::std::string& alternate_extensions(int index) const;
inline ::std::string* mutable_alternate_extensions(int index);
inline void set_alternate_extensions(int index, const ::std::string& value);
@ -2940,6 +3153,18 @@ class ClientDownloadRequest : public ::google::protobuf::MessageLite {
inline const ::google::protobuf::RepeatedPtrField< ::std::string>& alternate_extensions() const;
inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_alternate_extensions();
// repeated .safe_browsing.ClientDownloadRequest.URLChainEntry url_chain = 36;
inline int url_chain_size() const;
inline void clear_url_chain();
static const int kUrlChainFieldNumber = 36;
inline const ::safe_browsing::ClientDownloadRequest_URLChainEntry& url_chain(int index) const;
inline ::safe_browsing::ClientDownloadRequest_URLChainEntry* mutable_url_chain(int index);
inline ::safe_browsing::ClientDownloadRequest_URLChainEntry* add_url_chain();
inline const ::google::protobuf::RepeatedPtrField< ::safe_browsing::ClientDownloadRequest_URLChainEntry >&
url_chain() const;
inline ::google::protobuf::RepeatedPtrField< ::safe_browsing::ClientDownloadRequest_URLChainEntry >*
mutable_url_chain();
// @@protoc_insertion_point(class_scope:safe_browsing.ClientDownloadRequest)
private:
inline void set_has_url();
@ -2989,6 +3214,7 @@ class ClientDownloadRequest : public ::google::protobuf::MessageLite {
bool skipped_certificate_whitelist_;
::safe_browsing::ChromeUserPopulation* population_;
::google::protobuf::RepeatedPtrField< ::std::string> alternate_extensions_;
::google::protobuf::RepeatedPtrField< ::safe_browsing::ClientDownloadRequest_URLChainEntry > url_chain_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
friend void protobuf_AddDesc_chromium_2fchrome_2fcommon_2fsafe_5fbrowsing_2fcsd_2eproto_impl();
#else
@ -3193,7 +3419,7 @@ class ClientDownloadResponse : public ::google::protobuf::MessageLite {
// accessors -------------------------------------------------------
// required .safe_browsing.ClientDownloadResponse.Verdict verdict = 1;
// optional .safe_browsing.ClientDownloadResponse.Verdict verdict = 1 [default = SAFE];
inline bool has_verdict() const;
inline void clear_verdict();
static const int kVerdictFieldNumber = 1;
@ -12057,6 +12283,411 @@ inline void ClientDownloadRequest_ArchivedBinary::set_allocated_image_headers(::
// -------------------------------------------------------------------
// ClientDownloadRequest_URLChainEntry
// optional string url = 1;
inline bool ClientDownloadRequest_URLChainEntry::has_url() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_url() {
_has_bits_[0] |= 0x00000001u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_url() {
_has_bits_[0] &= ~0x00000001u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_url() {
if (url_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
url_->clear();
}
clear_has_url();
}
inline const ::std::string& ClientDownloadRequest_URLChainEntry::url() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.url)
return *url_;
}
inline void ClientDownloadRequest_URLChainEntry::set_url(const ::std::string& value) {
set_has_url();
if (url_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
url_ = new ::std::string;
}
url_->assign(value);
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.url)
}
inline void ClientDownloadRequest_URLChainEntry::set_url(const char* value) {
set_has_url();
if (url_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
url_ = new ::std::string;
}
url_->assign(value);
// @@protoc_insertion_point(field_set_char:safe_browsing.ClientDownloadRequest.URLChainEntry.url)
}
inline void ClientDownloadRequest_URLChainEntry::set_url(const char* value, size_t size) {
set_has_url();
if (url_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
url_ = new ::std::string;
}
url_->assign(reinterpret_cast<const char*>(value), size);
// @@protoc_insertion_point(field_set_pointer:safe_browsing.ClientDownloadRequest.URLChainEntry.url)
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::mutable_url() {
set_has_url();
if (url_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
url_ = new ::std::string;
}
// @@protoc_insertion_point(field_mutable:safe_browsing.ClientDownloadRequest.URLChainEntry.url)
return url_;
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::release_url() {
clear_has_url();
if (url_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = url_;
url_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return temp;
}
}
inline void ClientDownloadRequest_URLChainEntry::set_allocated_url(::std::string* url) {
if (url_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete url_;
}
if (url) {
set_has_url();
url_ = url;
} else {
clear_has_url();
url_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
// @@protoc_insertion_point(field_set_allocated:safe_browsing.ClientDownloadRequest.URLChainEntry.url)
}
// optional .safe_browsing.ClientDownloadRequest.URLChainEntry.URLType type = 2;
inline bool ClientDownloadRequest_URLChainEntry::has_type() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_type() {
_has_bits_[0] |= 0x00000002u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_type() {
_has_bits_[0] &= ~0x00000002u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_type() {
type_ = 1;
clear_has_type();
}
inline ::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType ClientDownloadRequest_URLChainEntry::type() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.type)
return static_cast< ::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType >(type_);
}
inline void ClientDownloadRequest_URLChainEntry::set_type(::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType value) {
assert(::safe_browsing::ClientDownloadRequest_URLChainEntry_URLType_IsValid(value));
set_has_type();
type_ = value;
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.type)
}
// optional string ip_address = 3;
inline bool ClientDownloadRequest_URLChainEntry::has_ip_address() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_ip_address() {
_has_bits_[0] |= 0x00000004u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_ip_address() {
_has_bits_[0] &= ~0x00000004u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_ip_address() {
if (ip_address_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
ip_address_->clear();
}
clear_has_ip_address();
}
inline const ::std::string& ClientDownloadRequest_URLChainEntry::ip_address() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.ip_address)
return *ip_address_;
}
inline void ClientDownloadRequest_URLChainEntry::set_ip_address(const ::std::string& value) {
set_has_ip_address();
if (ip_address_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
ip_address_ = new ::std::string;
}
ip_address_->assign(value);
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.ip_address)
}
inline void ClientDownloadRequest_URLChainEntry::set_ip_address(const char* value) {
set_has_ip_address();
if (ip_address_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
ip_address_ = new ::std::string;
}
ip_address_->assign(value);
// @@protoc_insertion_point(field_set_char:safe_browsing.ClientDownloadRequest.URLChainEntry.ip_address)
}
inline void ClientDownloadRequest_URLChainEntry::set_ip_address(const char* value, size_t size) {
set_has_ip_address();
if (ip_address_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
ip_address_ = new ::std::string;
}
ip_address_->assign(reinterpret_cast<const char*>(value), size);
// @@protoc_insertion_point(field_set_pointer:safe_browsing.ClientDownloadRequest.URLChainEntry.ip_address)
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::mutable_ip_address() {
set_has_ip_address();
if (ip_address_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
ip_address_ = new ::std::string;
}
// @@protoc_insertion_point(field_mutable:safe_browsing.ClientDownloadRequest.URLChainEntry.ip_address)
return ip_address_;
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::release_ip_address() {
clear_has_ip_address();
if (ip_address_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = ip_address_;
ip_address_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return temp;
}
}
inline void ClientDownloadRequest_URLChainEntry::set_allocated_ip_address(::std::string* ip_address) {
if (ip_address_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete ip_address_;
}
if (ip_address) {
set_has_ip_address();
ip_address_ = ip_address;
} else {
clear_has_ip_address();
ip_address_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
// @@protoc_insertion_point(field_set_allocated:safe_browsing.ClientDownloadRequest.URLChainEntry.ip_address)
}
// optional string referrer = 4;
inline bool ClientDownloadRequest_URLChainEntry::has_referrer() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_referrer() {
_has_bits_[0] |= 0x00000008u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_referrer() {
_has_bits_[0] &= ~0x00000008u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_referrer() {
if (referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
referrer_->clear();
}
clear_has_referrer();
}
inline const ::std::string& ClientDownloadRequest_URLChainEntry::referrer() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.referrer)
return *referrer_;
}
inline void ClientDownloadRequest_URLChainEntry::set_referrer(const ::std::string& value) {
set_has_referrer();
if (referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
referrer_ = new ::std::string;
}
referrer_->assign(value);
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.referrer)
}
inline void ClientDownloadRequest_URLChainEntry::set_referrer(const char* value) {
set_has_referrer();
if (referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
referrer_ = new ::std::string;
}
referrer_->assign(value);
// @@protoc_insertion_point(field_set_char:safe_browsing.ClientDownloadRequest.URLChainEntry.referrer)
}
inline void ClientDownloadRequest_URLChainEntry::set_referrer(const char* value, size_t size) {
set_has_referrer();
if (referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
referrer_ = new ::std::string;
}
referrer_->assign(reinterpret_cast<const char*>(value), size);
// @@protoc_insertion_point(field_set_pointer:safe_browsing.ClientDownloadRequest.URLChainEntry.referrer)
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::mutable_referrer() {
set_has_referrer();
if (referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
referrer_ = new ::std::string;
}
// @@protoc_insertion_point(field_mutable:safe_browsing.ClientDownloadRequest.URLChainEntry.referrer)
return referrer_;
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::release_referrer() {
clear_has_referrer();
if (referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = referrer_;
referrer_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return temp;
}
}
inline void ClientDownloadRequest_URLChainEntry::set_allocated_referrer(::std::string* referrer) {
if (referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete referrer_;
}
if (referrer) {
set_has_referrer();
referrer_ = referrer;
} else {
clear_has_referrer();
referrer_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
// @@protoc_insertion_point(field_set_allocated:safe_browsing.ClientDownloadRequest.URLChainEntry.referrer)
}
// optional string main_frame_referrer = 5;
inline bool ClientDownloadRequest_URLChainEntry::has_main_frame_referrer() const {
return (_has_bits_[0] & 0x00000010u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_main_frame_referrer() {
_has_bits_[0] |= 0x00000010u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_main_frame_referrer() {
_has_bits_[0] &= ~0x00000010u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_main_frame_referrer() {
if (main_frame_referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
main_frame_referrer_->clear();
}
clear_has_main_frame_referrer();
}
inline const ::std::string& ClientDownloadRequest_URLChainEntry::main_frame_referrer() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.main_frame_referrer)
return *main_frame_referrer_;
}
inline void ClientDownloadRequest_URLChainEntry::set_main_frame_referrer(const ::std::string& value) {
set_has_main_frame_referrer();
if (main_frame_referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
main_frame_referrer_ = new ::std::string;
}
main_frame_referrer_->assign(value);
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.main_frame_referrer)
}
inline void ClientDownloadRequest_URLChainEntry::set_main_frame_referrer(const char* value) {
set_has_main_frame_referrer();
if (main_frame_referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
main_frame_referrer_ = new ::std::string;
}
main_frame_referrer_->assign(value);
// @@protoc_insertion_point(field_set_char:safe_browsing.ClientDownloadRequest.URLChainEntry.main_frame_referrer)
}
inline void ClientDownloadRequest_URLChainEntry::set_main_frame_referrer(const char* value, size_t size) {
set_has_main_frame_referrer();
if (main_frame_referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
main_frame_referrer_ = new ::std::string;
}
main_frame_referrer_->assign(reinterpret_cast<const char*>(value), size);
// @@protoc_insertion_point(field_set_pointer:safe_browsing.ClientDownloadRequest.URLChainEntry.main_frame_referrer)
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::mutable_main_frame_referrer() {
set_has_main_frame_referrer();
if (main_frame_referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
main_frame_referrer_ = new ::std::string;
}
// @@protoc_insertion_point(field_mutable:safe_browsing.ClientDownloadRequest.URLChainEntry.main_frame_referrer)
return main_frame_referrer_;
}
inline ::std::string* ClientDownloadRequest_URLChainEntry::release_main_frame_referrer() {
clear_has_main_frame_referrer();
if (main_frame_referrer_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = main_frame_referrer_;
main_frame_referrer_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return temp;
}
}
inline void ClientDownloadRequest_URLChainEntry::set_allocated_main_frame_referrer(::std::string* main_frame_referrer) {
if (main_frame_referrer_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete main_frame_referrer_;
}
if (main_frame_referrer) {
set_has_main_frame_referrer();
main_frame_referrer_ = main_frame_referrer;
} else {
clear_has_main_frame_referrer();
main_frame_referrer_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
// @@protoc_insertion_point(field_set_allocated:safe_browsing.ClientDownloadRequest.URLChainEntry.main_frame_referrer)
}
// optional bool is_retargeting = 6;
inline bool ClientDownloadRequest_URLChainEntry::has_is_retargeting() const {
return (_has_bits_[0] & 0x00000020u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_is_retargeting() {
_has_bits_[0] |= 0x00000020u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_is_retargeting() {
_has_bits_[0] &= ~0x00000020u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_is_retargeting() {
is_retargeting_ = false;
clear_has_is_retargeting();
}
inline bool ClientDownloadRequest_URLChainEntry::is_retargeting() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.is_retargeting)
return is_retargeting_;
}
inline void ClientDownloadRequest_URLChainEntry::set_is_retargeting(bool value) {
set_has_is_retargeting();
is_retargeting_ = value;
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.is_retargeting)
}
// optional bool is_user_initiated = 7;
inline bool ClientDownloadRequest_URLChainEntry::has_is_user_initiated() const {
return (_has_bits_[0] & 0x00000040u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_is_user_initiated() {
_has_bits_[0] |= 0x00000040u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_is_user_initiated() {
_has_bits_[0] &= ~0x00000040u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_is_user_initiated() {
is_user_initiated_ = false;
clear_has_is_user_initiated();
}
inline bool ClientDownloadRequest_URLChainEntry::is_user_initiated() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.is_user_initiated)
return is_user_initiated_;
}
inline void ClientDownloadRequest_URLChainEntry::set_is_user_initiated(bool value) {
set_has_is_user_initiated();
is_user_initiated_ = value;
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.is_user_initiated)
}
// optional double timestamp_in_millisec = 8;
inline bool ClientDownloadRequest_URLChainEntry::has_timestamp_in_millisec() const {
return (_has_bits_[0] & 0x00000080u) != 0;
}
inline void ClientDownloadRequest_URLChainEntry::set_has_timestamp_in_millisec() {
_has_bits_[0] |= 0x00000080u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_has_timestamp_in_millisec() {
_has_bits_[0] &= ~0x00000080u;
}
inline void ClientDownloadRequest_URLChainEntry::clear_timestamp_in_millisec() {
timestamp_in_millisec_ = 0;
clear_has_timestamp_in_millisec();
}
inline double ClientDownloadRequest_URLChainEntry::timestamp_in_millisec() const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.URLChainEntry.timestamp_in_millisec)
return timestamp_in_millisec_;
}
inline void ClientDownloadRequest_URLChainEntry::set_timestamp_in_millisec(double value) {
set_has_timestamp_in_millisec();
timestamp_in_millisec_ = value;
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.URLChainEntry.timestamp_in_millisec)
}
// -------------------------------------------------------------------
// ClientDownloadRequest
// required string url = 1;
@ -12672,7 +13303,7 @@ inline void ClientDownloadRequest::set_skipped_certificate_whitelist(bool value)
// @@protoc_insertion_point(field_set:safe_browsing.ClientDownloadRequest.skipped_certificate_whitelist)
}
// repeated string alternate_extensions = 32;
// repeated string alternate_extensions = 35;
inline int ClientDownloadRequest::alternate_extensions_size() const {
return alternate_extensions_.size();
}
@ -12726,6 +13357,36 @@ ClientDownloadRequest::mutable_alternate_extensions() {
return &alternate_extensions_;
}
// repeated .safe_browsing.ClientDownloadRequest.URLChainEntry url_chain = 36;
inline int ClientDownloadRequest::url_chain_size() const {
return url_chain_.size();
}
inline void ClientDownloadRequest::clear_url_chain() {
url_chain_.Clear();
}
inline const ::safe_browsing::ClientDownloadRequest_URLChainEntry& ClientDownloadRequest::url_chain(int index) const {
// @@protoc_insertion_point(field_get:safe_browsing.ClientDownloadRequest.url_chain)
return url_chain_.Get(index);
}
inline ::safe_browsing::ClientDownloadRequest_URLChainEntry* ClientDownloadRequest::mutable_url_chain(int index) {
// @@protoc_insertion_point(field_mutable:safe_browsing.ClientDownloadRequest.url_chain)
return url_chain_.Mutable(index);
}
inline ::safe_browsing::ClientDownloadRequest_URLChainEntry* ClientDownloadRequest::add_url_chain() {
// @@protoc_insertion_point(field_add:safe_browsing.ClientDownloadRequest.url_chain)
return url_chain_.Add();
}
inline const ::google::protobuf::RepeatedPtrField< ::safe_browsing::ClientDownloadRequest_URLChainEntry >&
ClientDownloadRequest::url_chain() const {
// @@protoc_insertion_point(field_list:safe_browsing.ClientDownloadRequest.url_chain)
return url_chain_;
}
inline ::google::protobuf::RepeatedPtrField< ::safe_browsing::ClientDownloadRequest_URLChainEntry >*
ClientDownloadRequest::mutable_url_chain() {
// @@protoc_insertion_point(field_mutable_list:safe_browsing.ClientDownloadRequest.url_chain)
return &url_chain_;
}
// -------------------------------------------------------------------
// ClientDownloadResponse_MoreInfo
@ -12886,7 +13547,7 @@ inline void ClientDownloadResponse_MoreInfo::set_allocated_url(::std::string* ur
// ClientDownloadResponse
// required .safe_browsing.ClientDownloadResponse.Verdict verdict = 1;
// optional .safe_browsing.ClientDownloadResponse.Verdict verdict = 1 [default = SAFE];
inline bool ClientDownloadResponse::has_verdict() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}

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

@ -380,7 +380,46 @@ message ClientDownloadRequest {
// PPAPI_SAVE_REQUEST type messages may have more than one suggested filetype.
// Each element in this collection indicates an alternate extension including
// the leading extension separator.
repeated string alternate_extensions = 32;
repeated string alternate_extensions = 35;
message URLChainEntry {
enum URLType {
DOWNLOAD_URL = 1;
DOWNLOAD_REFERRER = 2;
LANDING_PAGE = 3;
LANDING_REFERRER = 4;
CLIENT_REDIRECT = 5;
SERVER_REDIRECT = 6;
}
// [required] The url of this Entry.
optional string url = 1;
// Type of URLs, such as download url, download referrer, etc.
optional URLType type = 2;
// IP address corresponding to url.
optional string ip_address = 3;
// Referrer url of this entry.
optional string referrer = 4;
// Main frame URL of referrer.
optional string main_frame_referrer = 5;
// If this URL loads in a different tab/frame from previous one.
optional bool is_retargeting = 6;
// If there is a user gesture attached to this transition.
optional bool is_user_initiated = 7;
optional double timestamp_in_millisec = 8;
} // End of URLChainEntry
// URLs transitions from landing referrer to download in reverse chronological
// order, i.e. download url comes first in this list, and landing referrer
// comes last.
repeated URLChainEntry url_chain = 36;
}
message ClientDownloadResponse {
@ -400,7 +439,7 @@ message ClientDownloadResponse {
// Chrome should show the default warning if configured for this file type.
UNKNOWN = 5;
}
required Verdict verdict = 1;
optional Verdict verdict = 1 [default = SAFE];
message MoreInfo {
// A human-readable string describing the nature of the warning.

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

@ -23,6 +23,7 @@ const {
normalizeTime,
runSafeSync,
SingletonEventManager,
PlatformInfo,
} = ExtensionUtils;
const DOWNLOAD_ITEM_FIELDS = ["id", "url", "referrer", "filename", "incognito",
@ -391,12 +392,18 @@ extensions.registerSchemaAPI("downloads", "addon_parent", context => {
return {
downloads: {
download(options) {
if (options.filename != null) {
if (options.filename.length == 0) {
let {filename} = options;
if (filename && PlatformInfo.os === "win") {
// cross platform javascript code uses "/"
filename = filename.replace(/\//g, "\\");
}
if (filename != null) {
if (filename.length == 0) {
return Promise.reject({message: "filename must not be empty"});
}
let path = OS.Path.split(options.filename);
let path = OS.Path.split(filename);
if (path.absolute) {
return Promise.reject({message: "filename must not be an absolute path"});
}
@ -416,23 +423,27 @@ extensions.registerSchemaAPI("downloads", "addon_parent", context => {
// if (options.saveAs) { }
let target;
if (options.filename) {
target = OS.Path.join(downloadsDir, options.filename);
if (filename) {
target = OS.Path.join(downloadsDir, filename);
} else {
let uri = NetUtil.newURI(options.url);
let filename;
let remote = "download";
if (uri instanceof Ci.nsIURL) {
filename = uri.fileName;
remote = uri.fileName;
}
target = OS.Path.join(downloadsDir, filename || "download");
target = OS.Path.join(downloadsDir, remote);
}
// This has a race, something else could come along and create
// the file between this test and them time the download code
// creates the target file. But we can't easily fix it without
// modifying DownloadCore so we live with it for now.
return OS.File.exists(target).then(exists => {
// Create any needed subdirectories if required by filename.
const dir = OS.Path.dirname(target);
return OS.File.makeDir(dir, {from: downloadsDir}).then(() => {
return OS.File.exists(target);
}).then(exists => {
// This has a race, something else could come along and create
// the file between this test and them time the download code
// creates the target file. But we can't easily fix it without
// modifying DownloadCore so we live with it for now.
if (exists) {
switch (options.conflictAction) {
case "uniquify":

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

@ -94,10 +94,10 @@ function touch(filename) {
}
// Remove a file in the downloads directory.
function remove(filename) {
function remove(filename, recursive = false) {
let file = downloadDir.clone();
file.append(filename);
file.remove(false);
file.remove(recursive);
}
add_task(function* test_downloads() {
@ -121,7 +121,8 @@ add_task(function* test_downloads() {
return waitForDownloads();
}).then(() => {
let localPath = downloadDir.clone();
localPath.append(localFile);
let parts = Array.isArray(localFile) ? localFile : [localFile];
parts.map(p => localPath.append(p));
equal(localPath.fileSize, expectedSize, "Downloaded file has expected size");
localPath.remove(false);
});
@ -140,6 +141,35 @@ add_task(function* test_downloads() {
filename: "newpath.txt",
}, "newpath.txt", FILE_LEN, "source and filename");
// Call download() with a filename with subdirs.
yield testDownload({
url: FILE_URL,
filename: "sub/dir/file",
}, ["sub", "dir", "file"], FILE_LEN, "source and filename with subdirs");
// Call download() with a filename with existing subdirs.
yield testDownload({
url: FILE_URL,
filename: "sub/dir/file2",
}, ["sub", "dir", "file2"], FILE_LEN, "source and filename with existing subdirs");
// Only run Windows path separator test on Windows.
if (WINDOWS) {
// Call download() with a filename with Windows path separator.
yield testDownload({
url: FILE_URL,
filename: "sub\\dir\\file3",
}, ["sub", "dir", "file3"], FILE_LEN, "filename with Windows path separator");
}
remove("sub", true);
// Call download(), filename with subdir, skipping parts.
yield testDownload({
url: FILE_URL,
filename: "skip//part",
}, ["skip", "part"], FILE_LEN, "source, filename, with subdir, skipping parts");
remove("skip", true);
// Check conflictAction of "uniquify".
touch(FILE_NAME);
yield testDownload({

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

@ -88,6 +88,10 @@ LoginManagerPromptFactory.prototype = {
var prompter = prompt.prompter;
var [hostname, httpRealm] = prompter._getAuthTarget(prompt.channel, prompt.authInfo);
var hasLogins = (prompter._pwmgr.countLogins(hostname, null, httpRealm) > 0);
if (!hasLogins && LoginHelper.schemeUpgrades && hostname.startsWith("https://")) {
let httpHostname = hostname.replace(/^https:\/\//, "http://");
hasLogins = (prompter._pwmgr.countLogins(httpHostname, null, httpRealm) > 0);
}
if (hasLogins && prompter._pwmgr.uiBusy) {
this.log("_doAsyncPrompt:run bypassed, master password UI busy");
return;
@ -511,6 +515,7 @@ LoginManagerPrompter.prototype = {
var epicfail = false;
var canAutologin = false;
var notifyObj;
var foundLogins;
try {
this.log("===== promptAuth called =====");
@ -523,9 +528,18 @@ LoginManagerPrompter.prototype = {
var [hostname, httpRealm] = this._getAuthTarget(aChannel, aAuthInfo);
// Looks for existing logins to prefill the prompt with.
var foundLogins = this._pwmgr.findLogins({},
hostname, null, httpRealm);
this.log("found " + foundLogins.length + " matching logins.");
foundLogins = LoginHelper.searchLoginsWithObject({
hostname,
httpRealm,
schemeUpgrades: LoginHelper.schemeUpgrades,
});
this.log("found", foundLogins.length, "matching logins.");
let resolveBy = [
"scheme",
"timePasswordChanged",
];
foundLogins = LoginHelper.dedupeLogins(foundLogins, ["username"], resolveBy, hostname);
this.log(foundLogins.length, "matching logins remain after deduping");
// XXX Can't select from multiple accounts yet. (bug 227632)
if (foundLogins.length > 0) {

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

@ -24,6 +24,8 @@ var iframe = document.getElementById("iframe");
// Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
isTabModal = false;
const AUTHENTICATE_PATH = new URL("authenticate.sjs", window.location.href).pathname;
let chromeScript = runInParent(SimpleTest.getTestFileURL("pwmgr_common.js"));
runInParent(() => {
@ -40,17 +42,41 @@ runInParent(() => {
createInstance(Ci.nsILoginInfo);
login4 = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let httpUpgradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let httpsDowngradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let dedupeHttpUpgradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
let dedupeHttpsUpgradeLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
login3A.init("http://mochi.test:8888", null, "mochitest",
"mochiuser1", "mochipass1", "", "");
login3B.init("http://mochi.test:8888", null, "mochitest2",
"mochiuser2", "mochipass2", "", "");
login4.init("http://mochi.test:8888", null, "mochitest3",
"mochiuser3", "mochipass3-old", "", "");
"mochiuser3", "mochipass3-old", "", "");
// Logins to test scheme upgrades (allowed) and downgrades (disallowed)
httpUpgradeLogin.init("http://example.com", null, "schemeUpgrade",
"httpUser", "httpPass", "", "");
httpsDowngradeLogin.init("https://example.com", null, "schemeDowngrade",
"httpsUser", "httpsPass", "", "");
// HTTP and HTTPS version of the same domain and realm but with different passwords.
dedupeHttpUpgradeLogin.init("http://example.org", null, "schemeUpgradeDedupe",
"dedupeUser", "httpPass", "", "");
dedupeHttpsUpgradeLogin.init("https://example.org", null, "schemeUpgradeDedupe",
"dedupeUser", "httpsPass", "", "");
pwmgr.addLogin(login3A);
pwmgr.addLogin(login3B);
pwmgr.addLogin(login4);
pwmgr.addLogin(httpUpgradeLogin);
pwmgr.addLogin(httpsDowngradeLogin);
pwmgr.addLogin(dedupeHttpUpgradeLogin);
pwmgr.addLogin(dedupeHttpsUpgradeLogin);
});
add_task(function* test_iframe() {
@ -234,6 +260,103 @@ add_task(function* test_iframe() {
iframe.contentDocument);
yield promptShownPromise;
});
add_task(function* test_schemeUpgrade() {
let state = {
msg : "https://example.com is requesting your username and password.\n\n" +
"WARNING: Your password will not be sent to the website you are currently visiting!",
title : "Authentication Required",
textValue : "httpUser",
passValue : "httpPass",
iconClass : "authentication-icon question-icon",
titleHidden : true,
textHidden : false,
passHidden : false,
checkHidden : true,
checkMsg : "",
checked : false,
focused : "textField",
defButton : "button0",
};
let action = {
buttonClick : "ok",
};
let promptDone = handlePrompt(state, action);
// The following tests are driven by iframe loads
let iframeLoaded = onloadPromiseFor("iframe");
iframe.src = "https://example.com" + AUTHENTICATE_PATH +
"?user=httpUser&pass=httpPass&realm=schemeUpgrade";
yield promptDone;
yield iframeLoaded;
checkEchoedAuthInfo({user: "httpUser", pass: "httpPass"},
SpecialPowers.wrap(iframe).contentDocument);
});
add_task(function* test_schemeDowngrade() {
let state = {
msg : "http://example.com is requesting your username and password.\n\n" +
"WARNING: Your password will not be sent to the website you are currently visiting!",
title : "Authentication Required",
textValue : "", // empty because we shouldn't downgrade
passValue : "",
iconClass : "authentication-icon question-icon",
titleHidden : true,
textHidden : false,
passHidden : false,
checkHidden : true,
checkMsg : "",
checked : false,
focused : "textField",
defButton : "button0",
};
let action = {
buttonClick : "cancel",
};
let promptDone = handlePrompt(state, action);
// The following tests are driven by iframe loads
let iframeLoaded = onloadPromiseFor("iframe");
iframe.src = "http://example.com" + AUTHENTICATE_PATH +
"?user=unused&pass=unused&realm=schemeDowngrade";
yield promptDone;
yield iframeLoaded;
});
add_task(function* test_schemeUpgrade_dedupe() {
let state = {
msg : "https://example.org is requesting your username and password.\n\n" +
"WARNING: Your password will not be sent to the website you are currently visiting!",
title : "Authentication Required",
textValue : "dedupeUser",
passValue : "httpsPass",
iconClass : "authentication-icon question-icon",
titleHidden : true,
textHidden : false,
passHidden : false,
checkHidden : true,
checkMsg : "",
checked : false,
focused : "textField",
defButton : "button0",
};
let action = {
buttonClick : "ok",
};
let promptDone = handlePrompt(state, action);
// The following tests are driven by iframe loads
let iframeLoaded = onloadPromiseFor("iframe");
iframe.src = "https://example.org" + AUTHENTICATE_PATH +
"?user=dedupeUser&pass=httpsPass&realm=schemeUpgradeDedupe";
yield promptDone;
yield iframeLoaded;
checkEchoedAuthInfo({user: "dedupeUser", pass: "httpsPass"},
SpecialPowers.wrap(iframe).contentDocument);
});
</script>
</pre>
</body>

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

@ -86,11 +86,6 @@ const BookmarkSyncUtils = PlacesSyncUtils.bookmarks = Object.freeze({
if (!children.length) {
return;
}
for (let child of children) {
// Note the current index for notifying observers. This can
// be removed once we switch to `reorder`.
child.oldIndex = child.index;
}
// Reorder the list, ignoring missing children.
let delta = 0;
@ -281,24 +276,6 @@ function updateChildIndex(children, child, newIndex) {
child.index = newIndex;
}
/**
* Sends a bookmarks notification through the given observers.
*
* @param observers
* array of nsINavBookmarkObserver objects.
* @param notification
* the notification name.
* @param args
* array of arguments to pass to the notification.
*/
function notify(observers, notification, args) {
for (let observer of observers) {
try {
observer[notification](...args);
} catch (ex) {}
}
}
// A helper for whenever we want to know if a GUID doesn't exist in the places
// database. Primarily used to detect orphans on incoming records.
var GUIDMissing = Task.async(function* (guid) {

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

@ -592,9 +592,12 @@ Finder.prototype = {
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
if (!aWebProgress.isTopLevel)
return;
// Ignore events that don't change the document.
if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)
return;
// Avoid leaking if we change the page.
this._previousLink = this._currentFoundRange = null;
this._lastFindResult = this._previousLink = this._currentFoundRange = null;
this.highlighter.onLocationChange();
this.iterator.reset();
},

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

@ -49,6 +49,7 @@ const kModalStyles = {
["transition-property", "opacity, transform, top, left"],
["transition-duration", "50ms"],
["transition-timing-function", "linear"],
["white-space", "nowrap"],
["z-index", 2]
],
outlineNodeDebug: [ ["z-index", 2147483647] ],
@ -76,7 +77,8 @@ const kModalStyles = {
["border-radius", "3px"],
["margin", "-1px 0 0 -1px !important"],
["padding", "0 1px 2px 1px !important"],
["position", "absolute"]
["position", "absolute"],
["white-space", "nowrap"]
],
maskRectBrightText: [ ["background", "#000"] ]
};
@ -159,7 +161,8 @@ FinderHighlighter.prototype = {
gWindows.set(window, {
dynamicRangesSet: new Set(),
frames: new Map(),
modalHighlightRectsMap: new Map()
modalHighlightRectsMap: new Map(),
previousRangeRectsCount: 0
});
}
return gWindows.get(window);
@ -409,7 +412,6 @@ FinderHighlighter.prototype = {
return;
}
let outlineNode;
if (foundRange !== dict.currentFoundRange || data.findAgain) {
dict.currentFoundRange = foundRange;
@ -424,6 +426,9 @@ FinderHighlighter.prototype = {
dict.brightText = this._isColorBright(fontStyle.color);
}
if (data.findAgain)
dict.updateAllRanges = true;
if (!dict.visible)
this.show(window);
else
@ -432,12 +437,14 @@ FinderHighlighter.prototype = {
this._updateRangeOutline(dict, textContent, fontStyle);
}
outlineNode = dict.modalHighlightOutline;
if (dict.animation)
dict.animation.finish();
dict.animation = outlineNode.setAnimationForElement(kModalOutlineId,
Cu.cloneInto(kModalOutlineAnim.keyframes, window), kModalOutlineAnim.duration);
dict.animation.onfinish = () => dict.animation = null;
let outlineNode = dict.modalHighlightOutline;
if (outlineNode) {
if (dict.animation)
dict.animation.finish();
dict.animation = outlineNode.setAnimationForElement(kModalOutlineId,
Cu.cloneInto(kModalOutlineAnim.keyframes, window), kModalOutlineAnim.duration);
dict.animation.onfinish = () => dict.animation = null;
}
if (this._highlightAll && data.searchString)
this.highlight(true, data.searchString, data.linksOnly);
@ -473,9 +480,10 @@ FinderHighlighter.prototype = {
*/
onLocationChange() {
let window = this.finder._getWindow();
this.hide(window);
let dict = this.getForWindow(window);
this.clear(window);
dict.currentFoundRange = null;
dict.currentFoundRange = dict.lastIteratorParams = null;
if (!dict.modalHighlightOutline)
return;
@ -580,7 +588,7 @@ FinderHighlighter.prototype = {
// Since the frame is an element inside a parent window, we'd like to
// learn its position relative to it.
let el = this._getDWU(currWin).containerElement;
currWin = window.parent;
currWin = currWin.parent;
dwu = this._getDWU(currWin);
let parentRect = Rect.fromRect(dwu.getBoundsWithoutFlushing(el));
@ -747,19 +755,14 @@ FinderHighlighter.prototype = {
/**
* Read and store the rectangles that encompass the entire region of a range
* for use by the drawing function of the highlighter and store them in the
* cache.
* for use by the drawing function of the highlighter.
*
* @param {nsIDOMRange} range Range to fetch the rectangles from
* @param {Boolean} [checkIfDynamic] Whether we should check if the range
* is dynamic as per the rules in
* `_isInDynamicContainer()`. Optional,
* defaults to `true`
* @param {Object} [dict] Dictionary of properties belonging to
* the currently active window
* @param {nsIDOMRange} range Range to fetch the rectangles from
* @param {Object} [dict] Dictionary of properties belonging to
* the currently active window
* @return {Set} Set of rects that were found for the range
*/
_updateRangeRects(range, checkIfDynamic = true, dict = null) {
_getRangeRects(range, dict = null) {
let window = range.startContainer.ownerDocument.defaultView;
let bounds;
// If the window is part of a frameset, try to cache the bounds query.
@ -785,6 +788,26 @@ FinderHighlighter.prototype = {
if (rect.intersects(topBounds))
rects.add(rect);
}
return rects;
},
/**
* Read and store the rectangles that encompass the entire region of a range
* for use by the drawing function of the highlighter and store them in the
* cache.
*
* @param {nsIDOMRange} range Range to fetch the rectangles from
* @param {Boolean} [checkIfDynamic] Whether we should check if the range
* is dynamic as per the rules in
* `_isInDynamicContainer()`. Optional,
* defaults to `true`
* @param {Object} [dict] Dictionary of properties belonging to
* the currently active window
* @return {Set} Set of rects that were found for the range
*/
_updateRangeRects(range, checkIfDynamic = true, dict = null) {
let window = range.startContainer.ownerDocument.defaultView;
let rects = this._getRangeRects(range, dict);
// Only fetch the rect at this point, if not passed in as argument.
dict = dict || this.getForWindow(window.top);
@ -811,47 +834,113 @@ FinderHighlighter.prototype = {
/**
* Update the content, position and style of the yellow current found range
* outline the floats atop the mask with the dimmed background.
* outline that floats atop the mask with the dimmed background.
* Rebuild it, if necessary, This will deactivate the animation between
* occurrences.
*
* @param {Object} dict Dictionary of properties belonging to the
* currently active window
* @param {Array} [textContent] Array of text that's inside the range. Optional,
* defaults to an empty array
* defaults to `null`
* @param {Object} [fontStyle] Dictionary of CSS styles in camelCase as
* returned by `_getRangeFontStyle()`. Optional
*/
_updateRangeOutline(dict, textContent = [], fontStyle = null) {
let outlineNode = dict.modalHighlightOutline;
let range = this.finder._fastFind.getFoundRange();
if (!outlineNode || !range)
return;
let rect = range.getClientRects()[0];
if (!rect)
_updateRangeOutline(dict, textContent = null, fontStyle = null) {
let range = dict.currentFoundRange;
if (!range)
return;
if (!fontStyle)
fontStyle = this._getRangeFontStyle(range);
fontStyle = fontStyle || this._getRangeFontStyle(range);
// Text color in the outline is determined by kModalStyles.
delete fontStyle.color;
if (textContent.length)
outlineNode.setTextContentForElement(kModalOutlineId + "-text", textContent.join(" "));
// Correct the line-height to align the text in the middle of the box.
fontStyle.lineHeight = rect.height + "px";
outlineNode.setAttributeForElement(kModalOutlineId + "-text", "style",
this._getStyleString(kModalStyles.outlineText) + "; " +
this._getHTMLFontStyle(fontStyle));
let rects = this._getRangeRects(range);
textContent = textContent || this._getRangeContentArray(range);
let window = range.startContainer.ownerDocument.defaultView;
let { left, top } = this._getRootBounds(window);
outlineNode.setAttributeForElement(kModalOutlineId, "style",
this._getStyleString(kModalStyles.outlineNode, [
["top", top + rect.top + "px"],
["left", left + rect.left + "px"],
let outlineAnonNode = dict.modalHighlightOutline;
let rectCount = rects.size;
// (re-)Building the outline is conditional and happens when one of the
// following conditions is met:
// 1. No outline nodes were built before, or
// 2. When the amount of rectangles to draw is different from before, or
// 3. When there's more than one rectangle to draw, because it's impossible
// to animate that consistently with AnonymousContent nodes.
let rebuildOutline = (!outlineAnonNode || rectCount !== dict.previousRangeRectsCount ||
rectCount != 1);
dict.previousRangeRectsCount = rectCount;
let document = range.startContainer.ownerDocument;
// First see if we need to and can remove the previous outline nodes.
if (rebuildOutline && outlineAnonNode) {
if (kDebug) {
outlineAnonNode.remove();
} else {
try {
document.removeAnonymousContent(outlineAnonNode);
} catch (ex) {}
}
dict.modalHighlightOutline = null;
}
// Abort when there's no text to highlight.
if (!textContent.length)
return;
let container, outlineBox;
if (rebuildOutline) {
// The outline needs to be sitting inside a container, otherwise the anonymous
// content API won't find it by its ID later...
container = document.createElementNS(kNSHTML, "div");
// Create the main (yellow) highlight outline box.
outlineBox = document.createElementNS(kNSHTML, "div");
outlineBox.setAttribute("id", kModalOutlineId);
}
const kModalOutlineTextId = kModalOutlineId + "-text";
let i = 0;
for (let rect of rects) {
// if the current rect is the last rect, then text is set to the rest of
// the textContent with single spaces injected between the text. Otherwise
// text is set to the current textContent for the matching rect.
let text = (i == rectCount - 1) ? textContent.slice(i).join(" ") : textContent[i];
++i;
let outlineStyle = this._getStyleString(kModalStyles.outlineNode, [
["top", rect.top + "px"],
["left", rect.left + "px"],
["height", rect.height + "px"],
["width", rect.width + "px"]],
kDebug ? kModalStyles.outlineNodeDebug : []
));
["width", rect.width + "px"]
], kDebug ? kModalStyles.outlineNodeDebug : []);
fontStyle.lineHeight = rect.height + "px";
let textStyle = this._getStyleString(kModalStyles.outlineText) + "; " +
this._getHTMLFontStyle(fontStyle);
if (rebuildOutline) {
let textBoxParent = (rectCount == 1) ? outlineBox :
outlineBox.appendChild(document.createElementNS(kNSHTML, "div"));
textBoxParent.setAttribute("style", outlineStyle);
let textBox = document.createElementNS(kNSHTML, "span");
if (rectCount == 1)
textBox.setAttribute("id", kModalOutlineTextId);
textBox.setAttribute("style", textStyle);
textBox.textContent = text;
textBoxParent.appendChild(textBox);
} else {
// Set the appropriate properties on the existing nodes, which will also
// activate the transitions.
outlineAnonNode.setAttributeForElement(kModalOutlineId, "style", outlineStyle);
outlineAnonNode.setAttributeForElement(kModalOutlineTextId, "style", textStyle);
outlineAnonNode.setTextContentForElement(kModalOutlineTextId, text);
}
}
if (rebuildOutline) {
container.appendChild(outlineBox);
dict.modalHighlightOutline = kDebug ?
mockAnonymousContentNode((document.body ||
document.documentElement).appendChild(container.firstChild)) :
document.insertAnonymousContent(container);
}
},
/**
@ -904,25 +993,7 @@ FinderHighlighter.prototype = {
return;
}
// The outline needs to be sitting inside a container, otherwise the anonymous
// content API won't find it by its ID later...
let container = document.createElementNS(kNSHTML, "div");
// Create the main (yellow) highlight outline box.
let outlineBox = document.createElementNS(kNSHTML, "div");
outlineBox.setAttribute("id", kModalOutlineId);
outlineBox.setAttribute("style", this._getStyleString(kModalStyles.outlineNode,
kDebug ? kModalStyles.outlineNodeDebug : []));
let outlineBoxText = document.createElementNS(kNSHTML, "span");
let attrValue = kModalOutlineId + "-text";
outlineBoxText.setAttribute("id", attrValue);
outlineBoxText.setAttribute("style", this._getStyleString(kModalStyles.outlineText));
outlineBox.appendChild(outlineBoxText);
container.appendChild(outlineBox);
dict.modalHighlightOutline = kDebug ?
mockAnonymousContentNode((document.body || document.documentElement).appendChild(container.firstChild)) :
document.insertAnonymousContent(container);
this._updateRangeOutline(dict);
// Make sure to at least show the dimmed background.
this._repaintHighlightAllMask(window, false);
@ -962,10 +1033,10 @@ FinderHighlighter.prototype = {
const rectStyle = this._getStyleString(kModalStyles.maskRect,
dict.brightText ? kModalStyles.maskRectBrightText : []);
for (let [range, rects] of dict.modalHighlightRectsMap) {
if (this._checkOverlap(dict.currentFoundRange, range))
continue;
if (dict.updateAllRanges)
rects = this._updateRangeRects(range);
if (this._checkOverlap(dict.currentFoundRange, range))
continue;
for (let rect of rects) {
maskContent.push(`<div xmlns="${kNSHTML}" style="${rectStyle}; top: ${rect.y}px;
left: ${rect.x}px; height: ${rect.height}px; width: ${rect.width}px;"></div>`);

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

@ -60,7 +60,7 @@ function promiseEnterStringIntoFindField(findbar, str) {
function promiseTestHighlighterOutput(browser, word, expectedResult, extraTest = () => {}) {
return ContentTask.spawn(browser, { word, expectedResult, extraTest: extraTest.toSource() },
function* ({ word, expectedResult, extraTest }) {
let document = content.document;
Cu.import("resource://gre/modules/Timer.jsm", this);
return new Promise((resolve, reject) => {
let stubbed = {};
@ -68,19 +68,22 @@ function promiseTestHighlighterOutput(browser, word, expectedResult, extraTest =
insertCalls: [],
removeCalls: []
};
let lastMaskNode, lastOutlineNode;
// Amount of milliseconds to wait after the last time one of our stubs
// was called.
const kTimeoutMs = 1000;
// The initial timeout may wait for a while for results to come in.
let timeout = content.setTimeout(() => finish(false, "Timeout"), kTimeoutMs * 5);
let timeout = setTimeout(() => finish(false, "Timeout"), kTimeoutMs * 5);
function finish(ok = true, message = "finished with error") {
// Restore the functions we stubbed out.
document.insertAnonymousContent = stubbed.insert;
document.removeAnonymousContent = stubbed.remove;
try {
content.document.insertAnonymousContent = stubbed.insert;
content.document.removeAnonymousContent = stubbed.remove;
} catch (ex) {}
stubbed = {};
content.clearTimeout(timeout);
clearTimeout(timeout);
if (expectedResult.rectCount !== 0)
Assert.ok(ok, message);
@ -96,7 +99,6 @@ function promiseTestHighlighterOutput(browser, word, expectedResult, extraTest =
// We reached the amount of calls we expected, so now we can check
// the amount of rects.
let lastMaskNode = callCounts.insertCalls.pop();
if (!lastMaskNode && expectedResult.rectCount !== 0) {
Assert.ok(false, `No mask node found, but expected ${expectedResult.rectCount} rects.`);
}
@ -108,7 +110,7 @@ function promiseTestHighlighterOutput(browser, word, expectedResult, extraTest =
// Allow more specific assertions to be tested in `extraTest`.
extraTest = eval(extraTest);
extraTest(lastMaskNode);
extraTest(lastMaskNode, lastOutlineNode);
resolve();
}
@ -116,17 +118,25 @@ function promiseTestHighlighterOutput(browser, word, expectedResult, extraTest =
// Create a function that will stub the original version and collects
// the arguments so we can check the results later.
function stub(which) {
stubbed[which] = document[which + "AnonymousContent"];
stubbed[which] = content.document[which + "AnonymousContent"];
let prop = which + "Calls";
return function(node) {
callCounts[prop].push(node);
content.clearTimeout(timeout);
timeout = content.setTimeout(finish, kTimeoutMs);
return stubbed[which].call(document, node);
if (which == "insert") {
if (node.outerHTML.indexOf("outlineMask") > -1)
lastMaskNode = node;
else
lastOutlineNode = node;
}
clearTimeout(timeout);
timeout = setTimeout(() => {
finish();
}, kTimeoutMs);
return stubbed[which].call(content.document, node);
};
}
document.insertAnonymousContent = stub("insert");
document.removeAnonymousContent = stub("remove");
content.document.insertAnonymousContent = stub("insert");
content.document.removeAnonymousContent = stub("remove");
});
});
}
@ -146,6 +156,15 @@ add_task(function* testModalResults() {
insertCalls: [2, 4],
removeCalls: [1, 2]
}],
["their law might propagate their kind", {
rectCount: 0,
insertCalls: [31, 32],
removeCalls: [31, 32],
extraTest: function(maskNode, outlineNode) {
Assert.equal(outlineNode.getElementsByTagName("div").length, 3,
"There should be multiple rects drawn");
}
}],
["ro", {
rectCount: 40,
insertCalls: [1, 4],
@ -158,8 +177,8 @@ add_task(function* testModalResults() {
}],
["o", {
rectCount: 491,
insertCalls: [1, 5],
removeCalls: [1, 4]
insertCalls: [3, 7],
removeCalls: [3, 6]
}]
]);
let url = kFixtureBaseURL + "file_FinderSample.html";
@ -171,7 +190,8 @@ add_task(function* testModalResults() {
Assert.ok(!findbar.hidden, "Findbar should be open now.");
yield new Promise(resolve => setTimeout(resolve, kIteratorTimeout));
let promise = promiseTestHighlighterOutput(browser, word, expectedResult);
let promise = promiseTestHighlighterOutput(browser, word, expectedResult,
expectedResult.extraTest);
yield promiseEnterStringIntoFindField(findbar, word);
yield promise;
@ -340,3 +360,33 @@ add_task(function* testXMLDocument() {
findbar.close(true);
});
});
add_task(function* testHideOnLocationChange() {
let url = kFixtureBaseURL + "file_FinderSample.html";
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
let browser = tab.linkedBrowser;
let findbar = gBrowser.getFindBar();
yield promiseOpenFindbar(findbar);
let word = "Roland";
let expectedResult = {
rectCount: 1,
insertCalls: [2, 4],
removeCalls: [1, 2]
};
let promise = promiseTestHighlighterOutput(browser, word, expectedResult);
yield promiseEnterStringIntoFindField(findbar, word);
yield promise;
// Now we try to navigate away! (Using the same page)
promise = promiseTestHighlighterOutput(browser, word, {
rectCount: 0,
insertCalls: [0, 0],
removeCalls: [1, 2]
});
yield BrowserTestUtils.loadURI(browser, url);
yield promise;
yield BrowserTestUtils.removeTab(tab);
});