Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: options.js

Issue 29536764: Issue 5587, 5748 - Use mobile options page on Firefox for Android (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Remove workaround for FOUC issue and update adblockplusui dependency Created Oct. 5, 2017, 1:24 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « options.html ('k') | popup.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: options.js
===================================================================
--- a/options.js
+++ b/options.js
@@ -10,738 +10,27 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
-/* global $, i18n, i18nTimeDateStrings */
-
"use strict";
-/**
- * Creates a wrapping function used to conveniently send a type of message.
- *
- * @param {Object} baseMessage The part of the message that's always sent
- * @param {...string} paramKeys Any message keys that have dynamic values. The
- * returned function will take the corresponding
- * values as arguments.
- * @return {function} The generated messaging function, optionally
- * taking any values as specified by the paramKeys
- * and finally an optional callback. (Although the
- * value arguments are optional their index must be
- * maintained. E.g. if you omit the first value you
- * must omit the second too.)
- */
-function wrapper(baseMessage, ...paramKeys)
-{
- return function(...paramValues /* , callback */)
- {
- let message = Object.assign(Object.create(null), baseMessage);
- let callback;
-
- if (paramValues.length > 0)
- {
- let lastArg = paramValues[paramValues.length - 1];
- if (typeof lastArg == "function")
- callback = lastArg;
-
- for (let i = 0; i < paramValues.length - (callback ? 1 : 0); i++)
- message[paramKeys[i]] = paramValues[i];
- }
-
- ext.backgroundPage.sendMessage(message, callback);
- };
-}
-
-const getDocLink = wrapper({type: "app.get", what: "doclink"}, "link");
-const getInfo = wrapper({type: "app.get"}, "what");
-const getPref = wrapper({type: "prefs.get"}, "key");
-const togglePref = wrapper({type: "prefs.toggle"}, "key");
-const getSubscriptions = wrapper({type: "subscriptions.get"},
- "downloadable", "special");
-const removeSubscription = wrapper({type: "subscriptions.remove"}, "url");
-const addSubscription = wrapper({type: "subscriptions.add"},
- "url", "title", "homepage");
-const toggleSubscription = wrapper({type: "subscriptions.toggle"},
- "url", "keepInstalled");
-const updateSubscription = wrapper({type: "subscriptions.update"}, "url");
-const importRawFilters = wrapper({type: "filters.importRaw"},
- "text", "removeExisting");
-const addFilter = wrapper({type: "filters.add"}, "text");
-const removeFilter = wrapper({type: "filters.remove"}, "text");
-const quoteCSS = wrapper({type: "composer.quoteCSS"}, "CSS");
-
-const whitelistedDomainRegexp = /^@@\|\|([^/:]+)\^\$document$/;
-const statusMessages = new Map([
- ["synchronize_invalid_url",
- "filters_subscription_lastDownload_invalidURL"],
- ["synchronize_connection_error",
- "filters_subscription_lastDownload_connectionError"],
- ["synchronize_invalid_data",
- "filters_subscription_lastDownload_invalidData"],
- ["synchronize_checksum_mismatch",
- "filters_subscription_lastDownload_checksumMismatch"]
-]);
-
-let delayedSubscriptionSelection = null;
-let acceptableAdsUrl;
-
-// Loads options from localStorage and sets UI elements accordingly
-function loadOptions()
-{
- // Set page title to i18n version of "Adblock Plus Options"
- document.title = i18n.getMessage("options");
+let iframe = document.getElementById("content");
- // Set links
- getPref("subscriptions_exceptionsurl", url =>
- {
- acceptableAdsUrl = url;
- $("#acceptableAdsLink").attr("href", acceptableAdsUrl);
- });
- getDocLink("acceptable_ads", url =>
- {
- $("#acceptableAdsDocs").attr("href", url);
- });
- getDocLink("filterdoc", url =>
- {
- setLinks("filter-must-follow-syntax", url);
- });
- getInfo("application", application =>
- {
- getInfo("platform", platform =>
- {
- if (platform == "chromium" && application != "opera")
- application = "chrome";
-
- getDocLink(application + "_support", url =>
- {
- setLinks("found-a-bug", url);
- });
-
- if (platform == "gecko")
- $("#firefox-warning").removeAttr("hidden");
- });
- });
-
- // Add event listeners
- $("#updateFilterLists").click(updateFilterLists);
- $("#startSubscriptionSelection").click(startSubscriptionSelection);
- $("#subscriptionSelector").change(updateSubscriptionSelection);
- $("#addSubscription").click(addSubscriptionClicked);
- $("#acceptableAds").click(toggleAcceptableAds);
- $("#whitelistForm").submit(addWhitelistDomain);
- $("#removeWhitelist").click(removeSelectedExcludedDomain);
- $("#customFilterForm").submit(addTypedFilter);
- $("#removeCustomFilter").click(removeSelectedFilters);
- $("#rawFiltersButton").click(toggleFiltersInRawFormat);
- $("#importRawFilters").click(importRawFiltersText);
-
- // Display jQuery UI elements
- $("#tabs").tabs();
- $("button:not(.subscriptionRemoveButton)").button();
- $(".refreshButton").button("option", "icons", {primary: "ui-icon-refresh"});
- $(".addButton").button("option", "icons", {primary: "ui-icon-plus"});
- $(".removeButton").button("option", "icons", {primary: "ui-icon-minus"});
-
- // Popuplate option checkboxes
- initCheckbox("shouldShowBlockElementMenu");
- initCheckbox("show_devtools_panel");
- initCheckbox("shouldShowNotifications", "notifications_ignoredcategories");
-
- getInfo("features", features =>
- {
- if (!features.devToolsPanel)
- document.getElementById("showDevtoolsPanelContainer").hidden = true;
- });
- getPref("notifications_showui", showNotificationsUI =>
- {
- if (!showNotificationsUI)
- document.getElementById("shouldShowNotificationsContainer").hidden = true;
- });
-
- // Register listeners in the background message responder
- ext.backgroundPage.sendMessage({
- type: "app.listen",
- filter: ["addSubscription", "focusSection"]
- });
- ext.backgroundPage.sendMessage({
- type: "filters.listen",
- filter: ["added", "loaded", "removed"]
- });
- ext.backgroundPage.sendMessage({
- type: "prefs.listen",
- filter: ["notifications_ignoredcategories", "notifications_showui",
- "show_devtools_panel", "shouldShowBlockElementMenu"]
- });
- ext.backgroundPage.sendMessage({
- type: "subscriptions.listen",
- filter: ["added", "disabled", "homepage", "lastDownload", "removed",
- "title", "downloadStatus", "downloading"]
- });
-
- // Load recommended subscriptions
- loadRecommendations();
-
- // Show user's filters
- reloadFilters();
-}
-$(loadOptions);
-
-function convertSpecialSubscription(subscription)
+iframe.onload = () =>
{
- for (let filter of subscription.filters)
- {
- if (whitelistedDomainRegexp.test(filter.text))
- appendToListBox("excludedDomainsBox", RegExp.$1);
- else
- appendToListBox("userFiltersBox", filter.text);
- }
-}
-
-// Reloads the displayed subscriptions and filters
-function reloadFilters()
-{
- // Load user filter URLs
- let container = document.getElementById("filterLists");
- while (container.lastChild)
- container.removeChild(container.lastChild);
-
- getSubscriptions(true, false, subscriptions =>
- {
- for (let subscription of subscriptions)
- {
- if (subscription.url == acceptableAdsUrl)
- $("#acceptableAds").prop("checked", !subscription.disabled);
- else
- addSubscriptionEntry(subscription);
- }
- });
-
- // User-entered filters
- getSubscriptions(false, true, subscriptions =>
- {
- document.getElementById("userFiltersBox").innerHTML = "";
- document.getElementById("excludedDomainsBox").innerHTML = "";
-
- for (let subscription of subscriptions)
- convertSpecialSubscription(subscription);
- });
-}
-
-function initCheckbox(id, key)
-{
- key = key || id;
- let checkbox = document.getElementById(id);
-
- getPref(key, value =>
- {
- onPrefMessage(key, value);
- });
-
- checkbox.addEventListener("click", () =>
- {
- togglePref(key);
- }, false);
-}
-
-function loadRecommendations()
-{
- fetch("subscriptions.xml")
- .then(response =>
- {
- return response.text();
- })
- .then(text =>
- {
- let selectedIndex = 0;
- let selectedPrefix = null;
- let matchCount = 0;
-
- let list = document.getElementById("subscriptionSelector");
- let doc = new DOMParser().parseFromString(text, "application/xml");
- let elements = doc.documentElement.getElementsByTagName("subscription");
-
- for (let i = 0; i < elements.length; i++)
- {
- let element = elements[i];
- let option = new Option();
- option.text = element.getAttribute("title") + " (" +
- element.getAttribute("specialization") + ")";
- option._data = {
- title: element.getAttribute("title"),
- url: element.getAttribute("url"),
- homepage: element.getAttribute("homepage")
- };
-
- let prefix = element.getAttribute("prefixes");
- if (prefix)
- {
- prefix = prefix.replace(/\W/g, "_");
- option.style.fontWeight = "bold";
- option.style.backgroundColor = "#E0FFE0";
- option.style.color = "#000000";
- if (!selectedPrefix || selectedPrefix.length < prefix.length)
- {
- selectedIndex = i;
- selectedPrefix = prefix;
- matchCount = 1;
- }
- else if (selectedPrefix && selectedPrefix.length == prefix.length)
- {
- matchCount++;
-
- // If multiple items have a matching prefix of the same length:
- // Select one of the items randomly, probability should be the same
- // for all items. So we replace the previous match here with
- // probability 1/N (N being the number of matches).
- if (Math.random() * matchCount < 1)
- {
- selectedIndex = i;
- selectedPrefix = prefix;
- }
- }
- }
- list.appendChild(option);
- }
-
- let option = new Option();
- let label = i18n.getMessage("filters_addSubscriptionOther_label");
- option.text = label + "\u2026";
- option._data = null;
- list.appendChild(option);
-
- list.selectedIndex = selectedIndex;
-
- if (delayedSubscriptionSelection)
- startSubscriptionSelection(...delayedSubscriptionSelection);
- });
-}
-
-function startSubscriptionSelection(title, url)
-{
- let list = document.getElementById("subscriptionSelector");
- if (list.length == 0)
- {
- delayedSubscriptionSelection = [title, url];
- return;
- }
-
- $("#tabs").tabs("option", "active", 0);
- $("#addSubscriptionContainer").show();
- $("#addSubscriptionButton").hide();
- $("#subscriptionSelector").focus();
- if (typeof url != "undefined")
- {
- list.selectedIndex = list.length - 1;
- document.getElementById("customSubscriptionTitle").value = title;
- document.getElementById("customSubscriptionLocation").value = url;
- }
- updateSubscriptionSelection();
- document.getElementById("addSubscriptionContainer").scrollIntoView(true);
-}
-
-function updateSubscriptionSelection()
-{
- let list = document.getElementById("subscriptionSelector");
- let data = list.options[list.selectedIndex]._data;
- if (data)
- $("#customSubscriptionContainer").hide();
- else
- {
- $("#customSubscriptionContainer").show();
- $("#customSubscriptionTitle").focus();
- }
-}
-
-function addSubscriptionClicked()
-{
- let list = document.getElementById("subscriptionSelector");
- let data = list.options[list.selectedIndex]._data;
- if (data)
- addSubscription(data.url, data.title, data.homepage);
- else
- {
- let url = document.getElementById("customSubscriptionLocation")
- .value.trim();
- if (!/^https?:/i.test(url))
- {
- alert(i18n.getMessage("global_subscription_invalid_location"));
- $("#customSubscriptionLocation").focus();
- return;
- }
-
- let title = document.getElementById("customSubscriptionTitle").value.trim();
- if (!title)
- title = url;
-
- addSubscription(url, title, null);
- }
+ document.title = iframe.contentDocument.title;
+};
- $("#addSubscriptionContainer").hide();
- $("#customSubscriptionContainer").hide();
- $("#addSubscriptionButton").show();
-}
-
-function toggleAcceptableAds()
-{
- toggleSubscription(acceptableAdsUrl, true);
-}
-
-function findSubscriptionElement(subscription)
-{
- for (let child of document.getElementById("filterLists").childNodes)
- {
- if (child._subscription.url == subscription.url)
- return child;
- }
- return null;
-}
-
-function updateSubscriptionInfo(element, subscription)
-{
- if (subscription)
- element._subscription = subscription;
- else
- subscription = element._subscription;
-
- let title = element.getElementsByClassName("subscriptionTitle")[0];
- title.textContent = subscription.title;
- title.setAttribute("title", subscription.url);
- if (subscription.homepage)
- title.href = subscription.homepage;
- else
- title.href = subscription.url;
-
- let enabled = element.getElementsByClassName("subscriptionEnabled")[0];
- enabled.checked = !subscription.disabled;
-
- let lastUpdate = element.getElementsByClassName("subscriptionUpdate")[0];
- lastUpdate.classList.remove("error");
-
- let {downloadStatus} = subscription;
- if (subscription.isDownloading)
- {
- lastUpdate.textContent = i18n.getMessage(
- "filters_subscription_lastDownload_inProgress"
- );
- }
- else if (downloadStatus && downloadStatus != "synchronize_ok")
- {
- if (statusMessages.has(downloadStatus))
- {
- lastUpdate.textContent = i18n.getMessage(
- statusMessages.get(downloadStatus)
- );
- }
- else
- lastUpdate.textContent = downloadStatus;
- lastUpdate.classList.add("error");
- }
- else if (subscription.lastDownload > 0)
- {
- let timeDate = i18nTimeDateStrings(subscription.lastDownload * 1000);
- let messageID = (timeDate[1] ? "last_updated_at" : "last_updated_at_today");
- lastUpdate.textContent = i18n.getMessage(messageID, timeDate);
- }
-}
-
-function onSubscriptionMessage(action, subscription)
-{
- let element = findSubscriptionElement(subscription);
-
- switch (action)
- {
- case "disabled":
- case "downloading":
- case "downloadStatus":
- case "homepage":
- case "lastDownload":
- case "title":
- if (element)
- updateSubscriptionInfo(element, subscription);
- break;
- case "added":
- if (subscription.url.indexOf("~user") == 0)
- convertSpecialSubscription(subscription);
- else if (subscription.url == acceptableAdsUrl)
- $("#acceptableAds").prop("checked", true);
- else if (!element)
- addSubscriptionEntry(subscription);
- break;
- case "removed":
- if (subscription.url == acceptableAdsUrl)
- $("#acceptableAds").prop("checked", false);
- else if (element)
- element.parentNode.removeChild(element);
- break;
- }
-}
-
-function onPrefMessage(key, value)
-{
- switch (key)
- {
- case "notifications_showui":
- document.getElementById(
- "shouldShowNotificationsContainer"
- ).hidden = !value;
- return;
- case "notifications_ignoredcategories":
- key = "shouldShowNotifications";
- value = value.indexOf("*") == -1;
- break;
- }
- let checkbox = document.getElementById(key);
- if (checkbox)
- checkbox.checked = value;
-}
-
-function onFilterMessage(action, filter)
-{
- switch (action)
- {
- case "loaded":
- reloadFilters();
- break;
- case "added":
- if (whitelistedDomainRegexp.test(filter.text))
- appendToListBox("excludedDomainsBox", RegExp.$1);
- else
- appendToListBox("userFiltersBox", filter.text);
- break;
- case "removed":
- if (whitelistedDomainRegexp.test(filter.text))
- removeFromListBox("excludedDomainsBox", RegExp.$1);
- else
- removeFromListBox("userFiltersBox", filter.text);
- break;
- }
-}
-
-// Add a filter string to the list box.
-function appendToListBox(boxId, text)
-{
- // Note: document.createElement("option") is unreliable in Opera
- let elt = new Option();
- elt.text = text;
- elt.value = text;
- document.getElementById(boxId).appendChild(elt);
-}
-
-// Remove a filter string from a list box.
-function removeFromListBox(boxId, text)
-{
- let list = document.getElementById(boxId);
- // Edge does not support CSS.escape yet:
- // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/101410/
- quoteCSS(text, escapedCSS =>
- {
- let selector = "option[value=" + escapedCSS + "]";
- for (let option of list.querySelectorAll(selector))
- list.removeChild(option);
- });
-}
-
-function addWhitelistDomain(event)
-{
- event.preventDefault();
-
- let domain = document.getElementById(
- "newWhitelistDomain"
- ).value.replace(/\s/g, "");
- document.getElementById("newWhitelistDomain").value = "";
- if (!domain)
- return;
-
- let filterText = "@@||" + domain + "^$document";
- addFilter(filterText);
-}
-
-// Adds filter text that user typed to the selection box
-function addTypedFilter(event)
+chrome.runtime.sendMessage({
Oleksandr 2017/10/09 11:49:59 Edge does not support the 'chrome' namespace for e
Manish Jethani 2017/10/09 12:00:55 Thanks.
Sebastian Noack 2017/10/09 15:09:55 Note that we already do so in ext/common.js: https
+ type: "app.get",
+ what: "application"
+},
+application =>
{
- event.preventDefault();
-
- let element = document.getElementById("newFilter");
- addFilter(element.value, errors =>
- {
- if (errors.length > 0)
- alert(errors.join("\n"));
- else
- element.value = "";
- });
-}
-
-// Removes currently selected whitelisted domains
-function removeSelectedExcludedDomain(event)
-{
- event.preventDefault();
- let remove = [];
- for (let option of document.getElementById("excludedDomainsBox").options)
- {
- if (option.selected)
- remove.push(option.value);
- }
- if (!remove.length)
- return;
-
- for (let domain of remove)
- removeFilter("@@||" + domain + "^$document");
-}
-
-// Removes all currently selected filters
-function removeSelectedFilters(event)
-{
- event.preventDefault();
- let options = document.querySelectorAll("#userFiltersBox > option:checked");
- for (let option of options)
- removeFilter(option.value);
-}
-
-// Shows raw filters box and fills it with the current user filters
-function toggleFiltersInRawFormat(event)
-{
- event.preventDefault();
-
- let rawFilters = document.getElementById("rawFilters");
- let filters = [];
-
- if (rawFilters.style.display != "table-row")
- {
- rawFilters.style.display = "table-row";
- for (let option of document.getElementById("userFiltersBox").options)
- filters.push(option.value);
- }
- else
- {
- rawFilters.style.display = "none";
- }
-
- document.getElementById("rawFiltersText").value = filters.join("\n");
-}
-
-// Imports filters in the raw text box
-function importRawFiltersText()
-{
- let text = document.getElementById("rawFiltersText").value;
-
- importRawFilters(text, true, errors =>
- {
- if (errors.length > 0)
- alert(errors.join("\n"));
- else
- $("#rawFilters").hide();
- });
-}
-
-// Called when user explicitly requests filter list updates
-function updateFilterLists()
-{
- // Without the URL parameter this will update all subscriptions
- updateSubscription();
-}
-
-// Adds a subscription entry to the UI.
-function addSubscriptionEntry(subscription)
-{
- let template = document.getElementById("subscriptionTemplate");
- let element = template.cloneNode(true);
- element.removeAttribute("id");
- element._subscription = subscription;
-
- let removeButton = element.getElementsByClassName(
- "subscriptionRemoveButton"
- )[0];
- removeButton.setAttribute("title", removeButton.textContent);
- removeButton.textContent = "\xD7";
- removeButton.addEventListener("click", () =>
- {
- if (!confirm(i18n.getMessage("global_remove_subscription_warning")))
- return;
-
- removeSubscription(subscription.url);
- }, false);
-
- getPref("additional_subscriptions", additionalSubscriptions =>
- {
- if (additionalSubscriptions.includes(subscription.url))
- removeButton.style.visibility = "hidden";
- });
-
- let enabled = element.getElementsByClassName("subscriptionEnabled")[0];
- enabled.addEventListener("click", () =>
- {
- subscription.disabled = !subscription.disabled;
- toggleSubscription(subscription.url, true);
- }, false);
-
- updateSubscriptionInfo(element);
-
- document.getElementById("filterLists").appendChild(element);
-}
-
-function setLinks(id, ...args)
-{
- let element = document.getElementById(id);
- if (!element)
- return;
-
- let links = element.getElementsByTagName("a");
- for (let i = 0; i < links.length; i++)
- {
- if (typeof args[i] == "string")
- {
- links[i].href = args[i];
- links[i].setAttribute("target", "_blank");
- }
- else if (typeof args[i] == "function")
- {
- links[i].href = "javascript:void(0);";
- links[i].addEventListener("click", args[i], false);
- }
- }
-}
-
-ext.onMessage.addListener(message =>
-{
- switch (message.type)
- {
- case "app.respond":
- switch (message.action)
- {
- case "addSubscription":
- let subscription = message.args[0];
- startSubscriptionSelection(subscription.title, subscription.url);
- break;
- case "focusSection":
- for (let tab of document.getElementsByClassName("ui-tabs-panel"))
- {
- let found = tab.querySelector(
- "[data-section='" + message.args[0] + "']"
- );
- if (!found)
- continue;
-
- let previous = document.getElementsByClassName("focused");
- if (previous.length > 0)
- previous[0].classList.remove("focused");
-
- let index = $("[href='#" + tab.id + "']").parent().index();
- $("#tabs").tabs("option", "active", index);
- found.classList.add("focused");
- }
- break;
- }
- break;
- case "filters.respond":
- onFilterMessage(message.action, message.args[0]);
- break;
- case "prefs.respond":
- onPrefMessage(message.action, message.args[0]);
- break;
- case "subscriptions.respond":
- onSubscriptionMessage(message.action, message.args[0]);
- break;
- }
+ // Load the mobile version of the options page on Firefox for Android.
+ iframe.src = iframe.getAttribute("data-src-" + application) ||
+ iframe.getAttribute("data-src");
});
« no previous file with comments | « options.html ('k') | popup.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld