mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 09:15:35 +00:00
Merge m-c to inbound. a=merge
This commit is contained in:
commit
290c5baa10
@ -5,3 +5,6 @@
|
||||
# This file is included by all browser mozconfigs
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common"
|
||||
|
||||
# Enable Telemetry
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
@ -11,8 +11,6 @@ ac_add_options --with-mozilla-api-keyfile=/builds/mozilla-desktop-geoloc-api.key
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
|
||||
ac_add_options --enable-warnings-as-errors
|
||||
|
||||
|
@ -11,8 +11,6 @@ ac_add_options --with-mozilla-api-keyfile=/builds/mozilla-desktop-geoloc-api.key
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
|
||||
ac_add_options --enable-warnings-as-errors
|
||||
|
||||
|
@ -14,8 +14,6 @@ ac_add_options --with-mozilla-api-keyfile=/builds/mozilla-desktop-geoloc-api.key
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
|
||||
ac_add_options --enable-warnings-as-errors
|
||||
|
||||
|
@ -25,8 +25,6 @@ ac_add_options --with-mozilla-api-keyfile=/c/builds/mozilla-desktop-geoloc-api.k
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
. $topsrcdir/build/win32/mozconfig.vs2015-win64
|
||||
|
||||
# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
|
||||
|
@ -23,8 +23,6 @@ ac_add_options --with-mozilla-api-keyfile=/c/builds/mozilla-desktop-geoloc-api.k
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
|
||||
ac_add_options --enable-warnings-as-errors
|
||||
|
||||
|
@ -115,3 +115,7 @@ storage.data.label=Data
|
||||
# LOCALIZATION NOTE (storage.parsedValue.label):
|
||||
# This is the heading displayed over the item parsed value in the sidebar
|
||||
storage.parsedValue.label=Parsed Value
|
||||
|
||||
# LOCALIZATION NOTE (storage.popupMenu.deleteLabel):
|
||||
# Label of popup menu action to delete storage item.
|
||||
storage.popupMenu.deleteLabel=Delete “%S”
|
||||
|
@ -57,6 +57,8 @@ const MAX_VISIBLE_STRING_SIZE = 100;
|
||||
* - removableColumns: Whether columns are removeable. If set to false,
|
||||
* the context menu in the headers will not appear.
|
||||
* - firstColumn: key of the first column that should appear.
|
||||
* - cellContextMenuId: ID of a <menupopup> element to be set as a
|
||||
* context menu of every cell.
|
||||
*/
|
||||
function TableWidget(node, options = {}) {
|
||||
EventEmitter.decorate(this);
|
||||
@ -66,12 +68,13 @@ function TableWidget(node, options = {}) {
|
||||
this._parent = node;
|
||||
|
||||
let {initialColumns, emptyText, uniqueId, highlightUpdated, removableColumns,
|
||||
firstColumn} = options;
|
||||
firstColumn, cellContextMenuId} = options;
|
||||
this.emptyText = emptyText || "";
|
||||
this.uniqueId = uniqueId || "name";
|
||||
this.firstColumn = firstColumn || "";
|
||||
this.highlightUpdated = highlightUpdated || false;
|
||||
this.removableColumns = removableColumns !== false;
|
||||
this.cellContextMenuId = cellContextMenuId;
|
||||
|
||||
this.tbody = this.document.createElementNS(XUL_NS, "hbox");
|
||||
this.tbody.className = "table-widget-body theme-body";
|
||||
@ -807,6 +810,7 @@ TableWidget.prototype = {
|
||||
}
|
||||
for (let column of this.columns.values()) {
|
||||
column.remove(item);
|
||||
column.updateZebra();
|
||||
}
|
||||
if (this.items.size == 0) {
|
||||
this.tbody.setAttribute("empty", "empty");
|
||||
@ -1449,6 +1453,15 @@ function Cell(column, item, nextCell) {
|
||||
column.column.appendChild(this.label);
|
||||
}
|
||||
|
||||
if (column.table.cellContextMenuId) {
|
||||
this.label.setAttribute("context", column.table.cellContextMenuId);
|
||||
this.label.addEventListener("contextmenu", (event) => {
|
||||
// Make the ID of the clicked cell available as a property on the table.
|
||||
// It's then available for the popupshowing or command handler.
|
||||
column.table.contextMenuRowId = this.id;
|
||||
}, false);
|
||||
}
|
||||
|
||||
this.value = item[column.id];
|
||||
this.id = item[column.uniqueId];
|
||||
}
|
||||
|
@ -22,6 +22,12 @@
|
||||
|
||||
<commandset id="editMenuCommands"/>
|
||||
|
||||
<popupset id="storagePopupSet">
|
||||
<menupopup id="storage-table-popup">
|
||||
<menuitem id="storage-table-popup-delete"/>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
|
||||
<box flex="1" class="devtools-responsive-container theme-body">
|
||||
<vbox id="storage-tree"/>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
|
@ -20,6 +20,7 @@ support-files =
|
||||
[browser_storage_cookies_tab_navigation.js]
|
||||
[browser_storage_dynamic_updates.js]
|
||||
[browser_storage_localstorage_edit.js]
|
||||
[browser_storage_delete.js]
|
||||
[browser_storage_overflow.js]
|
||||
[browser_storage_search.js]
|
||||
skip-if = os == "linux" && e10s # Bug 1240804 - unhandled promise rejections
|
||||
|
49
devtools/client/storage/test/browser_storage_delete.js
Normal file
49
devtools/client/storage/test/browser_storage_delete.js
Normal file
@ -0,0 +1,49 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* import-globals-from head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test deleting storage items
|
||||
|
||||
const TEST_CASES = [
|
||||
[["localStorage", "http://test1.example.org"],
|
||||
"ls1", "name"],
|
||||
[["sessionStorage", "http://test1.example.org"],
|
||||
"ss1", "name"],
|
||||
[["cookies", "test1.example.org"],
|
||||
"c1", "name"]
|
||||
];
|
||||
|
||||
add_task(function*() {
|
||||
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
|
||||
|
||||
let contextMenu = gPanelWindow.document.getElementById("storage-table-popup");
|
||||
let menuDeleteItem = contextMenu.querySelector("#storage-table-popup-delete");
|
||||
|
||||
for (let [ [store, host], rowName, cellToClick] of TEST_CASES) {
|
||||
info(`Selecting tree item ${store} > ${host}`);
|
||||
yield selectTreeItem([store, host]);
|
||||
|
||||
let row = getRowCells(rowName);
|
||||
|
||||
ok(gUI.table.items.has(rowName),
|
||||
`There is a row '${rowName}' in ${store} > ${host}`);
|
||||
|
||||
yield waitForContextMenu(contextMenu, row[cellToClick], () => {
|
||||
info(`Opened context menu in ${store} > ${host}, row '${rowName}'`);
|
||||
menuDeleteItem.click();
|
||||
ok(menuDeleteItem.getAttribute("label").includes(rowName),
|
||||
`Context menu item label contains '${rowName}'`);
|
||||
});
|
||||
|
||||
yield gUI.once("store-objects-updated");
|
||||
|
||||
ok(!gUI.table.items.has(rowName),
|
||||
`There is no row '${rowName}' in ${store} > ${host} after deletion`);
|
||||
}
|
||||
|
||||
yield finishTests();
|
||||
});
|
@ -803,3 +803,50 @@ function PressKeyXTimes(key, x, modifiers = {}) {
|
||||
EventUtils.synthesizeKey(key, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a context menu popup to open.
|
||||
*
|
||||
* @param nsIDOMElement popup
|
||||
* The XUL popup you expect to open.
|
||||
* @param nsIDOMElement button
|
||||
* The button/element that receives the contextmenu event. This is
|
||||
* expected to open the popup.
|
||||
* @param function onShown
|
||||
* Function to invoke on popupshown event.
|
||||
* @param function onHidden
|
||||
* Function to invoke on popuphidden event.
|
||||
* @return object
|
||||
* A Promise object that is resolved after the popuphidden event
|
||||
* callback is invoked.
|
||||
*/
|
||||
function waitForContextMenu(popup, button, onShown, onHidden) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
function onPopupShown() {
|
||||
info("onPopupShown");
|
||||
popup.removeEventListener("popupshown", onPopupShown);
|
||||
|
||||
onShown && onShown();
|
||||
|
||||
// Use executeSoon() to get out of the popupshown event.
|
||||
popup.addEventListener("popuphidden", onPopupHidden);
|
||||
executeSoon(() => popup.hidePopup());
|
||||
}
|
||||
function onPopupHidden() {
|
||||
info("onPopupHidden");
|
||||
popup.removeEventListener("popuphidden", onPopupHidden);
|
||||
|
||||
onHidden && onHidden();
|
||||
|
||||
deferred.resolve(popup);
|
||||
}
|
||||
|
||||
popup.addEventListener("popupshown", onPopupShown);
|
||||
|
||||
info("wait for the context menu to open");
|
||||
let eventDetails = {type: "contextmenu", button: 2};
|
||||
EventUtils.synthesizeMouse(button, 2, 2, eventDetails,
|
||||
button.ownerDocument.defaultView);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -47,6 +47,10 @@ const REASON = {
|
||||
UPDATE: "update"
|
||||
};
|
||||
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* StorageUI is controls and builds the UI of the Storage Inspector.
|
||||
*
|
||||
@ -74,6 +78,7 @@ var StorageUI = this.StorageUI = function StorageUI(front, target, panelWin) {
|
||||
this.table = new TableWidget(tableNode, {
|
||||
emptyText: L10N.getStr("table.emptyText"),
|
||||
highlightUpdated: true,
|
||||
cellContextMenuId: "storage-table-popup"
|
||||
});
|
||||
|
||||
this.displayObjectSidebar = this.displayObjectSidebar.bind(this);
|
||||
@ -105,6 +110,15 @@ var StorageUI = this.StorageUI = function StorageUI(front, target, panelWin) {
|
||||
|
||||
this.handleKeypress = this.handleKeypress.bind(this);
|
||||
this._panelDoc.addEventListener("keypress", this.handleKeypress);
|
||||
|
||||
this.onPopupShowing = this.onPopupShowing.bind(this);
|
||||
this._tablePopup = this._panelDoc.getElementById("storage-table-popup");
|
||||
this._tablePopup.addEventListener("popupshowing", this.onPopupShowing, false);
|
||||
|
||||
this.onRemoveItem = this.onRemoveItem.bind(this);
|
||||
this._tablePopupDelete = this._panelDoc.getElementById(
|
||||
"storage-table-popup-delete");
|
||||
this._tablePopupDelete.addEventListener("command", this.onRemoveItem, false);
|
||||
};
|
||||
|
||||
exports.StorageUI = StorageUI;
|
||||
@ -130,6 +144,9 @@ StorageUI.prototype = {
|
||||
this._panelDoc.removeEventListener("keypress", this.handleKeypress);
|
||||
this.searchBox.removeEventListener("input", this.filterItems);
|
||||
this.searchBox = null;
|
||||
|
||||
this._tablePopup.removeEventListener("popupshowing", this.onPopupShowing);
|
||||
this._tablePopupDelete.removeEventListener("command", this.onRemoveItem);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -733,5 +750,41 @@ StorageUI.prototype = {
|
||||
names = [JSON.stringify(item.slice(2))];
|
||||
}
|
||||
this.fetchStorageObjects(type, host, names, REASON.NEXT_50_ITEMS);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fires before a cell context menu with the "Delete" action is shown.
|
||||
* If the current storage actor doesn't support removing items, prevent
|
||||
* showing the menu.
|
||||
*/
|
||||
onPopupShowing: function(event) {
|
||||
if (!this.getCurrentActor().removeItem) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
let name = data[this.table.uniqueId];
|
||||
|
||||
const maxLen = ITEM_NAME_MAX_LENGTH;
|
||||
if (name.length > maxLen) {
|
||||
name = name.substr(0, maxLen) + L10N.ellipsis;
|
||||
}
|
||||
|
||||
this._tablePopupDelete.setAttribute("label",
|
||||
L10N.getFormatStr("storage.popupMenu.deleteLabel", name));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles removing an item from the storage
|
||||
*/
|
||||
onRemoveItem: function() {
|
||||
let [, host] = this.tree.selectedItem;
|
||||
let actor = this.getCurrentActor();
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
|
||||
actor.removeItem(host, data[this.table.uniqueId]);
|
||||
},
|
||||
};
|
||||
|
@ -426,7 +426,7 @@ StorageActors.defaults = function(typeName, observationTopic, storeObjectType) {
|
||||
* - storeObjectType {string}
|
||||
* The RetVal type of the store object of this actor.
|
||||
* @param {object} overrides
|
||||
* All the methods which you want to be differnt from the ones in
|
||||
* All the methods which you want to be different from the ones in
|
||||
* StorageActors.defaults method plus the required ones described there.
|
||||
*/
|
||||
StorageActors.createActor = function(options = {}, overrides = {}) {
|
||||
@ -674,6 +674,16 @@ StorageActors.createActor({
|
||||
response: {}
|
||||
}),
|
||||
|
||||
removeItem: method(Task.async(function*(host, name) {
|
||||
this.removeCookie(host, name);
|
||||
}), {
|
||||
request: {
|
||||
host: Arg(0),
|
||||
name: Arg(1),
|
||||
},
|
||||
response: {}
|
||||
}),
|
||||
|
||||
maybeSetupChildProcess: function() {
|
||||
cookieHelpers.onCookieChanged = this.onCookieChanged.bind(this);
|
||||
|
||||
@ -682,6 +692,7 @@ StorageActors.createActor({
|
||||
this.addCookieObservers = cookieHelpers.addCookieObservers;
|
||||
this.removeCookieObservers = cookieHelpers.removeCookieObservers;
|
||||
this.editCookie = cookieHelpers.editCookie;
|
||||
this.removeCookie = cookieHelpers.removeCookie;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -701,6 +712,8 @@ StorageActors.createActor({
|
||||
callParentProcess.bind(null, "removeCookieObservers");
|
||||
this.editCookie =
|
||||
callParentProcess.bind(null, "editCookie");
|
||||
this.removeCookie =
|
||||
callParentProcess.bind(null, "removeCookie");
|
||||
|
||||
addMessageListener("storage:storage-cookie-request-child",
|
||||
cookieHelpers.handleParentRequest);
|
||||
@ -854,6 +867,32 @@ var cookieHelpers = {
|
||||
);
|
||||
},
|
||||
|
||||
removeCookie: function(host, name) {
|
||||
function hostMatches(cookieHost, matchHost) {
|
||||
if (cookieHost == null) {
|
||||
return matchHost == null;
|
||||
}
|
||||
if (cookieHost.startsWith(".")) {
|
||||
return matchHost.endsWith(cookieHost);
|
||||
}
|
||||
return cookieHost == host;
|
||||
}
|
||||
|
||||
let enumerator = Services.cookies.getCookiesFromHost(host);
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
|
||||
if (hostMatches(cookie.host, host) && cookie.name === name) {
|
||||
Services.cookies.remove(
|
||||
cookie.host,
|
||||
cookie.name,
|
||||
cookie.path,
|
||||
cookie.originAttributes,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addCookieObservers: function() {
|
||||
Services.obs.addObserver(cookieHelpers, "cookie-changed", false);
|
||||
return null;
|
||||
@ -902,17 +941,26 @@ var cookieHelpers = {
|
||||
|
||||
handleChildRequest: function(msg) {
|
||||
switch (msg.json.method) {
|
||||
case "getCookiesFromHost":
|
||||
case "getCookiesFromHost": {
|
||||
let host = msg.data.args[0];
|
||||
let cookies = cookieHelpers.getCookiesFromHost(host);
|
||||
return JSON.stringify(cookies);
|
||||
case "addCookieObservers":
|
||||
}
|
||||
case "addCookieObservers": {
|
||||
return cookieHelpers.addCookieObservers();
|
||||
case "removeCookieObservers":
|
||||
}
|
||||
case "removeCookieObservers": {
|
||||
return cookieHelpers.removeCookieObservers();
|
||||
case "editCookie":
|
||||
}
|
||||
case "editCookie": {
|
||||
let rowdata = msg.data.args[0];
|
||||
return cookieHelpers.editCookie(rowdata);
|
||||
}
|
||||
case "removeCookie": {
|
||||
let host = msg.data.args[0];
|
||||
let name = msg.data.args[1];
|
||||
return cookieHelpers.removeCookie(host, name);
|
||||
}
|
||||
default:
|
||||
console.error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD", msg.json.method);
|
||||
throw new Error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD");
|
||||
@ -1113,6 +1161,17 @@ function getObjectForLocalOrSessionStorage(type) {
|
||||
value: new LongStringActor(this.conn, item.value || "")
|
||||
};
|
||||
},
|
||||
|
||||
removeItem: method(Task.async(function*(host, name) {
|
||||
let storage = this.hostVsStores.get(host);
|
||||
storage.removeItem(name);
|
||||
}), {
|
||||
request: {
|
||||
host: Arg(0),
|
||||
name: Arg(1),
|
||||
},
|
||||
response: {}
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -524,8 +524,9 @@ SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't bother caching the result of this URI load.
|
||||
chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING);
|
||||
// Don't bother caching the result of this URI load, but do not exempt
|
||||
// it from Safe Browsing.
|
||||
chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_CLASSIFY_URI);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
|
||||
if (!httpChan) {
|
||||
|
@ -2,6 +2,7 @@ buildDir "${topobjdir}/gradle/build/mobile/android/app"
|
||||
|
||||
apply plugin: 'android-sdk-manager' // Must come before 'com.android.*'.
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'checkstyle'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
@ -211,6 +212,18 @@ dependencies {
|
||||
androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.5.4'
|
||||
}
|
||||
|
||||
// TODO: (bug 1261486): This impl is not robust -
|
||||
// we just wanted to land something.
|
||||
task checkstyle(type: Checkstyle) {
|
||||
configFile file("checkstyle.xml")
|
||||
// TODO: should use sourceSets from project instead of hard-coded str.
|
||||
source '../base/java/'
|
||||
// TODO: This ignores our pre-processed resources.
|
||||
include '**/*.java'
|
||||
// TODO: classpath should probably be something.
|
||||
classpath = files()
|
||||
}
|
||||
|
||||
task syncOmnijarFromDistDir(type: Sync) {
|
||||
into("${project.buildDir}/generated/omnijar")
|
||||
from("${topobjdir}/dist/fennec/assets") {
|
||||
|
49
mobile/android/app/checkstyle.xml
Normal file
49
mobile/android/app/checkstyle.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.2//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
|
||||
|
||||
<!-- TODO: Clean up code & add checks:
|
||||
- WhitespaceAround
|
||||
- EmptyLineSeparator
|
||||
- NeedBraces
|
||||
- LeftCurly // placement of "{" in new scope or literal
|
||||
- RightCurly // placement of "}" in close scope or literal
|
||||
- Indentation
|
||||
- OneStatementPerLine
|
||||
- OperatorWrap
|
||||
- SeparatorWrap
|
||||
- MultipleVariableDeclarations
|
||||
- FallThrough
|
||||
(I spent too much time already)
|
||||
|
||||
Maybe add:
|
||||
- OneTopLevelClass
|
||||
- OverloadMethodsDeclarationOrder
|
||||
- Empty*Block // better to catch errors!
|
||||
(I spent too much time already)
|
||||
|
||||
See http://checkstyle.sourceforge.net/google_style.html
|
||||
for a good set of defaults.
|
||||
-->
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
||||
<!-- TODO: <property name="fileExtensions" value="java, properties, xml"/> -->
|
||||
|
||||
<module name="FileTabCharacter"> <!-- No tabs! -->
|
||||
<property name="eachLine" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<module name="NoLineWrap">
|
||||
<property name="tokens" value="IMPORT,PACKAGE_DEF"/>
|
||||
</module>
|
||||
<module name="OuterTypeFilename"/> <!-- `class Lol` only in Lol.java -->
|
||||
</module>
|
||||
|
||||
</module>
|
@ -963,25 +963,6 @@ OnSharedPreferenceChangeListener
|
||||
context.sendBroadcast(intent, GlobalConstants.PER_ANDROID_PACKAGE_PERMISSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast an intent with <code>pref</code>, <code>branch</code>, and
|
||||
* <code>enabled</code> extras. This is intended to represent the
|
||||
* notification of a preference value to observers.
|
||||
*
|
||||
* The broadcast will be sent only to receivers registered with the
|
||||
* (Fennec-specific) per-Android package permission.
|
||||
*/
|
||||
public static void broadcastPrefAction(final Context context,
|
||||
final String action,
|
||||
final String pref,
|
||||
final boolean value) {
|
||||
final Intent intent = new Intent(action)
|
||||
.putExtra("pref", pref)
|
||||
.putExtra("branch", GeckoSharedPrefs.APP_PREFS_NAME)
|
||||
.putExtra("enabled", value);
|
||||
broadcastAction(context, intent);
|
||||
}
|
||||
|
||||
private static void fillIntentWithProfileInfo(final Context context, final Intent intent) {
|
||||
// There is a race here, but GeckoProfile returns the default profile
|
||||
// when Gecko is not explicitly running for a different profile. In a
|
||||
|
@ -150,6 +150,7 @@
|
||||
<!ENTITY pref_category_vendor2 "&vendorShortName; &brandShortName;">
|
||||
<!ENTITY pref_category_vendor_summary2 "About &brandShortName;, FAQs, feedback">
|
||||
<!ENTITY pref_category_datareporting "Data choices">
|
||||
<!ENTITY pref_category_logins "Logins">
|
||||
<!ENTITY pref_learn_more "Learn more">
|
||||
<!ENTITY pref_category_installed_search_engines "Installed search engines">
|
||||
<!ENTITY pref_category_add_search_providers "Add more search providers">
|
||||
|
@ -42,18 +42,6 @@
|
||||
android:entryValues="@array/pref_cookies_values"
|
||||
android:persistent="false" />
|
||||
|
||||
<org.mozilla.gecko.preferences.LinkPreference android:key="android.not_a_preference.signon.manage"
|
||||
android:title="@string/pref_manage_logins"
|
||||
url="about:logins"/>
|
||||
|
||||
<CheckBoxPreference android:key="signon.rememberSignons"
|
||||
android:title="@string/pref_remember_signons"
|
||||
android:persistent="false" />
|
||||
|
||||
<CheckBoxPreference android:key="privacy.masterpassword.enabled"
|
||||
android:title="@string/pref_use_master_password"
|
||||
android:persistent="false" />
|
||||
|
||||
|
||||
<!-- This pref is persisted in both Gecko and Java -->
|
||||
<org.mozilla.gecko.preferences.ListCheckboxPreference
|
||||
@ -68,6 +56,25 @@
|
||||
android:dialogTitle="@string/pref_clear_on_exit_dialog_title"
|
||||
android:positiveButtonText="@string/button_set"/>
|
||||
|
||||
<PreferenceCategory android:title="@string/pref_category_logins">
|
||||
|
||||
<org.mozilla.gecko.preferences.LinkPreference
|
||||
android:key="android.not_a_preference.signon.manage"
|
||||
android:title="@string/pref_manage_logins"
|
||||
url="about:logins"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="signon.rememberSignons"
|
||||
android:title="@string/pref_remember_signons"
|
||||
android:persistent="false" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="privacy.masterpassword.enabled"
|
||||
android:title="@string/pref_use_master_password"
|
||||
android:persistent="false" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:key="android.not_a_preference.datareporting.preferences"
|
||||
android:title="@string/pref_category_datareporting">
|
||||
|
||||
|
@ -146,6 +146,7 @@
|
||||
<string name="pref_category_vendor">&pref_category_vendor2;</string>
|
||||
<string name="pref_category_vendor_summary">&pref_category_vendor_summary2;</string>
|
||||
<string name="pref_category_datareporting">&pref_category_datareporting;</string>
|
||||
<string name="pref_category_logins">&pref_category_logins;</string>
|
||||
<string name="pref_category_installed_search_engines">&pref_category_installed_search_engines;</string>
|
||||
<string name="pref_category_add_search_providers">&pref_category_add_search_providers;</string>
|
||||
<string name="pref_category_search_restore_defaults">&pref_category_search_restore_defaults;</string>
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
static const char* gQuitApplicationMessage = "quit-application";
|
||||
|
||||
// Limit the list file size to 32mb
|
||||
const uint32_t MAX_FILE_SIZE = (32 * 1024 * 1024);
|
||||
|
||||
#undef LOG
|
||||
|
||||
// NSPR_LOG_MODULES=UrlClassifierStreamUpdater:5
|
||||
@ -644,6 +647,11 @@ nsUrlClassifierStreamUpdater::OnDataAvailable(nsIRequest *request,
|
||||
|
||||
LOG(("OnDataAvailable (%d bytes)", aLength));
|
||||
|
||||
if (aSourceOffset > MAX_FILE_SIZE) {
|
||||
LOG(("OnDataAvailable::Abort because exceeded the maximum file size(%lld)", aSourceOffset));
|
||||
return NS_ERROR_FILE_TOO_BIG;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Copy the data into a nsCString
|
||||
|
@ -17,7 +17,9 @@ support-files =
|
||||
vp9.webm
|
||||
whitelistFrame.html
|
||||
workerFrame.html
|
||||
ping.sjs
|
||||
|
||||
[test_classifier.html]
|
||||
skip-if = (os == 'linux' && debug) #Bug 1199778
|
||||
[test_classifier_worker.html]
|
||||
[test_classify_ping.html]
|
||||
|
16
toolkit/components/url-classifier/tests/mochitest/ping.sjs
Normal file
16
toolkit/components/url-classifier/tests/mochitest/ping.sjs
Normal file
@ -0,0 +1,16 @@
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
|
||||
if (request.method == "POST") {
|
||||
setState(query["id"], "ping");
|
||||
} else {
|
||||
var value = getState(query["id"]);
|
||||
response.setHeader("Content-Type", "text/plain", false);
|
||||
response.write(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1233914 - ping doesn't honor the TP list here.</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.requestFlakyTimeout("Delay to make sure ping is made prior than XHR");
|
||||
|
||||
const timeout = 200;
|
||||
const host_nottrack = "http://not-tracking.example.com/";
|
||||
const host_track = "http://trackertest.org/";
|
||||
const path_ping = "tests/toolkit/components/url-classifier/tests/mochitest/ping.sjs";
|
||||
const TP_ENABLE_PREF = "privacy.trackingprotection.enabled";
|
||||
|
||||
function testPingNonBlacklist() {
|
||||
SpecialPowers.setBoolPref(TP_ENABLE_PREF, true);
|
||||
|
||||
var msg = "ping should reach page not in blacklist";
|
||||
var expectPing = true;
|
||||
var id = "1111";
|
||||
ping(id, host_nottrack);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
isPinged(id, expectPing, msg, resolve);
|
||||
}, timeout);
|
||||
});
|
||||
}
|
||||
|
||||
function testPingBlacklistSafebrowsingOff() {
|
||||
SpecialPowers.setBoolPref(TP_ENABLE_PREF, false);
|
||||
|
||||
var msg = "ping should reach page in blacklist when tracking protection is off";
|
||||
var expectPing = true;
|
||||
var id = "2222";
|
||||
ping(id, host_track);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
isPinged(id, expectPing, msg, resolve);
|
||||
}, timeout);
|
||||
});
|
||||
}
|
||||
|
||||
function testPingBlacklistSafebrowsingOn() {
|
||||
SpecialPowers.setBoolPref(TP_ENABLE_PREF, true);
|
||||
|
||||
var msg = "ping should not reach page in blacklist when tracking protection is on";
|
||||
var expectPing = false;
|
||||
var id = "3333";
|
||||
ping(id, host_track);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
setTimeout(function() {
|
||||
isPinged(id, expectPing, msg, resolve);
|
||||
}, timeout);
|
||||
});
|
||||
}
|
||||
|
||||
function ping(id, host) {
|
||||
var elm = document.createElement("a");
|
||||
elm.setAttribute('ping', host + path_ping + "?id=" + id);
|
||||
elm.setAttribute('href', "#");
|
||||
document.body.appendChild(elm);
|
||||
|
||||
// Trigger ping.
|
||||
elm.click();
|
||||
|
||||
document.body.removeChild(elm);
|
||||
}
|
||||
|
||||
function isPinged(id, expected, msg, callback) {
|
||||
var url = "http://mochi.test:8888/" + path_ping;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url + "?id=" + id);
|
||||
xhr.onload = function() {
|
||||
var isPinged = xhr.response === "ping";
|
||||
is(expected, isPinged, msg);
|
||||
|
||||
callback();
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
SpecialPowers.clearUserPref(TP_ENABLE_PREF);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
Promise.resolve()
|
||||
.then(testPingNonBlacklist)
|
||||
.then(testPingBlacklistSafebrowsingOff)
|
||||
.then(testPingBlacklistSafebrowsingOn)
|
||||
.then(function() {
|
||||
SimpleTest.finish();
|
||||
}).catch(function(e) {
|
||||
ok(false, "Some test failed with error " + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.registerCleanupFunction(cleanup);
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["browser.send_pings", true],
|
||||
["urlclassifier.trackingTable", "test-track-simple"],
|
||||
]}, runTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -35,11 +35,13 @@ function* do_test(test) {
|
||||
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
|
||||
|
||||
info("Moving mouse out of the way.");
|
||||
yield new Promise(resolve => {
|
||||
EventUtils.synthesizeNativeMouseMove(tab.linkedBrowser, 300, 300, resolve);
|
||||
});
|
||||
|
||||
ContentTask.spawn(tab.linkedBrowser, test, function*(test) {
|
||||
info("creating input field");
|
||||
yield ContentTask.spawn(tab.linkedBrowser, test, function*(test) {
|
||||
let doc = content.document;
|
||||
let input = doc.createElement("input");
|
||||
doc.body.appendChild(input);
|
||||
@ -58,6 +60,7 @@ function* do_test(test) {
|
||||
});
|
||||
|
||||
if (test.value) {
|
||||
info("Creating mock filepicker to select files");
|
||||
let MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(window);
|
||||
MockFilePicker.returnValue = MockFilePicker.returnOK;
|
||||
@ -68,6 +71,7 @@ function* do_test(test) {
|
||||
// Open the File Picker dialog (MockFilePicker) to select
|
||||
// the files for the test.
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("#test_input", {}, tab.linkedBrowser);
|
||||
info("Waiting for the input to have the requisite files");
|
||||
yield ContentTask.spawn(tab.linkedBrowser, {}, function*() {
|
||||
let input = content.document.querySelector("#test_input");
|
||||
yield ContentTaskUtils.waitForCondition(() => input.files.length,
|
||||
@ -77,6 +81,8 @@ function* do_test(test) {
|
||||
} finally {
|
||||
MockFilePicker.cleanup();
|
||||
}
|
||||
} else {
|
||||
info("No real file selection required.");
|
||||
}
|
||||
|
||||
let awaitTooltipOpen = new Promise(resolve => {
|
||||
@ -89,17 +95,22 @@ function* do_test(test) {
|
||||
resolve(event.target);
|
||||
});
|
||||
});
|
||||
info("Initial mouse move");
|
||||
yield new Promise(resolve => {
|
||||
EventUtils.synthesizeNativeMouseMove(tab.linkedBrowser, 100, 5, resolve);
|
||||
});
|
||||
info("Waiting");
|
||||
yield new Promise(resolve => setTimeout(resolve, 100));
|
||||
info("Second mouse move");
|
||||
yield new Promise(resolve => {
|
||||
EventUtils.synthesizeNativeMouseMove(tab.linkedBrowser, 110, 15, resolve);
|
||||
});
|
||||
info("Waiting for tooltip to open");
|
||||
let tooltip = yield awaitTooltipOpen;
|
||||
|
||||
is(tooltip.getAttribute("label"), test.result, "tooltip label should match expectation");
|
||||
|
||||
info("Closing tab");
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user