From 0c6c32a0e6243040360d9dce05af377e95a71a5f Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 09:31:07 +0200 Subject: Bug 846635 - Use asynchronous getCharsetForURI in getShortcutOrURI Issue #121 --- application/palemoon/base/content/browser.js | 239 ++++++++++---------- application/palemoon/base/content/openLocation.js | 78 ++++--- application/palemoon/base/content/tabbrowser.xml | 4 +- .../palemoon/base/content/urlbarBindings.xml | 242 +++++++++++---------- 4 files changed, 304 insertions(+), 259 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index b2d260101..73661a8c9 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -9,6 +9,9 @@ var Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource:///modules/RecentWindow.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu", "resource:///modules/CharsetMenu.jsm"); @@ -1896,88 +1899,89 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup) { } catch (e) {} } -function getShortcutOrURI(aURL, aPostDataRef, aMayInheritPrincipal) { - // Initialize outparam to false - if (aMayInheritPrincipal) - aMayInheritPrincipal.value = false; - - var shortcutURL = null; - var keyword = aURL; - var param = ""; - - var offset = aURL.indexOf(" "); - if (offset > 0) { - keyword = aURL.substr(0, offset); - param = aURL.substr(offset + 1); - } - - if (!aPostDataRef) - aPostDataRef = {}; - - var engine = Services.search.getEngineByAlias(keyword); - if (engine) { - var submission = engine.getSubmission(param); - aPostDataRef.value = submission.postData; - return submission.uri.spec; - } - - [shortcutURL, aPostDataRef.value] = - PlacesUtils.getURLAndPostDataForKeyword(keyword); +function getShortcutOrURIAndPostData(aURL) { + return Task.spawn(function() { + let mayInheritPrincipal = false; + let postData = null; + let shortcutURL = null; + let keyword = aURL; + let param = ""; + + let offset = aURL.indexOf(" "); + if (offset > 0) { + keyword = aURL.substr(0, offset); + param = aURL.substr(offset + 1); + } + + let engine = Services.search.getEngineByAlias(keyword); + if (engine) { + let submission = engine.getSubmission(param); + postData = submission.postData; + throw new Task.Result({ postData: submission.postData, + url: submission.uri.spec, + mayInheritPrincipal: mayInheritPrincipal }); + } + + [shortcutURL, postData] = + PlacesUtils.getURLAndPostDataForKeyword(keyword); + + if (!shortcutURL) + throw new Task.Result({ postData: postData, url: aURL, + mayInheritPrincipal: mayInheritPrincipal }); + + let escapedPostData = ""; + if (postData) + escapedPostData = unescape(postData); + + if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { + let charset = ""; + const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; + let matches = shortcutURL.match(re); + if (matches) + [, shortcutURL, charset] = matches; + else { + // Try to get the saved character-set. + try { + // makeURI throws if URI is invalid. + // Will return an empty string if character-set is not found. + charset = yield PlacesUtils.getCharsetForURI(makeURI(shortcutURL)); + } catch (e) {} + } - if (!shortcutURL) - return aURL; + // encodeURIComponent produces UTF-8, and cannot be used for other charsets. + // escape() works in those cases, but it doesn't uri-encode +, @, and /. + // Therefore we need to manually replace these ASCII characters by their + // encodeURIComponent result, to match the behavior of nsEscape() with + // url_XPAlphas + let encodedParam = ""; + if (charset && charset != "UTF-8") + encodedParam = escape(convertFromUnicode(charset, param)). + replace(/[+@\/]+/g, encodeURIComponent); + else // Default charset is UTF-8 + encodedParam = encodeURIComponent(param); - var postData = ""; - if (aPostDataRef.value) - postData = unescape(aPostDataRef.value); + shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); - if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) { - var charset = ""; - const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; - var matches = shortcutURL.match(re); - if (matches) - [, shortcutURL, charset] = matches; - else { - // Try to get the saved character-set. - try { - // makeURI throws if URI is invalid. - // Will return an empty string if character-set is not found. - charset = PlacesUtils.history.getCharsetForURI(makeURI(shortcutURL)); - } catch (e) {} + if (/%s/i.test(escapedPostData)) // POST keyword + postData = getPostDataStream(escapedPostData, param, encodedParam, + "application/x-www-form-urlencoded"); } + else if (param) { + // This keyword doesn't take a parameter, but one was provided. Just return + // the original URL. + postData = null; - // encodeURIComponent produces UTF-8, and cannot be used for other charsets. - // escape() works in those cases, but it doesn't uri-encode +, @, and /. - // Therefore we need to manually replace these ASCII characters by their - // encodeURIComponent result, to match the behavior of nsEscape() with - // url_XPAlphas - var encodedParam = ""; - if (charset && charset != "UTF-8") - encodedParam = escape(convertFromUnicode(charset, param)). - replace(/[+@\/]+/g, encodeURIComponent); - else // Default charset is UTF-8 - encodedParam = encodeURIComponent(param); - - shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); - - if (/%s/i.test(postData)) // POST keyword - aPostDataRef.value = getPostDataStream(postData, param, encodedParam, - "application/x-www-form-urlencoded"); - } - else if (param) { - // This keyword doesn't take a parameter, but one was provided. Just return - // the original URL. - aPostDataRef.value = null; - - return aURL; - } + throw new Task.Result({ postData: postData, url: aURL, + mayInheritPrincipal: mayInheritPrincipal }); + } - // This URL came from a bookmark, so it's safe to let it inherit the current - // document's principal. - if (aMayInheritPrincipal) - aMayInheritPrincipal.value = true; + // This URL came from a bookmark, so it's safe to let it inherit the current + // document's principal. + mayInheritPrincipal = true; - return shortcutURL; + throw new Task.Result({ postData: postData, url: shortcutURL, + mayInheritPrincipal: mayInheritPrincipal }); + }); } function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) { @@ -2722,12 +2726,13 @@ var newTabButtonObserver = { onDrop: function (aEvent) { let url = browserDragAndDrop.drop(aEvent, { }); - var postData = {}; - url = getShortcutOrURI(url, postData); - if (url) { - // allow third-party services to fixup this URL - openNewTabWith(url, null, postData.value, aEvent, true); - } + Task.spawn(function() { + let data = yield getShortcutOrURIAndPostData(url); + if (data.url) { + // allow third-party services to fixup this URL + openNewTabWith(data.url, null, data.postData, aEvent, true); + } + }); } } @@ -2742,12 +2747,13 @@ var newWindowButtonObserver = { onDrop: function (aEvent) { let url = browserDragAndDrop.drop(aEvent, { }); - var postData = {}; - url = getShortcutOrURI(url, postData); - if (url) { - // allow third-party services to fixup this URL - openNewWindowWith(url, null, postData.value, true); - } + Task.spawn(function() { + let data = yield getShortcutOrURIAndPostData(url); + if (data.url) { + // allow third-party services to fixup this URL + openNewWindowWith(data.url, null, data.postData, true); + } + }); } } @@ -5035,36 +5041,52 @@ function middleMousePaste(event) { // bar's behavior (stripsurroundingwhitespace) clipboard = clipboard.replace(/\s*\n\s*/g, ""); - let mayInheritPrincipal = { value: false }; - let url = getShortcutOrURI(clipboard, mayInheritPrincipal); - try { - makeURI(url); - } catch (ex) { - // Not a valid URI. - return; + // if it's not the current tab, we don't need to do anything because the + // browser doesn't exist. + let where = whereToOpenLink(event, true, false); + let lastLocationChange; + if (where == "current") { + lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; } - try { - addToUrlbarHistory(url); - } catch (ex) { - // Things may go wrong when adding url to session history, - // but don't let that interfere with the loading of the url. - Cu.reportError(ex); - } + Task.spawn(function() { + let data = yield getShortcutOrURIAndPostData(clipboard); + try { + makeURI(data.url); + } catch (ex) { + // Not a valid URI. + return; + } + + try { + addToUrlbarHistory(data.url); + } catch (ex) { + // Things may go wrong when adding url to session history, + // but don't let that interfere with the loading of the url. + Cu.reportError(ex); + } - openUILink(url, event, - { ignoreButton: true, - disallowInheritPrincipal: !mayInheritPrincipal.value }); + if (where != "current" || + lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) { + openUILink(data.url, event, + { ignoreButton: true, + disallowInheritPrincipal: !data.mayInheritPrincipal }); + } + }); event.stopPropagation(); } function handleDroppedLink(event, url, name) { - let postData = { }; - let uri = getShortcutOrURI(url, postData); - if (uri) - loadURI(uri, null, postData.value, false); + let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; + + Task.spawn(function() { + let data = yield getShortcutOrURIAndPostData(url); + if (data.url && + lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) + loadURI(data.url, null, data.postData, false); + }); // Keep the event from being handled by the dragDrop listeners // built-in to goanna if they happen to be above us. @@ -5179,7 +5201,6 @@ function charsetLoadListener() { } } - var gPageStyleMenu = { _getAllStyleSheets: function (frameset) { diff --git a/application/palemoon/base/content/openLocation.js b/application/palemoon/base/content/openLocation.js index 5b731c7e8..b00dbc571 100644 --- a/application/palemoon/base/content/openLocation.js +++ b/application/palemoon/base/content/openLocation.js @@ -16,6 +16,7 @@ try { } Components.utils.import("resource:///modules/openLocationLastURL.jsm", openLocationModule); +Components.utils.import("resource://gre/modules/Task.jsm"); let gOpenLocationLastURL = new openLocationModule.OpenLocationLastURL(window.opener); function onLoad() @@ -61,45 +62,52 @@ function doEnabling() function open() { - var url; - var postData = {}; - var mayInheritPrincipal = {value: false}; - if (browser) - url = browser.getShortcutOrURI(dialog.input.value, postData, mayInheritPrincipal); - else - url = dialog.input.value; + Task.spawn(function() { + let url; + let postData = null; + let mayInheritPrincipal = false; + + if (browser) { + let data = yield browser.getShortcutOrURIAndPostData(dialog.input.value); + url = data.url; + postData = data.postData; + mayInheritPrincipal = data.mayInheritPrincipal; + } else { + url = dialog.input.value; + } - try { - // Whichever target we use for the load, we allow third-party services to - // fixup the URI - switch (dialog.openWhereList.value) { - case "0": - var webNav = Components.interfaces.nsIWebNavigation; - var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - if (!mayInheritPrincipal.value) - flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; - browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData.value); - break; - case "1": - window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no", - url, postData.value, null, null, true); - break; - case "3": - browser.delayedOpenTab(url, null, null, postData.value, true); - break; + try { + // Whichever target we use for the load, we allow third-party services to + // fixup the URI + switch (dialog.openWhereList.value) { + case "0": + var webNav = Components.interfaces.nsIWebNavigation; + var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; + if (!mayInheritPrincipal) + flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; + browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData); + break; + case "1": + window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no", + url, postData, null, null, true); + break; + case "3": + browser.delayedOpenTab(url, null, null, postData, true); + break; + } + } + catch(exception) { } - } - catch(exception) { - } - if (pref) { - gOpenLocationLastURL.value = dialog.input.value; - pref.setIntPref("general.open_location.last_window_choice", dialog.openWhereList.value); - } + if (pref) { + gOpenLocationLastURL.value = dialog.input.value; + pref.setIntPref("general.open_location.last_window_choice", dialog.openWhereList.value); + } + + // Delay closing slightly to avoid timing bug on Linux. + window.close(); + }); - // Delay closing slightly to avoid timing bug on Linux. - window.close(); return false; } diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index 4b10855a7..4f713d76f 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -738,8 +738,10 @@ aFlags]); } - if (topLevel) + if (topLevel) { this.mBrowser.lastURI = aLocation; + this.mBrowser.lastLocationChange = Date.now(); + } }, onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) { diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml index c99819f0d..e0bb40d64 100644 --- a/application/palemoon/base/content/urlbarBindings.xml +++ b/application/palemoon/base/content/urlbarBindings.xml @@ -263,151 +263,165 @@ var postData = null; var action = this._parseActionUrl(url); - if (action) { - url = action.param; - if (this.hasAttribute("actiontype")) { - if (action.type == "switchtab") { - this.handleRevert(); - let prevTab = gBrowser.selectedTab; - if (switchToTabHavingURI(url) && - isTabEmpty(prevTab)) - gBrowser.removeTab(prevTab); + let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; + Task.spawn(function() { + let matchLastLocationChange = true; + if (action) { + url = action.param; + if (this.hasAttribute("actiontype")) { + if (action.type == "switchtab") { + this.handleRevert(); + let prevTab = gBrowser.selectedTab; + if (switchToTabHavingURI(url) && + isTabEmpty(prevTab)) + gBrowser.removeTab(prevTab); + } + return; } - return; } - } - else { - [url, postData, mayInheritPrincipal] = this._canonizeURL(aTriggeringEvent); - if (!url) - return; - } + else { + [url, postData, mayInheritPrincipal] = yield this._canonizeURL(aTriggeringEvent); + matchLastLocationChange = (lastLocationChange == + gBrowser.selectedBrowser.lastLocationChange); + if (!url) + return; + } - this.value = url; - gBrowser.userTypedValue = url; - try { - addToUrlbarHistory(url); - } catch (ex) { - // Things may go wrong when adding url to session history, - // but don't let that interfere with the loading of the url. - Cu.reportError(ex); - } + this.value = url; + gBrowser.userTypedValue = url; + try { + addToUrlbarHistory(url); + } catch (ex) { + // Things may go wrong when adding url to session history, + // but don't let that interfere with the loading of the url. + Cu.reportError(ex); + } - function loadCurrent() { - let webnav = Ci.nsIWebNavigation; - let flags = webnav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - webnav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - // Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from - // inheriting the currently loaded document's principal, unless this - // URL is marked as safe to inherit (e.g. came from a bookmark - // keyword). - if (!mayInheritPrincipal) - flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; - gBrowser.loadURIWithFlags(url, flags, null, null, postData); - } + function loadCurrent() { + let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; + // Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from + // inheriting the currently loaded document's principal, unless this + // URL is marked as safe to inherit (e.g. came from a bookmark + // keyword). + if (!mayInheritPrincipal) + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; + // If the value wasn't typed, we know that we decoded the value as + // UTF-8 (see losslessDecodeURI) + if (!this.valueIsTyped) + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_URI_IS_UTF8; + gBrowser.loadURIWithFlags(url, flags, null, null, postData); + } - // Focus the content area before triggering loads, since if the load - // occurs in a new tab, we want focus to be restored to the content - // area when the current tab is re-selected. - gBrowser.selectedBrowser.focus(); + // Focus the content area before triggering loads, since if the load + // occurs in a new tab, we want focus to be restored to the content + // area when the current tab is re-selected. + gBrowser.selectedBrowser.focus(); - let isMouseEvent = aTriggeringEvent instanceof MouseEvent; - let altEnter = !isMouseEvent && aTriggeringEvent && aTriggeringEvent.altKey; + let isMouseEvent = aTriggeringEvent instanceof MouseEvent; + let altEnter = !isMouseEvent && aTriggeringEvent && aTriggeringEvent.altKey; - if (altEnter) { - // XXX This was added a long time ago, and I'm not sure why it is - // necessary. Alt+Enter's default action might cause a system beep, - // or something like that? - aTriggeringEvent.preventDefault(); - aTriggeringEvent.stopPropagation(); - } + if (altEnter) { + // XXX This was added a long time ago, and I'm not sure why it is + // necessary. Alt+Enter's default action might cause a system beep, + // or something like that? + aTriggeringEvent.preventDefault(); + aTriggeringEvent.stopPropagation(); + } - // If the current tab is empty, ignore Alt+Enter (just reuse this tab) - altEnter = altEnter && !isTabEmpty(gBrowser.selectedTab); + // If the current tab is empty, ignore Alt+Enter (just reuse this tab) + altEnter = altEnter && !isTabEmpty(gBrowser.selectedTab); - if (isMouseEvent || altEnter) { - // Use the standard UI link behaviors for clicks or Alt+Enter - let where = "tab"; - if (isMouseEvent) - where = whereToOpenLink(aTriggeringEvent, false, false); + if (isMouseEvent || altEnter) { + // Use the standard UI link behaviors for clicks or Alt+Enter + let where = "tab"; + if (isMouseEvent) + where = whereToOpenLink(aTriggeringEvent, false, false); - if (where == "current") { - loadCurrent(); + if (where == "current") { + if (matchLastLocationChange) { + loadCurrent(); + } + } else { + this.handleRevert(); + let params = { allowThirdPartyFixup: true, + postData: postData, + initiatingDoc: document }; + if (!this.valueIsTyped) + params.isUTF8 = true; + openUILinkIn(url, where, params); + } } else { - this.handleRevert(); - let params = { allowThirdPartyFixup: true, - postData: postData, - initiatingDoc: document }; - openUILinkIn(url, where, params); + if (matchLastLocationChange) { + loadCurrent(); + } } - } else { - loadCurrent(); - } + }.bind(this)); ]]> = 0) { + url = url.substring(0, firstSlash) + suffix + + url.substring(firstSlash + 1); + } else { + url = url + suffix; + } - if (firstSlash >= 0) { - url = url.substring(0, firstSlash) + suffix + - url.substring(firstSlash + 1); - } else { - url = url + suffix; + url = "http://www." + url; } - - url = "http://www." + url; } - } - var postData = {}; - var mayInheritPrincipal = { value: false }; - url = getShortcutOrURI(url, postData, mayInheritPrincipal); + let data = yield getShortcutOrURIAndPostData(url); - return [url, postData.value, mayInheritPrincipal.value]; + throw new Task.Result([data.url, data.postData, data.mayInheritPrincipal]); + }.bind(this)); ]]> -- cgit v1.2.3 From f2b4134845cb61831847e6746de2f15051d65a08 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 09:46:17 +0200 Subject: Bug 989984 - getShortcutOrURIAndPostData should have a synchronous callback behavior Issue #112 --- application/palemoon/base/content/browser.js | 140 +++++++++++--------- .../palemoon/base/content/urlbarBindings.xml | 147 +++++++++++---------- 2 files changed, 152 insertions(+), 135 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 73661a8c9..154badae5 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -1899,55 +1899,47 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup) { } catch (e) {} } -function getShortcutOrURIAndPostData(aURL) { - return Task.spawn(function() { - let mayInheritPrincipal = false; - let postData = null; - let shortcutURL = null; - let keyword = aURL; - let param = ""; - - let offset = aURL.indexOf(" "); - if (offset > 0) { - keyword = aURL.substr(0, offset); - param = aURL.substr(offset + 1); - } - - let engine = Services.search.getEngineByAlias(keyword); - if (engine) { - let submission = engine.getSubmission(param); - postData = submission.postData; - throw new Task.Result({ postData: submission.postData, - url: submission.uri.spec, - mayInheritPrincipal: mayInheritPrincipal }); - } - - [shortcutURL, postData] = - PlacesUtils.getURLAndPostDataForKeyword(keyword); - - if (!shortcutURL) - throw new Task.Result({ postData: postData, url: aURL, - mayInheritPrincipal: mayInheritPrincipal }); - - let escapedPostData = ""; - if (postData) - escapedPostData = unescape(postData); - - if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { - let charset = ""; - const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; - let matches = shortcutURL.match(re); - if (matches) - [, shortcutURL, charset] = matches; - else { - // Try to get the saved character-set. - try { - // makeURI throws if URI is invalid. - // Will return an empty string if character-set is not found. - charset = yield PlacesUtils.getCharsetForURI(makeURI(shortcutURL)); - } catch (e) {} - } +function getShortcutOrURIAndPostData(aURL, aCallback) { + let mayInheritPrincipal = false; + let postData = null; + let shortcutURL = null; + let keyword = aURL; + let param = ""; + + let offset = aURL.indexOf(" "); + if (offset > 0) { + keyword = aURL.substr(0, offset); + param = aURL.substr(offset + 1); + } + + let engine = Services.search.getEngineByAlias(keyword); + if (engine) { + let submission = engine.getSubmission(param); + postData = submission.postData; + aCallback({ postData: submission.postData, url: submission.uri.spec, + mayInheritPrincipal: mayInheritPrincipal }); + return; + } + + [shortcutURL, postData] = + PlacesUtils.getURLAndPostDataForKeyword(keyword); + + if (!shortcutURL) { + aCallback({ postData: postData, url: aURL, + mayInheritPrincipal: mayInheritPrincipal }); + return; + } + + let escapedPostData = ""; + if (postData) + escapedPostData = unescape(postData); + if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { + let charset = ""; + const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; + let matches = shortcutURL.match(re); + + let continueOperation = function () { // encodeURIComponent produces UTF-8, and cannot be used for other charsets. // escape() works in those cases, but it doesn't uri-encode +, @, and /. // Therefore we need to manually replace these ASCII characters by their @@ -1965,23 +1957,45 @@ function getShortcutOrURIAndPostData(aURL) { if (/%s/i.test(escapedPostData)) // POST keyword postData = getPostDataStream(escapedPostData, param, encodedParam, "application/x-www-form-urlencoded"); + + // This URL came from a bookmark, so it's safe to let it inherit the current + // document's principal. + mayInheritPrincipal = true; + + aCallback({ postData: postData, url: shortcutURL, + mayInheritPrincipal: mayInheritPrincipal }); } - else if (param) { - // This keyword doesn't take a parameter, but one was provided. Just return - // the original URL. - postData = null; - throw new Task.Result({ postData: postData, url: aURL, - mayInheritPrincipal: mayInheritPrincipal }); + if (matches) { + [, shortcutURL, charset] = matches; + continueOperation(); + } else { + // Try to get the saved character-set. + // makeURI throws if URI is invalid. + // Will return an empty string if character-set is not found. + try { + PlacesUtils.getCharsetForURI(makeURI(shortcutURL)) + .then(c => { charset = c; continueOperation(); }); + } catch (ex) { + continueOperation(); + } } + } + else if (param) { + // This keyword doesn't take a parameter, but one was provided. Just return + // the original URL. + postData = null; + aCallback({ postData: postData, url: aURL, + mayInheritPrincipal: mayInheritPrincipal }); + } else { // This URL came from a bookmark, so it's safe to let it inherit the current // document's principal. mayInheritPrincipal = true; - throw new Task.Result({ postData: postData, url: shortcutURL, - mayInheritPrincipal: mayInheritPrincipal }); - }); + aCallback({ postData: postData, url: shortcutURL, + mayInheritPrincipal: mayInheritPrincipal }); + } } function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) { @@ -2726,8 +2740,7 @@ var newTabButtonObserver = { onDrop: function (aEvent) { let url = browserDragAndDrop.drop(aEvent, { }); - Task.spawn(function() { - let data = yield getShortcutOrURIAndPostData(url); + getShortcutOrURIAndPostData(url, data => { if (data.url) { // allow third-party services to fixup this URL openNewTabWith(data.url, null, data.postData, aEvent, true); @@ -2747,8 +2760,7 @@ var newWindowButtonObserver = { onDrop: function (aEvent) { let url = browserDragAndDrop.drop(aEvent, { }); - Task.spawn(function() { - let data = yield getShortcutOrURIAndPostData(url); + getShortcutOrURIAndPostData(url, data => { if (data.url) { // allow third-party services to fixup this URL openNewWindowWith(data.url, null, data.postData, true); @@ -5049,8 +5061,7 @@ function middleMousePaste(event) { lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; } - Task.spawn(function() { - let data = yield getShortcutOrURIAndPostData(clipboard); + getShortcutOrURIAndPostData(clipboard, data => { try { makeURI(data.url); } catch (ex) { @@ -5081,8 +5092,7 @@ function handleDroppedLink(event, url, name) { let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - Task.spawn(function() { - let data = yield getShortcutOrURIAndPostData(url); + getShortcutOrURIAndPostData(url, data => { if (data.url && lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) loadURI(data.url, null, data.postData, false); diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml index e0bb40d64..44b398304 100644 --- a/application/palemoon/base/content/urlbarBindings.xml +++ b/application/palemoon/base/content/urlbarBindings.xml @@ -264,29 +264,35 @@ var action = this._parseActionUrl(url); let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - Task.spawn(function() { - let matchLastLocationChange = true; - if (action) { - url = action.param; - if (this.hasAttribute("actiontype")) { - if (action.type == "switchtab") { - this.handleRevert(); - let prevTab = gBrowser.selectedTab; - if (switchToTabHavingURI(url) && - isTabEmpty(prevTab)) - gBrowser.removeTab(prevTab); - } - return; + + let matchLastLocationChange = true; + if (action) { + url = action.param; + if (this.hasAttribute("actiontype")) { + if (action.type == "switchtab") { + this.handleRevert(); + let prevTab = gBrowser.selectedTab; + if (switchToTabHavingURI(url) && + isTabEmpty(prevTab)) + gBrowser.removeTab(prevTab); } + return; } - else { - [url, postData, mayInheritPrincipal] = yield this._canonizeURL(aTriggeringEvent); - matchLastLocationChange = (lastLocationChange == - gBrowser.selectedBrowser.lastLocationChange); - if (!url) - return; - } + continueOperation.call(this); + } + else { + this._canonizeURL(aTriggeringEvent, response => { + [url, postData, mayInheritPrincipal] = response; + if (url) { + matchLastLocationChange = (lastLocationChange == + gBrowser.selectedBrowser.lastLocationChange); + continueOperation.call(this); + } + }); + } + function continueOperation() + { this.value = url; gBrowser.userTypedValue = url; try { @@ -355,73 +361,74 @@ loadCurrent(); } } - }.bind(this)); + } ]]> + = 0) { - url = url.substring(0, firstSlash) + suffix + - url.substring(firstSlash + 1); - } else { - url = url + suffix; - } + let firstSlash = url.indexOf("/"); - url = "http://www." + url; + if (firstSlash >= 0) { + url = url.substring(0, firstSlash) + suffix + + url.substring(firstSlash + 1); + } else { + url = url + suffix; } - } - let data = yield getShortcutOrURIAndPostData(url); + url = "http://www." + url; + } + } - throw new Task.Result([data.url, data.postData, data.mayInheritPrincipal]); - }.bind(this)); + getShortcutOrURIAndPostData(url, data => { + aCallback([data.url, data.postData, data.mayInheritPrincipal]); + }); ]]> -- cgit v1.2.3 From 451cbfc0393ee0f3b8d18f856e6c8ad88d57b172 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 09:48:39 +0200 Subject: Bug 1100291 - Make getShortcutOrURIAndPostData() async by calling the passed callback off a zero timeout Issue #112 --- application/palemoon/base/content/browser.js | 6 ++++++ application/palemoon/base/content/urlbarBindings.xml | 12 ++---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 154badae5..be7993961 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -1906,6 +1906,12 @@ function getShortcutOrURIAndPostData(aURL, aCallback) { let keyword = aURL; let param = ""; + // XXX Bug 1100294 will remove this little hack by using an async version of + // PlacesUtils.getURLAndPostDataForKeyword(). For now we simulate an async + // execution with at least a setTimeout(fn, 0). + let originalCallback = aCallback; + aCallback = data => setTimeout(() => originalCallback(data)); + let offset = aURL.indexOf(" "); if (offset > 0) { keyword = aURL.substr(0, offset); diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml index 44b398304..ec9feb22d 100644 --- a/application/palemoon/base/content/urlbarBindings.xml +++ b/application/palemoon/base/content/urlbarBindings.xml @@ -324,18 +324,10 @@ gBrowser.selectedBrowser.focus(); let isMouseEvent = aTriggeringEvent instanceof MouseEvent; - let altEnter = !isMouseEvent && aTriggeringEvent && aTriggeringEvent.altKey; - - if (altEnter) { - // XXX This was added a long time ago, and I'm not sure why it is - // necessary. Alt+Enter's default action might cause a system beep, - // or something like that? - aTriggeringEvent.preventDefault(); - aTriggeringEvent.stopPropagation(); - } // If the current tab is empty, ignore Alt+Enter (just reuse this tab) - altEnter = altEnter && !isTabEmpty(gBrowser.selectedTab); + let altEnter = !isMouseEvent && aTriggeringEvent && + aTriggeringEvent.altKey && !isTabEmpty(gBrowser.selectedTab); if (isMouseEvent || altEnter) { // Use the standard UI link behaviors for clicks or Alt+Enter -- cgit v1.2.3 From 54cd77a551a0576f7593d24dfc9d82abcf99154f Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:14:20 +0200 Subject: Bug 1100294 - Turn getShortcutOrURIAndPostData() into a task that uses the new keywords API Issue #121 --- application/palemoon/base/content/browser.js | 169 ++++++++++++--------- .../palemoon/base/content/urlbarBindings.xml | 2 +- 2 files changed, 99 insertions(+), 72 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index be7993961..7a85b18e9 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -1899,53 +1899,81 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup) { } catch (e) {} } -function getShortcutOrURIAndPostData(aURL, aCallback) { - let mayInheritPrincipal = false; - let postData = null; - let shortcutURL = null; - let keyword = aURL; - let param = ""; - - // XXX Bug 1100294 will remove this little hack by using an async version of - // PlacesUtils.getURLAndPostDataForKeyword(). For now we simulate an async - // execution with at least a setTimeout(fn, 0). - let originalCallback = aCallback; - aCallback = data => setTimeout(() => originalCallback(data)); - - let offset = aURL.indexOf(" "); - if (offset > 0) { - keyword = aURL.substr(0, offset); - param = aURL.substr(offset + 1); +/** + * Given a urlbar value, discerns between URIs, keywords and aliases. + * + * @param url + * The urlbar value. + * @param callback (optional, deprecated) + * The callback function invoked when done. This parameter is + * deprecated, please use the Promise that is returned. + * + * @return Promise<{ postData, url, mayInheritPrincipal }> + */ +function getShortcutOrURIAndPostData(url, callback = null) { + if (callback) { + Deprecated.warning("Please use the Promise returned by " + + "getShortcutOrURIAndPostData() instead of passing a " + + "callback", + "https://bugzilla.mozilla.org/show_bug.cgi?id=1100294"); } - let engine = Services.search.getEngineByAlias(keyword); - if (engine) { - let submission = engine.getSubmission(param); - postData = submission.postData; - aCallback({ postData: submission.postData, url: submission.uri.spec, - mayInheritPrincipal: mayInheritPrincipal }); - return; - } + return Task.spawn(function* () { + let mayInheritPrincipal = false; + let postData = null; + let shortcutURL = null; + let keyword = url; + let param = ""; - [shortcutURL, postData] = - PlacesUtils.getURLAndPostDataForKeyword(keyword); + let offset = url.indexOf(" "); + if (offset > 0) { + keyword = url.substr(0, offset); + param = url.substr(offset + 1); + } - if (!shortcutURL) { - aCallback({ postData: postData, url: aURL, - mayInheritPrincipal: mayInheritPrincipal }); - return; - } + let engine = Services.search.getEngineByAlias(keyword); + if (engine) { + let submission = engine.getSubmission(param, null, "keyword"); + postData = submission.postData; + return { postData: submission.postData, url: submission.uri.spec, + mayInheritPrincipal }; + } + + let entry = yield PlacesUtils.keywords.fetch(keyword); + if (entry) { + shortcutURL = entry.url.href; + postData = entry.postData; + } + + if (!shortcutURL) { + return { postData, url, mayInheritPrincipal }; + } + + let escapedPostData = ""; + if (postData) + escapedPostData = unescape(postData); - let escapedPostData = ""; - if (postData) - escapedPostData = unescape(postData); + if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { + let charset = ""; + const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; + let matches = shortcutURL.match(re); - if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { - let charset = ""; - const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; - let matches = shortcutURL.match(re); + if (matches) { + [, shortcutURL, charset] = matches; + } else { + let uri; + try { + // makeURI() throws if URI is invalid. + uri = makeURI(shortcutURL); + } catch (ex) {} + + if (uri) { + // Try to get the saved character-set. + // Will return an empty string if character-set is not found. + charset = yield PlacesUtils.getCharsetForURI(uri); + } + } - let continueOperation = function () { // encodeURIComponent produces UTF-8, and cannot be used for other charsets. // escape() works in those cases, but it doesn't uri-encode +, @, and /. // Therefore we need to manually replace these ASCII characters by their @@ -1968,40 +1996,29 @@ function getShortcutOrURIAndPostData(aURL, aCallback) { // document's principal. mayInheritPrincipal = true; - aCallback({ postData: postData, url: shortcutURL, - mayInheritPrincipal: mayInheritPrincipal }); + return { postData, url: shortcutURL, mayInheritPrincipal }; } - if (matches) { - [, shortcutURL, charset] = matches; - continueOperation(); - } else { - // Try to get the saved character-set. - // makeURI throws if URI is invalid. - // Will return an empty string if character-set is not found. - try { - PlacesUtils.getCharsetForURI(makeURI(shortcutURL)) - .then(c => { charset = c; continueOperation(); }); - } catch (ex) { - continueOperation(); - } + if (param) { + // This keyword doesn't take a parameter, but one was provided. Just return + // the original URL. + postData = null; + + return { postData, url, mayInheritPrincipal }; } - } - else if (param) { - // This keyword doesn't take a parameter, but one was provided. Just return - // the original URL. - postData = null; - aCallback({ postData: postData, url: aURL, - mayInheritPrincipal: mayInheritPrincipal }); - } else { // This URL came from a bookmark, so it's safe to let it inherit the current // document's principal. mayInheritPrincipal = true; - aCallback({ postData: postData, url: shortcutURL, - mayInheritPrincipal: mayInheritPrincipal }); - } + return { postData, url: shortcutURL, mayInheritPrincipal }; + }).then(data => { + if (callback) { + callback(data); + } + + return data; + }); } function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) { @@ -2746,7 +2763,7 @@ var newTabButtonObserver = { onDrop: function (aEvent) { let url = browserDragAndDrop.drop(aEvent, { }); - getShortcutOrURIAndPostData(url, data => { + getShortcutOrURIAndPostData(url).then(data => { if (data.url) { // allow third-party services to fixup this URL openNewTabWith(data.url, null, data.postData, aEvent, true); @@ -2766,7 +2783,7 @@ var newWindowButtonObserver = { onDrop: function (aEvent) { let url = browserDragAndDrop.drop(aEvent, { }); - getShortcutOrURIAndPostData(url, data => { + getShortcutOrURIAndPostData(url).then(data => { if (data.url) { // allow third-party services to fixup this URL openNewWindowWith(data.url, null, data.postData, true); @@ -5067,7 +5084,7 @@ function middleMousePaste(event) { lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; } - getShortcutOrURIAndPostData(clipboard, data => { + getShortcutOrURIAndPostData(clipboard).then(data => { try { makeURI(data.url); } catch (ex) { @@ -5094,11 +5111,21 @@ function middleMousePaste(event) { event.stopPropagation(); } -function handleDroppedLink(event, url, name) +// handleDroppedLink has the following 2 overloads: +// handleDroppedLink(event, url, name) +// handleDroppedLink(event, links) +function handleDroppedLink(event, urlOrLinks, name) { + let links; + if (Array.isArray(urlOrLinks)) { + links = urlOrLinks; + } else { + links = [{ url: urlOrLinks, name, type: "" }]; + } + let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - getShortcutOrURIAndPostData(url, data => { + getShortcutOrURIAndPostData(url).then(data => { if (data.url && lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) loadURI(data.url, null, data.postData, false); diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml index ec9feb22d..e859fe804 100644 --- a/application/palemoon/base/content/urlbarBindings.xml +++ b/application/palemoon/base/content/urlbarBindings.xml @@ -418,7 +418,7 @@ } } - getShortcutOrURIAndPostData(url, data => { + getShortcutOrURIAndPostData(url).then(data => { aCallback([data.url, data.postData, data.mayInheritPrincipal]); }); ]]> -- cgit v1.2.3 From 3c93fde763c87eaaa655a517cc93faa895415185 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:29:52 +0200 Subject: Bug 92737 - Part 2: Open multiple tabs when multiple items are dropped on non-remote content area browser.js: // handleDroppedLink has the following 2 overloads: // handleDroppedLink(event, url, name) // handleDroppedLink(event, links) function handleDroppedLink(event, urlOrLinks, name) { let links; if (Array.isArray(urlOrLinks)) { links = urlOrLinks; } else { links = [{ url: urlOrLinks, name, type: "" }]; } ...it is in the previous commit. --- application/palemoon/base/content/browser.js | 31 +++++++++--- application/palemoon/base/content/tabbrowser.xml | 61 +++++++++++++++++++++--- 2 files changed, 80 insertions(+), 12 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 7a85b18e9..1d1fd73ae 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -2677,8 +2677,8 @@ var browserDragAndDrop = { } }, - drop: function (aEvent, aName, aDisallowInherit) { - return Services.droppedLinkHandler.dropLink(aEvent, aName, aDisallowInherit); + dropLinks: function (aEvent, aDisallowInherit) { + return Services.droppedLinkHandler.dropLinks(aEvent, aDisallowInherit); } }; @@ -5125,10 +5125,29 @@ function handleDroppedLink(event, urlOrLinks, name) let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - getShortcutOrURIAndPostData(url).then(data => { - if (data.url && - lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) - loadURI(data.url, null, data.postData, false); + let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid"); + + let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); + if (event.shiftKey) + inBackground = !inBackground; + + Task.spawn(function*() { + let urls = []; + let postDatas = []; + for (let link of links) { + let data = yield getShortcutOrURIAndPostData(link.url); + urls.push(data.url); + postDatas.push(data.postData); + } + if (lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) { + gBrowser.loadTabs(urls, { + inBackground, + replace: true, + allowThirdPartyFixup: false, + postDatas, + userContextId, + }); + } }); // Keep the event from being handled by the dragDrop listeners diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index 4f713d76f..0d9c29395 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -1314,6 +1314,24 @@ 1; var owner = multiple || aLoadInBackground ? null : this.selectedTab; var firstTabAdded = null; + var targetTabIndex = -1; if (aReplace) { + let browser; + if (aTargetTab) { + browser = this.getBrowserForTab(aTargetTab); + targetTabIndex = aTargetTab._tPos; + } else { + browser = this.mCurrentBrowser; + targetTabIndex = this.tabContainer.selectedIndex; + } + let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; + if (aAllowThirdPartyFixup) { + flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | + Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; + } try { - this.loadURI(aURIs[0], null, null); + browser.loadURIWithFlags(aURIs[0], { + flags, postData: aPostDatas[0] + }); } catch (e) { // Ignore failure in case a URI is wrong, so we can continue // opening the next ones. } + } else { + firstTabAdded = this.addTab(aURIs[0], { + ownerTab: owner, + skipAnimation: multiple, + allowThirdPartyFixup: aAllowThirdPartyFixup, + postData: aPostDatas[0], + userContextId: aUserContextId + }); + if (aNewIndex !== -1) { + this.moveTabTo(firstTabAdded, aNewIndex); + targetTabIndex = firstTabAdded._tPos; + } } - else - firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple}); - var tabNum = this.tabContainer.selectedIndex; + let tabNum = targetTabIndex; for (let i = 1; i < aURIs.length; ++i) { - let tab = this.addTab(aURIs[i], {skipAnimation: true}); - if (aReplace) + let tab = this.addTab(aURIs[i], { + skipAnimation: true, + allowThirdPartyFixup: aAllowThirdPartyFixup, + postData: aPostDatas[i], + userContextId: aUserContextId + }); + if (targetTabIndex !== -1) this.moveTabTo(tab, ++tabNum); } -- cgit v1.2.3 From 60d29fb2861768032b831b77541e06de03b6ded2 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:43:52 +0200 Subject: Bug 92737 - Part 4: Open multiple tabs when multiple items are dropped on tab + Follow up: Bug 92737 - Part 3: Open multiple tabs when multiple items are dropped on remote content area - browser.js: "usercontextid" (default: 0) --- application/palemoon/base/content/browser.js | 3 +- application/palemoon/base/content/tabbrowser.xml | 43 +++++++++++------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 1d1fd73ae..e05eca986 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -5125,7 +5125,8 @@ function handleDroppedLink(event, urlOrLinks, name) let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; - let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid"); + let userContextId = gBrowser.selectedBrowser + .getAttribute("usercontextid") || 0; let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); if (event.shiftKey) diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index 0d9c29395..69d824fd5 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -4503,40 +4503,35 @@ this.tabbrowser.updateCurrentBrowser(true); } else { // Pass true to disallow dropping javascript: or data: urls - let url; + let links; try { - url = browserDragAndDrop.drop(event, { }, true); + links = browserDragAndDrop.dropLinks(event, true); } catch (ex) {} // // valid urls don't contain spaces ' '; if we have a space it isn't a valid url. // if (!url || url.includes(" ")) //PMed - if (!url) //FF + if (!links || links.length === 0) //FF return; - let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); + let inBackground = Services.prefs.getBoolPref("browser.tabs.loadInBackground"); if (event.shiftKey) - bgLoad = !bgLoad; + inBackground = !inBackground; - let tab = this._getDragTargetTab(event); - if (!tab || dropEffect == "copy") { - // We're adding a new tab. - let newIndex = this._getDropIndex(event); - let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true}); - this.tabbrowser.moveTabTo(newTab, newIndex); - } else { - // Load in an existing tab. - try { - let webNav = Ci.nsIWebNavigation; - let flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - this.tabbrowser.getBrowserForTab(tab).loadURIWithFlags(url, flags); - if (!bgLoad) - this.selectedItem = tab; - } catch(ex) { - // Just ignore invalid urls - } - } + let targetTab = this._getDragTargetTab(event); + let userContextId = this.selectedItem + .getAttribute("usercontextid") || 0; + let replace = !(!tab || dropEffect == "copy"); + let newIndex = this._getDropIndex(event); + let urls = links.map(link => link.url); + this.tabbrowser.loadTabs(urls, { + inBackground, + replace, + allowThirdPartyFixup: true, + targetTab, + newIndex, + userContextId, + }); } if (draggedTab) { -- cgit v1.2.3 From d432689a50bc57be3b38e0b8ec8e1171bc26b2b2 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:46:16 +0200 Subject: Bug 92737 - Part 5: Set multiple homepage when multiple items are dropped on Home button Issue #121 --- application/palemoon/base/content/browser.js | 22 +++++++++++++++------- .../en-US/chrome/browser/browser.properties | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index e05eca986..efd26c2b9 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -2686,8 +2686,10 @@ var homeButtonObserver = { onDrop: function (aEvent) { // disallow setting home pages that inherit the principal - let url = browserDragAndDrop.drop(aEvent, {}, true); - setTimeout(openHomeDialog, 0, url); + let links = browserDragAndDrop.dropLinks(aEvent, true); + if (links.length) { + setTimeout(openHomeDialog, 0, links.map(link => link.url).join("|")); + } }, onDragOver: function (aEvent) @@ -2703,18 +2705,24 @@ var homeButtonObserver = { function openHomeDialog(aURL) { var promptTitle = gNavigatorBundle.getString("droponhometitle"); - var promptMsg = gNavigatorBundle.getString("droponhomemsg"); + var promptMsg; + if (aURL.includes("|")) { + promptMsg = gNavigatorBundle.getString("droponhomemsgMultiple"); + } else { + promptMsg = gNavigatorBundle.getString("droponhomemsg"); + } + var pressedVal = Services.prompt.confirmEx(window, promptTitle, promptMsg, Services.prompt.STD_YES_NO_BUTTONS, null, null, null, null, {value:0}); if (pressedVal == 0) { try { - var str = Components.classes["@mozilla.org/supports-string;1"] - .createInstance(Components.interfaces.nsISupportsString); - str.data = aURL; + var homepageStr = Components.classes["@mozilla.org/supports-string;1"] + .createInstance(Components.interfaces.nsISupportsString); + homepageStr.data = aURL; gPrefService.setComplexValue("browser.startup.homepage", - Components.interfaces.nsISupportsString, str); + Components.interfaces.nsISupportsString, homepageStr); } catch (ex) { dump("Failed to set the home page.\n"+ex+"\n"); } diff --git a/application/palemoon/locales/en-US/chrome/browser/browser.properties b/application/palemoon/locales/en-US/chrome/browser/browser.properties index 8b3fea4d5..5e08c3e50 100644 --- a/application/palemoon/locales/en-US/chrome/browser/browser.properties +++ b/application/palemoon/locales/en-US/chrome/browser/browser.properties @@ -7,6 +7,7 @@ openFile=Open File droponhometitle=Set Home Page droponhomemsg=Do you want this document to be your new home page? +droponhomemsgMultiple=Do you want these documents to be your new home pages? # context menu strings -- cgit v1.2.3 From d15edc6fd6d5f96a46793871d60487ba1dac10b2 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:47:06 +0200 Subject: Bug 92737 - Part 6: Open multiple tabs when multiple items are dropped on New Tab button Issue #121 --- application/palemoon/base/content/browser.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index efd26c2b9..9c8e16942 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -2770,11 +2770,14 @@ var newTabButtonObserver = { onDrop: function (aEvent) { - let url = browserDragAndDrop.drop(aEvent, { }); - getShortcutOrURIAndPostData(url).then(data => { - if (data.url) { - // allow third-party services to fixup this URL - openNewTabWith(data.url, null, data.postData, aEvent, true); + let links = browserDragAndDrop.dropLinks(aEvent); + Task.spawn(function*() { + for (let link of links) { + let data = yield getShortcutOrURIAndPostData(link.url); + if (data.url) { + // allow third-party services to fixup this URL + openNewTabWith(data.url, null, data.postData, aEvent, true); + } } }); } -- cgit v1.2.3 From c16c115ea719abdcddbe5106e126935c9f391be8 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:48:06 +0200 Subject: Bug 92737 - Part 7: Open multiple windows when multiple items are dropped on New Window button Issue #121 --- application/palemoon/base/content/browser.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 9c8e16942..3f294d82b 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -2793,11 +2793,14 @@ var newWindowButtonObserver = { }, onDrop: function (aEvent) { - let url = browserDragAndDrop.drop(aEvent, { }); - getShortcutOrURIAndPostData(url).then(data => { - if (data.url) { - // allow third-party services to fixup this URL - openNewWindowWith(data.url, null, data.postData, true); + let links = browserDragAndDrop.dropLinks(aEvent); + Task.spawn(function*() { + for (let link of links) { + let data = yield getShortcutOrURIAndPostData(link.url); + if (data.url) { + // allow third-party services to fixup this URL + openNewWindowWith(data.url, null, data.postData, true); + } } }); } -- cgit v1.2.3 From b15719c7f8c862b3898bd49930bb11f5202dc893 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:49:38 +0200 Subject: Bug 92737 - Part 8: Download multiple files when multiple items are dropped on Downloads button Issue #121 --- .../components/downloads/content/indicator.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/application/palemoon/components/downloads/content/indicator.js b/application/palemoon/components/downloads/content/indicator.js index e6a5bd012..1a2175a92 100644 --- a/application/palemoon/components/downloads/content/indicator.js +++ b/application/palemoon/components/downloads/content/indicator.js @@ -548,15 +548,18 @@ const DownloadsIndicatorView = { if (dt.mozGetDataAt("application/x-moz-file", 0)) return; - let name = {}; - let url = browserDragAndDrop.drop(aEvent, name); - if (url) { - if (url.startsWith("about:")) { - return; - } - - let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document; - saveURL(url, name.value, null, true, true, null, sourceDoc); + let links = browserDragAndDrop.dropLinks(aEvent); + if (!links.length) + return; + let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document; + let handled = false; + for (let link of links) { + if (link.url.startsWith("about:")) + continue; + saveURL(link.url, link.name, null, true, true, null, sourceDoc); + handled = true; + } + if (handled) { aEvent.preventDefault(); } }, -- cgit v1.2.3 From 02dffb57c8c330ae6d299141ae97ae23f433a927 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:52:31 +0200 Subject: Bug 92737 - Part 9: Download multiple files when multiple items are dropped on Downloads view in Library Window Issue #121 --- .../components/downloads/content/allDownloadsViewOverlay.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js index 46e867068..d9758cb09 100644 --- a/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js +++ b/application/palemoon/components/downloads/content/allDownloadsViewOverlay.js @@ -1594,10 +1594,14 @@ DownloadsPlacesView.prototype = { if (dt.mozGetDataAt("application/x-moz-file", 0)) return; - let name = { }; - let url = Services.droppedLinkHandler.dropLink(aEvent, name); - if (url) - DownloadURL(url, name.value); + let links = Services.droppedLinkHandler.dropLinks(aEvent); + if (!links.length) + return; + for (let link of links) { + if (link.url.startsWith("about:")) + continue; + DownloadURL(link.url, link.name); + } } }; -- cgit v1.2.3 From cebd1e72e28b58881fbcccfb48a43ce47a6b01a4 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 11:53:33 +0200 Subject: Bug 92737 - Part 10: Use browserDragAndDrop.dropLinks in urlbarBindings.xml Issue #121 --- application/palemoon/base/content/urlbarBindings.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/application/palemoon/base/content/urlbarBindings.xml b/application/palemoon/base/content/urlbarBindings.xml index e859fe804..bdb7a6a12 100644 --- a/application/palemoon/base/content/urlbarBindings.xml +++ b/application/palemoon/base/content/urlbarBindings.xml @@ -455,11 +455,12 @@ 0 && links[0].url) { + let url = links[0].url; aEvent.preventDefault(); this.value = url; SetPageProxyState("invalid"); -- cgit v1.2.3 From cfa5951ea85357e119f397524710320a8aa85e83 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 12:07:57 +0200 Subject: Maybe fix openLocation.js (to Promise) Issue #121 --- application/palemoon/base/content/openLocation.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/application/palemoon/base/content/openLocation.js b/application/palemoon/base/content/openLocation.js index b00dbc571..80d542954 100644 --- a/application/palemoon/base/content/openLocation.js +++ b/application/palemoon/base/content/openLocation.js @@ -62,13 +62,12 @@ function doEnabling() function open() { - Task.spawn(function() { + getShortcutOrURIAndPostData(dialog.input.value).then(data => { let url; let postData = null; let mayInheritPrincipal = false; if (browser) { - let data = yield browser.getShortcutOrURIAndPostData(dialog.input.value); url = data.url; postData = data.postData; mayInheritPrincipal = data.mayInheritPrincipal; -- cgit v1.2.3 From 1b4963fd734bbfb857593afaa103879d6c0e55eb Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 15 Apr 2018 12:51:04 +0200 Subject: Fix flags for "loadURIWithFlags" in openLocation.js Issue #121 --- application/palemoon/base/content/openLocation.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/palemoon/base/content/openLocation.js b/application/palemoon/base/content/openLocation.js index 80d542954..6987abdf8 100644 --- a/application/palemoon/base/content/openLocation.js +++ b/application/palemoon/base/content/openLocation.js @@ -81,7 +81,8 @@ function open() switch (dialog.openWhereList.value) { case "0": var webNav = Components.interfaces.nsIWebNavigation; - var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; + var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | + webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; if (!mayInheritPrincipal) flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData); -- cgit v1.2.3 From e3dda3ebd5658bcea920be3becc89a84194930f6 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Tue, 17 Apr 2018 08:19:14 +0200 Subject: [PALEMOON] Fix conflict in openLocation.js https://github.com/MoonchildProductions/UXP/commit/931950a880b3550490422b1855c509be10586858#diff-2f4cb31954d5857012f1452698b9bfce --- application/palemoon/base/content/openLocation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/palemoon/base/content/openLocation.js b/application/palemoon/base/content/openLocation.js index 6987abdf8..f6e6a2434 100644 --- a/application/palemoon/base/content/openLocation.js +++ b/application/palemoon/base/content/openLocation.js @@ -7,7 +7,7 @@ var browser; var dialog = {}; var pref = null; -let openLocationModule = {}; +var openLocationModule = {}; try { pref = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); @@ -17,7 +17,7 @@ try { Components.utils.import("resource:///modules/openLocationLastURL.jsm", openLocationModule); Components.utils.import("resource://gre/modules/Task.jsm"); -let gOpenLocationLastURL = new openLocationModule.OpenLocationLastURL(window.opener); +var gOpenLocationLastURL = new openLocationModule.OpenLocationLastURL(window.opener); function onLoad() { -- cgit v1.2.3 From 90c68b34abf51ae0b1a2848094fc3115b30ee498 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Tue, 17 Apr 2018 08:25:01 +0200 Subject: [PALEMOON] Remove unused Task.jsm in openLocation.js --- application/palemoon/base/content/openLocation.js | 1 - 1 file changed, 1 deletion(-) diff --git a/application/palemoon/base/content/openLocation.js b/application/palemoon/base/content/openLocation.js index f6e6a2434..1a10334c7 100644 --- a/application/palemoon/base/content/openLocation.js +++ b/application/palemoon/base/content/openLocation.js @@ -16,7 +16,6 @@ try { } Components.utils.import("resource:///modules/openLocationLastURL.jsm", openLocationModule); -Components.utils.import("resource://gre/modules/Task.jsm"); var gOpenLocationLastURL = new openLocationModule.OpenLocationLastURL(window.opener); function onLoad() -- cgit v1.2.3 From 4549256c2b685782587f2ccad6a105c0392492c7 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Fri, 20 Apr 2018 22:54:26 +0200 Subject: moebius#56: Fix: DataTransfer - Pasting image from clipboard fails in some cases https://github.com/MoonchildProductions/moebius/pull/56 --- .../test/browser_toolbox_textbox_context_menu.js | 9 +- .../browser_computed_search-filter_context-menu.js | 9 +- .../browser_rules_search-filter_context-menu.js | 9 +- ...browser_inspector_search-filter_context-menu.js | 7 +- editor/libeditor/HTMLEditorDataTransfer.cpp | 7 ++ editor/libeditor/TextEditorDataTransfer.cpp | 7 ++ editor/libeditor/tests/chrome.ini | 1 + editor/libeditor/tests/mochitest.ini | 2 + editor/libeditor/tests/test_pasteImgTextarea.html | 20 +++++ editor/libeditor/tests/test_pasteImgTextarea.xul | 27 ++++++ widget/windows/nsClipboard.cpp | 2 +- widget/windows/nsDataObj.cpp | 99 +++++++++++++++++----- widget/windows/nsDataObj.h | 1 - 13 files changed, 156 insertions(+), 44 deletions(-) create mode 100644 editor/libeditor/tests/test_pasteImgTextarea.html create mode 100644 editor/libeditor/tests/test_pasteImgTextarea.xul diff --git a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js index 2e5f3210e..e2e961255 100644 --- a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js +++ b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js @@ -36,15 +36,12 @@ add_task(function* () { is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled"); is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); - // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // Cut/Copy/Paste items are enabled in context menu even if there + // is no selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); yield cleanup(toolbox); }); diff --git a/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js b/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js index b5dbe4475..b04a247f5 100644 --- a/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js +++ b/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js @@ -45,15 +45,12 @@ add_task(function* () { is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled"); is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); - // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // Cut/Copy/Paste items are enabled in context menu even if there is no + // selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); info("Closing context menu"); let onContextMenuHidden = once(searchContextMenu, "popuphidden"); diff --git a/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js b/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js index 349f1b9b3..d66df91ab 100644 --- a/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js +++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js @@ -44,15 +44,12 @@ add_task(function* () { is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled"); is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); - // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // Cut/Copy/Paste items are enabled in context menu even if there is no + // selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); info("Closing context menu"); let onContextMenuHidden = once(searchContextMenu, "popuphidden"); diff --git a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js index 137456468..7bd4b5e6f 100644 --- a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js +++ b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js @@ -43,14 +43,11 @@ add_task(function* () { is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled"); // Cut/Copy items are enabled in context menu even if there - // is no selection. See also Bug 1303033 + // is no selection. See also Bug 1303033, and 1317322 is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled"); is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled"); - if (isWindows()) { - // emptyClipboard only works on Windows (666254), assert paste only for this OS. - is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled"); - } + is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled"); info("Closing context menu"); let onContextMenuHidden = once(searchContextMenu, "popuphidden"); diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp index ed350c0dd..c56fbead7 100644 --- a/editor/libeditor/HTMLEditorDataTransfer.cpp +++ b/editor/libeditor/HTMLEditorDataTransfer.cpp @@ -1538,6 +1538,13 @@ HTMLEditor::CanPaste(int32_t aSelectionType, NS_ENSURE_ARG_POINTER(aCanPaste); *aCanPaste = false; + // Always enable the paste command when inside of a HTML or XHTML document. + nsCOMPtr doc = GetDocument(); + if (doc && doc->IsHTMLOrXHTML()) { + *aCanPaste = true; + return NS_OK; + } + // can't paste if readonly if (!IsModifiable()) { return NS_OK; diff --git a/editor/libeditor/TextEditorDataTransfer.cpp b/editor/libeditor/TextEditorDataTransfer.cpp index 0388aa4a8..2cc2906fa 100644 --- a/editor/libeditor/TextEditorDataTransfer.cpp +++ b/editor/libeditor/TextEditorDataTransfer.cpp @@ -383,6 +383,13 @@ TextEditor::CanPaste(int32_t aSelectionType, NS_ENSURE_ARG_POINTER(aCanPaste); *aCanPaste = false; + // Always enable the paste command when inside of a HTML or XHTML document. + nsCOMPtr doc = GetDocument(); + if (doc && doc->IsHTMLOrXHTML()) { + *aCanPaste = true; + return NS_OK; + } + // can't paste if readonly if (!IsModifiable()) { return NS_OK; diff --git a/editor/libeditor/tests/chrome.ini b/editor/libeditor/tests/chrome.ini index 98db30001..dd13370a5 100644 --- a/editor/libeditor/tests/chrome.ini +++ b/editor/libeditor/tests/chrome.ini @@ -12,3 +12,4 @@ support-files = green.png [test_set_document_title_transaction.html] [test_texteditor_keyevent_handling.html] skip-if = (debug && os=='win') || (os == 'linux') # Bug 1116205, leaks on windows debug, fails delete key on linux +[test_pasteImgTextarea.xul] diff --git a/editor/libeditor/tests/mochitest.ini b/editor/libeditor/tests/mochitest.ini index 4df3f606b..33b164819 100644 --- a/editor/libeditor/tests/mochitest.ini +++ b/editor/libeditor/tests/mochitest.ini @@ -247,3 +247,5 @@ skip-if = toolkit == 'android' [test_css_chrome_load_access.html] skip-if = toolkit == 'android' # chrome urls not available due to packaging [test_selection_move_commands.html] +[test_pasteImgTextarea.html] +skip-if = toolkit == 'android' # bug 1299578 diff --git a/editor/libeditor/tests/test_pasteImgTextarea.html b/editor/libeditor/tests/test_pasteImgTextarea.html new file mode 100644 index 000000000..3168ae729 --- /dev/null +++ b/editor/libeditor/tests/test_pasteImgTextarea.html @@ -0,0 +1,20 @@ + + + + + + + diff --git a/editor/libeditor/tests/test_pasteImgTextarea.xul b/editor/libeditor/tests/test_pasteImgTextarea.xul new file mode 100644 index 000000000..545027aa3 --- /dev/null +++ b/editor/libeditor/tests/test_pasteImgTextarea.xul @@ -0,0 +1,27 @@ + + + + + + + + + + + + + diff --git a/widget/windows/nsClipboard.cpp b/widget/windows/nsClipboard.cpp index 1afee3496..0db1dd342 100644 --- a/widget/windows/nsClipboard.cpp +++ b/widget/windows/nsClipboard.cpp @@ -65,7 +65,7 @@ nsClipboard::nsClipboard() : nsBaseClipboard() nsCOMPtr observerService = do_GetService("@mozilla.org/observer-service;1"); if (observerService) - observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE); + observerService->AddObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, PR_FALSE); } //------------------------------------------------------------------------- diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp index 02ec3b2fe..977a87c08 100644 --- a/widget/windows/nsDataObj.cpp +++ b/widget/windows/nsDataObj.cpp @@ -443,6 +443,82 @@ STDMETHODIMP_(ULONG) nsDataObj::AddRef() return m_cRef; } +namespace { +class RemoveTempFileHelper : public nsIObserver +{ +public: + explicit RemoveTempFileHelper(nsIFile* aTempFile) + : mTempFile(aTempFile) + { + MOZ_ASSERT(mTempFile); + } + + // The attach method is seperate from the constructor as we may be addref-ing + // ourself, and we want to be sure someone has a strong reference to us. + void Attach() + { + // We need to listen to both the xpcom shutdown message and our timer, and + // fire when the first of either of these two messages is received. + nsresult rv; + mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + mTimer->Init(this, 500, nsITimer::TYPE_ONE_SHOT); + + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1"); + if (NS_WARN_IF(!observerService)) { + mTimer->Cancel(); + mTimer = nullptr; + return; + } + observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + +private: + ~RemoveTempFileHelper() + { + if (mTempFile) { + mTempFile->Remove(false); + } + } + + nsCOMPtr mTempFile; + nsCOMPtr mTimer; +}; + +NS_IMPL_ISUPPORTS(RemoveTempFileHelper, nsIObserver); + +NS_IMETHODIMP +RemoveTempFileHelper::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) +{ + // Let's be careful and make sure that we don't die immediately + RefPtr grip = this; + + // Make sure that we aren't called again by destroying references to ourself. + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1"); + if (observerService) { + observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + } + + if (mTimer) { + mTimer->Cancel(); + mTimer = nullptr; + } + + // Remove the tempfile + if (mTempFile) { + mTempFile->Remove(false); + mTempFile = nullptr; + } + return NS_OK; +} +} // namespace //----------------------------------------------------- STDMETHODIMP_(ULONG) nsDataObj::Release() @@ -456,17 +532,12 @@ STDMETHODIMP_(ULONG) nsDataObj::Release() // We have released our last ref on this object and need to delete the // temp file. External app acting as drop target may still need to open the // temp file. Addref a timer so it can delay deleting file and destroying - // this object. Delete file anyway and destroy this obj if there's a problem. + // this object. if (mCachedTempFile) { - nsresult rv; - mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv)) { - mTimer->InitWithFuncCallback(nsDataObj::RemoveTempFile, this, - 500, nsITimer::TYPE_ONE_SHOT); - return AddRef(); - } - mCachedTempFile->Remove(false); + RefPtr helper = + new RemoveTempFileHelper(mCachedTempFile); mCachedTempFile = nullptr; + helper->Attach(); } delete this; @@ -2153,13 +2224,3 @@ HRESULT nsDataObj::GetFileContents_IStream(FORMATETC& aFE, STGMEDIUM& aSTG) return S_OK; } - -void nsDataObj::RemoveTempFile(nsITimer* aTimer, void* aClosure) -{ - nsDataObj *timedDataObj = static_cast(aClosure); - if (timedDataObj->mCachedTempFile) { - timedDataObj->mCachedTempFile->Remove(false); - timedDataObj->mCachedTempFile = nullptr; - } - timedDataObj->Release(); -} diff --git a/widget/windows/nsDataObj.h b/widget/windows/nsDataObj.h index 2d7fb75ee..61f209e85 100644 --- a/widget/windows/nsDataObj.h +++ b/widget/windows/nsDataObj.h @@ -289,7 +289,6 @@ protected: bool LookupArbitraryFormat(FORMATETC *aFormat, LPDATAENTRY *aDataEntry, BOOL aAddorUpdate); bool CopyMediumData(STGMEDIUM *aMediumDst, STGMEDIUM *aMediumSrc, LPFORMATETC aFormat, BOOL aSetData); - static void RemoveTempFile(nsITimer* aTimer, void* aClosure); }; -- cgit v1.2.3 From d0024630326af8a6dbe40f5974d72d0746cf87a1 Mon Sep 17 00:00:00 2001 From: JustOff Date: Sun, 22 Apr 2018 00:43:24 +0300 Subject: [PMkit] Mark 'sdk/panel' as compatible with Pale Moon --- toolkit/jetpack/sdk/panel.js | 1 + 1 file changed, 1 insertion(+) diff --git a/toolkit/jetpack/sdk/panel.js b/toolkit/jetpack/sdk/panel.js index 4b625799d..34cde2edd 100644 --- a/toolkit/jetpack/sdk/panel.js +++ b/toolkit/jetpack/sdk/panel.js @@ -8,6 +8,7 @@ module.metadata = { "stability": "stable", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } -- cgit v1.2.3 From 54db9d2005c9e0450c902805c7a94fbda12f46cb Mon Sep 17 00:00:00 2001 From: JustOff Date: Sun, 22 Apr 2018 00:44:42 +0300 Subject: [PMkit] Fix the shim for 'sdk/ui/button' --- toolkit/jetpack/sdk/ui/button/view.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/toolkit/jetpack/sdk/ui/button/view.js b/toolkit/jetpack/sdk/ui/button/view.js index 552aab2f7..dcc3be59d 100644 --- a/toolkit/jetpack/sdk/ui/button/view.js +++ b/toolkit/jetpack/sdk/ui/button/view.js @@ -141,11 +141,11 @@ function create(options) { CustomizableUI.createWidget({ #endif id: id, + type: 'custom', #ifdef MC_PALEMOON onBuild: function(document, _id) { #else - type: 'custom', removable: true, defaultArea: AREA_NAVBAR, allowedAreas: [ AREA_PANEL, AREA_NAVBAR ], @@ -167,9 +167,7 @@ function create(options) { node.setAttribute('id', this.id); #endif node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional badged-button'); -#ifndef MC_PALEMOON node.setAttribute('type', type); -#endif node.setAttribute('label', label); node.setAttribute('tooltiptext', label); node.setAttribute('image', image); -- cgit v1.2.3 From 766ad26871b23d1135643086aaf064f39d9cc3a7 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 02:28:42 +0200 Subject: [PALEMOON] [frontend vs backend] Use "devtools-browser.css" instead of "global/skin/devtools/common.css" (does not exist) in browser.xul Issue #121 --- application/palemoon/base/content/browser.xul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/palemoon/base/content/browser.xul b/application/palemoon/base/content/browser.xul index 11c4f16f9..c2553f295 100644 --- a/application/palemoon/base/content/browser.xul +++ b/application/palemoon/base/content/browser.xul @@ -13,7 +13,7 @@ #ifdef MOZ_DEVTOOLS - + #endif -- cgit v1.2.3 From 9e45391482dcbbc45414142bf38d326522a03450 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 02:31:00 +0200 Subject: Use preprocessor for "chrome://devtools/skin/devtools-browser.css" in browser.xul --- browser/base/content/browser.xul | 2 ++ 1 file changed, 2 insertions(+) diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 5879f2a29..485471ee3 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -9,7 +9,9 @@ +#ifdef MOZ_DEVTOOLS +#endif -- cgit v1.2.3 From 752af49b6e86d2d557f4aed740367a94b3c53fc0 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 02:34:33 +0200 Subject: [DevTools] Fix warnings: "Property contained reference to invalid variable" Issue #121 --- devtools/client/webconsole/webconsole.xul | 2 ++ 1 file changed, 2 insertions(+) diff --git a/devtools/client/webconsole/webconsole.xul b/devtools/client/webconsole/webconsole.xul index cd3e44d82..1310fb57d 100644 --- a/devtools/client/webconsole/webconsole.xul +++ b/devtools/client/webconsole/webconsole.xul @@ -7,6 +7,8 @@ %webConsoleDTD; ]> + Date: Sun, 22 Apr 2018 11:16:08 -0400 Subject: Fix for loops in AddonRepository_SQLiteMigrator.jsm (SyntaxError: missing ] after element list) --- .../mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm b/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm index 11944ddf5..66147b9aa 100644 --- a/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm +++ b/toolkit/mozapps/extensions/internal/AddonRepository_SQLiteMigrator.jsm @@ -60,7 +60,11 @@ this.AddonRepository_SQLiteMigrator = { this._retrieveStoredData((results) => { this._closeConnection(); - let resultArray = [addon for ([,addon] of Iterator(results))]; + // Tycho: let resultArray = [addon for ([,addon] of Iterator(results))]; + let resultArray = []; + for (let [,addon] of Iterator(results)) { + resultArray.push(addon); + } logger.debug(resultArray.length + " addons imported.") aCallback(resultArray); }); -- cgit v1.2.3 From 1b4c4256ee7705724b02919b4d432b2a391bcd04 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 18:51:38 +0200 Subject: moebius#223: Consider blocking top level window data: URIs (part 1/3 without tests) https://github.com/MoonchildProductions/moebius/pull/223 --- docshell/base/nsDocShell.cpp | 16 +++- docshell/base/nsDocShell.h | 1 + .../en-US/chrome/security/security.properties | 3 + dom/security/nsContentSecurityManager.cpp | 84 ++++++++++++++++++++ dom/security/nsContentSecurityManager.h | 5 ++ dom/security/test/general/browser.ini | 5 ++ .../browser_test_toplevel_data_navigations.js | 54 +++++++++++++ .../file_block_toplevel_data_navigation.html | 14 ++++ .../file_block_toplevel_data_navigation2.html | 29 +++++++ .../file_block_toplevel_data_navigation3.html | 13 ++++ .../general/file_block_toplevel_data_redirect.sjs | 14 ++++ .../general/file_toplevel_data_meta_redirect.html | 10 +++ .../general/file_toplevel_data_navigations.sjs | 14 ++++ dom/security/test/general/mochitest.ini | 12 +++ .../test/general/test_allow_opening_data_json.html | 39 ++++++++++ .../test/general/test_allow_opening_data_pdf.html | 41 ++++++++++ .../test_block_toplevel_data_img_navigation.html | 51 ++++++++++++ .../test_block_toplevel_data_navigation.html | 90 ++++++++++++++++++++++ dom/security/test/moz.build | 1 + modules/libpref/init/all.js | 6 ++ netwerk/base/nsIOService.cpp | 10 +++ netwerk/base/nsIOService.h | 4 + 22 files changed, 515 insertions(+), 1 deletion(-) create mode 100644 dom/security/test/general/browser.ini create mode 100644 dom/security/test/general/browser_test_toplevel_data_navigations.js create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation.html create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation2.html create mode 100644 dom/security/test/general/file_block_toplevel_data_navigation3.html create mode 100644 dom/security/test/general/file_block_toplevel_data_redirect.sjs create mode 100644 dom/security/test/general/file_toplevel_data_meta_redirect.html create mode 100644 dom/security/test/general/file_toplevel_data_navigations.sjs create mode 100644 dom/security/test/general/test_allow_opening_data_json.html create mode 100644 dom/security/test/general/test_allow_opening_data_pdf.html create mode 100644 dom/security/test/general/test_block_toplevel_data_img_navigation.html create mode 100644 dom/security/test/general/test_block_toplevel_data_navigation.html diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 58c182cbb..ae97a7c9e 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -42,6 +42,7 @@ #include "nsArray.h" #include "nsArrayUtils.h" +#include "nsContentSecurityManager.h" #include "nsICaptivePortalService.h" #include "nsIDOMStorage.h" #include "nsIContentViewer.h" @@ -9884,6 +9885,15 @@ nsDocShell::InternalLoad(nsIURI* aURI, contentType = nsIContentPolicy::TYPE_DOCUMENT; } + if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI( + aURI, + contentType, + aTriggeringPrincipal, + (aLoadType == LOAD_NORMAL_EXTERNAL))) { + // logging to console happens within AllowTopLevelNavigationToDataURI + return NS_OK; + } + // If there's no targetDocShell, that means we are about to create a new window, // perform a content policy check before creating the window. if (!targetDocShell) { @@ -10232,8 +10242,11 @@ nsDocShell::InternalLoad(nsIURI* aURI, } } + bool loadFromExternal = false; + // Before going any further vet loads initiated by external programs. if (aLoadType == LOAD_NORMAL_EXTERNAL) { + loadFromExternal = true; // Disallow external chrome: loads targetted at content windows bool isChrome = false; if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) { @@ -10724,7 +10737,7 @@ nsDocShell::InternalLoad(nsIURI* aURI, nsINetworkPredictor::PREDICT_LOAD, this, nullptr); nsCOMPtr req; - rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, aReferrer, + rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, loadFromExternal, aReferrer, !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER), aReferrerPolicy, aTriggeringPrincipal, principalToInherit, aTypeHint, @@ -10804,6 +10817,7 @@ nsresult nsDocShell::DoURILoad(nsIURI* aURI, nsIURI* aOriginalURI, bool aLoadReplace, + bool aLoadFromExternal, nsIURI* aReferrerURI, bool aSendReferrer, uint32_t aReferrerPolicy, diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 3ca9e0b34..549d7f540 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -369,6 +369,7 @@ protected: nsresult DoURILoad(nsIURI* aURI, nsIURI* aOriginalURI, bool aLoadReplace, + bool aLoadFromExternal, nsIURI* aReferrer, bool aSendReferrer, uint32_t aReferrerPolicy, diff --git a/dom/locales/en-US/chrome/security/security.properties b/dom/locales/en-US/chrome/security/security.properties index 8b66cc265..c0b80996c 100644 --- a/dom/locales/en-US/chrome/security/security.properties +++ b/dom/locales/en-US/chrome/security/security.properties @@ -81,3 +81,6 @@ MimeTypeMismatch=The resource from “%1$S” was blocked due to MIME type misma XCTOHeaderValueMissing=X-Content-Type-Options header warning: value was “%1$S”; did you mean to send “nosniff”? BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a disallowed MIME type. + +# LOCALIZATION NOTE: Do not translate "data: URI". +BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”) diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index c4e1ed8e1..069e7d6a7 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -1,13 +1,16 @@ #include "nsContentSecurityManager.h" +#include "nsEscape.h" #include "nsIChannel.h" #include "nsIHttpChannelInternal.h" #include "nsIStreamListener.h" #include "nsILoadInfo.h" +#include "nsIOService.h" #include "nsContentUtils.h" #include "nsCORSListenerProxy.h" #include "nsIStreamListener.h" #include "nsIDocument.h" #include "nsMixedContentBlocker.h" +#include "nsNullPrincipal.h" #include "mozilla/dom/Element.h" @@ -15,6 +18,66 @@ NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager, nsIChannelEventSink) +/* static */ bool +nsContentSecurityManager::AllowTopLevelNavigationToDataURI( + nsIURI* aURI, + nsContentPolicyType aContentPolicyType, + nsIPrincipal* aTriggeringPrincipal, + bool aLoadFromExternal) +{ + // Let's block all toplevel document navigations to a data: URI. + // In all cases where the toplevel document is navigated to a + // data: URI the triggeringPrincipal is a codeBasePrincipal, or + // a NullPrincipal. In other cases, e.g. typing a data: URL into + // the URL-Bar, the triggeringPrincipal is a SystemPrincipal; + // we don't want to block those loads. Only exception, loads coming + // from an external applicaton (e.g. Thunderbird) don't load + // using a codeBasePrincipal, but we want to block those loads. + if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) { + return true; + } + if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) { + return true; + } + bool isDataURI = + (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI); + if (!isDataURI) { + return true; + } + // Whitelist data: images as long as they are not SVGs + nsAutoCString filePath; + aURI->GetFilePath(filePath); + if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) && + !StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) { + return true; + } + // Whitelist data: PDFs and JSON + if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/pdf")) || + StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) { + return true; + } + if (!aLoadFromExternal && + nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) { + return true; + } + nsAutoCString dataSpec; + aURI->GetSpec(dataSpec); + if (dataSpec.Length() > 50) { + dataSpec.Truncate(50); + dataSpec.AppendLiteral("..."); + } + NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec)); + const char16_t* params[] = { specUTF16.get() }; + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("DATA_URI_BLOCKED"), + // no doc available, log to browser console + nullptr, + nsContentUtils::eSECURITY_PROPERTIES, + "BlockTopLevelDataURINavigation", + params, ArrayLength(params)); + return false; +} + static nsresult ValidateSecurityFlags(nsILoadInfo* aLoadInfo) { @@ -478,6 +541,27 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel, } } + // Redirecting to a toplevel data: URI is not allowed, hence we pass + // a NullPrincipal as the TriggeringPrincipal to + // AllowTopLevelNavigationToDataURI() which definitely blocks any + // data: URI load. + nsCOMPtr newLoadInfo = aNewChannel->GetLoadInfo(); + if (newLoadInfo) { + nsCOMPtr uri; + nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr nullTriggeringPrincipal = nsNullPrincipal::Create(); + if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI( + uri, + newLoadInfo->GetExternalContentPolicyType(), + nullTriggeringPrincipal, + false)) { + // logging to console happens within AllowTopLevelNavigationToDataURI + aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI); + return NS_ERROR_DOM_BAD_URI; + } + } + // Also verify that the redirecting server is allowed to redirect to the // given URI nsCOMPtr oldPrincipal; diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index 912c0e89f..09b6c86aa 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -32,6 +32,11 @@ public: static nsresult doContentSecurityCheck(nsIChannel* aChannel, nsCOMPtr& aInAndOutListener); + static bool AllowTopLevelNavigationToDataURI(nsIURI* aURI, + nsContentPolicyType aContentPolicyType, + nsIPrincipal* aTriggeringPrincipal, + bool aLoadFromExternal); + private: static nsresult CheckChannel(nsIChannel* aChannel); diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini new file mode 100644 index 000000000..97ddae3bf --- /dev/null +++ b/dom/security/test/general/browser.ini @@ -0,0 +1,5 @@ +[DEFAULT] +[browser_test_toplevel_data_navigations.js] +support-files = + file_toplevel_data_navigations.sjs + file_toplevel_data_meta_redirect.html diff --git a/dom/security/test/general/browser_test_toplevel_data_navigations.js b/dom/security/test/general/browser_test_toplevel_data_navigations.js new file mode 100644 index 000000000..a13a6350e --- /dev/null +++ b/dom/security/test/general/browser_test_toplevel_data_navigations.js @@ -0,0 +1,54 @@ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ + +"use strict"; + +const kDataBody = "toplevel navigation to data: URI allowed"; +const kDataURI = "data:text/html," + kDataBody + ""; +const kTestPath = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content", "http://example.com") +const kRedirectURI = kTestPath + "file_toplevel_data_navigations.sjs"; +const kMetaRedirectURI = kTestPath + "file_toplevel_data_meta_redirect.html"; + +add_task(async function test_nav_data_uri() { + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]], + }); + await BrowserTestUtils.withNewTab(kDataURI, async function(browser) { + await ContentTask.spawn(gBrowser.selectedBrowser, {kDataBody}, async function({kDataBody}) { // eslint-disable-line + is(content.document.body.innerHTML, kDataBody, + "data: URI navigation from system should be allowed"); + }); + }); +}); + +add_task(async function test_nav_data_uri_redirect() { + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]], + }); + let tab = BrowserTestUtils.addTab(gBrowser, kRedirectURI); + registerCleanupFunction(async function() { + await BrowserTestUtils.removeTab(tab); + }); + // wait to make sure data: URI did not load before checking that it got blocked + await new Promise(resolve => setTimeout(resolve, 500)); + await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { + is(content.document.body.innerHTML, "", + "data: URI navigation after server redirect should be blocked"); + }); +}); + +add_task(async function test_nav_data_uri_meta_redirect() { + await SpecialPowers.pushPrefEnv({ + "set": [["security.data_uri.block_toplevel_data_uri_navigations", true]], + }); + let tab = BrowserTestUtils.addTab(gBrowser, kMetaRedirectURI); + registerCleanupFunction(async function() { + await BrowserTestUtils.removeTab(tab); + }); + // wait to make sure data: URI did not load before checking that it got blocked + await new Promise(resolve => setTimeout(resolve, 500)); + await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() { + is(content.document.body.innerHTML, "", + "data: URI navigation after meta redirect should be blocked"); + }); +}); diff --git a/dom/security/test/general/file_block_toplevel_data_navigation.html b/dom/security/test/general/file_block_toplevel_data_navigation.html new file mode 100644 index 000000000..5fbfdfdef --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_navigation.html @@ -0,0 +1,14 @@ + + + + + Toplevel data navigation + + +test1: clicking data: URI tries to navigate window
+click me + + + diff --git a/dom/security/test/general/file_block_toplevel_data_navigation2.html b/dom/security/test/general/file_block_toplevel_data_navigation2.html new file mode 100644 index 000000000..e0308e1ae --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_navigation2.html @@ -0,0 +1,29 @@ + + + + + Toplevel data navigation + + +test2: data: URI in iframe tries to window.open(data:, _blank);
+ + + + diff --git a/dom/security/test/general/file_block_toplevel_data_navigation3.html b/dom/security/test/general/file_block_toplevel_data_navigation3.html new file mode 100644 index 000000000..34aeddab3 --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_navigation3.html @@ -0,0 +1,13 @@ + + + + + Toplevel data navigation + + +test3: performing data: URI navigation through win.loc.href
+ + + diff --git a/dom/security/test/general/file_block_toplevel_data_redirect.sjs b/dom/security/test/general/file_block_toplevel_data_redirect.sjs new file mode 100644 index 000000000..64e294cab --- /dev/null +++ b/dom/security/test/general/file_block_toplevel_data_redirect.sjs @@ -0,0 +1,14 @@ +// Custom *.sjs file specifically for the needs of Bug: +// Bug 1394554 - Block toplevel data: URI navigations after redirect + +var DATA_URI = + "toplevel data: URI navigations after redirect should be blocked"; + +function handleRequest(request, response) +{ + // avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", "data:text/html," + escape(DATA_URI), false); +} diff --git a/dom/security/test/general/file_toplevel_data_meta_redirect.html b/dom/security/test/general/file_toplevel_data_meta_redirect.html new file mode 100644 index 000000000..f4f5deb52 --- /dev/null +++ b/dom/security/test/general/file_toplevel_data_meta_redirect.html @@ -0,0 +1,10 @@ + + + + + + +Meta Redirect to data: URI + + diff --git a/dom/security/test/general/file_toplevel_data_navigations.sjs b/dom/security/test/general/file_toplevel_data_navigations.sjs new file mode 100644 index 000000000..501b833e5 --- /dev/null +++ b/dom/security/test/general/file_toplevel_data_navigations.sjs @@ -0,0 +1,14 @@ +// Custom *.sjs file specifically for the needs of Bug: +// Bug 1394554 - Block toplevel data: URI navigations after redirect + +var DATA_URI = + "data:text/html,toplevel data: URI navigations after redirect should be blocked"; + +function handleRequest(request, response) +{ + // avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", DATA_URI, false); +} diff --git a/dom/security/test/general/mochitest.ini b/dom/security/test/general/mochitest.ini index 70c0c9fb6..f3bcca072 100644 --- a/dom/security/test/general/mochitest.ini +++ b/dom/security/test/general/mochitest.ini @@ -3,7 +3,19 @@ support-files = file_contentpolicytype_targeted_link_iframe.sjs file_nosniff_testserver.sjs file_block_script_wrong_mime_server.sjs + file_block_toplevel_data_navigation.html + file_block_toplevel_data_navigation2.html + file_block_toplevel_data_navigation3.html + file_block_toplevel_data_redirect.sjs [test_contentpolicytype_targeted_link_iframe.html] [test_nosniff.html] [test_block_script_wrong_mime.html] +[test_block_toplevel_data_navigation.html] +skip-if = toolkit == 'android' # intermittent failure +[test_block_toplevel_data_img_navigation.html] +skip-if = toolkit == 'android' # intermittent failure +[test_allow_opening_data_pdf.html] +skip-if = toolkit == 'android' +[test_allow_opening_data_json.html] +skip-if = toolkit == 'android' diff --git a/dom/security/test/general/test_allow_opening_data_json.html b/dom/security/test/general/test_allow_opening_data_json.html new file mode 100644 index 000000000..1530a24e8 --- /dev/null +++ b/dom/security/test/general/test_allow_opening_data_json.html @@ -0,0 +1,39 @@ + + + + + Bug 1403814: Allow toplevel data URI navigation data:application/json + + + + + + + diff --git a/dom/security/test/general/test_allow_opening_data_pdf.html b/dom/security/test/general/test_allow_opening_data_pdf.html new file mode 100644 index 000000000..6b51fe57b --- /dev/null +++ b/dom/security/test/general/test_allow_opening_data_pdf.html @@ -0,0 +1,41 @@ + + + + + Bug 1398692: Allow toplevel navigation to a data:application/pdf + + + + + + + diff --git a/dom/security/test/general/test_block_toplevel_data_img_navigation.html b/dom/security/test/general/test_block_toplevel_data_img_navigation.html new file mode 100644 index 000000000..2b8f62760 --- /dev/null +++ b/dom/security/test/general/test_block_toplevel_data_img_navigation.html @@ -0,0 +1,51 @@ + + + + + Bug 1396798: Do not block toplevel data: navigation to image (except svgs) + + + + + + + diff --git a/dom/security/test/general/test_block_toplevel_data_navigation.html b/dom/security/test/general/test_block_toplevel_data_navigation.html new file mode 100644 index 000000000..fc91f2ec0 --- /dev/null +++ b/dom/security/test/general/test_block_toplevel_data_navigation.html @@ -0,0 +1,90 @@ + + + + + Bug 1331351 - Block top level window data: URI navigations + + + + + + + + diff --git a/dom/security/test/moz.build b/dom/security/test/moz.build index ddb4e9b89..946959dee 100644 --- a/dom/security/test/moz.build +++ b/dom/security/test/moz.build @@ -27,5 +27,6 @@ MOCHITEST_CHROME_MANIFESTS += [ BROWSER_CHROME_MANIFESTS += [ 'contentverifier/browser.ini', 'csp/browser.ini', + 'general/browser.ini', 'hsts/browser.ini', ] diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 182de4a11..ccc59269b 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5564,6 +5564,12 @@ pref("security.mixed_content.use_hsts", true); // Approximately 1 week default cache for HSTS priming failures pref ("security.mixed_content.hsts_priming_cache_timeout", 10080); +// TODO: Bug 1380959: Block toplevel data: URI navigations +// If true, all toplevel data: URI navigations will be blocked. +// Please note that manually entering a data: URI in the +// URL-Bar will not be blocked when flipping this pref. +pref("security.data_uri.block_toplevel_data_uri_navigations", false); + // Disable Storage api in release builds. #ifdef NIGHTLY_BUILD pref("dom.storageManager.enabled", true); diff --git a/netwerk/base/nsIOService.cpp b/netwerk/base/nsIOService.cpp index 0da79c18a..8b7f31f99 100644 --- a/netwerk/base/nsIOService.cpp +++ b/netwerk/base/nsIOService.cpp @@ -173,6 +173,8 @@ uint32_t nsIOService::gDefaultSegmentCount = 24; bool nsIOService::sTelemetryEnabled = false; +bool nsIOService::sBlockToplevelDataUriNavigations = false; + //////////////////////////////////////////////////////////////////////////////// nsIOService::nsIOService() @@ -251,6 +253,8 @@ nsIOService::Init() NS_WARNING("failed to get observer service"); Preferences::AddBoolVarCache(&sTelemetryEnabled, "toolkit.telemetry.enabled", false); + Preferences::AddBoolVarCache(&sBlockToplevelDataUriNavigations, + "security.data_uri.block_toplevel_data_uri_navigations", false); Preferences::AddBoolVarCache(&mOfflineMirrorsConnectivity, OFFLINE_MIRRORS_CONNECTIVITY, true); gIOService = this; @@ -1876,5 +1880,11 @@ nsIOService::SpeculativeAnonymousConnect2(nsIURI *aURI, return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true); } +/*static*/ bool +nsIOService::BlockToplevelDataUriNavigations() +{ + return sBlockToplevelDataUriNavigations; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/base/nsIOService.h b/netwerk/base/nsIOService.h index 7ac23b791..e592c4d1c 100644 --- a/netwerk/base/nsIOService.h +++ b/netwerk/base/nsIOService.h @@ -95,6 +95,8 @@ public: bool IsLinkUp(); + static bool BlockToplevelDataUriNavigations(); + // Used to trigger a recheck of the captive portal status nsresult RecheckCaptivePortal(); private: @@ -176,6 +178,8 @@ private: static bool sTelemetryEnabled; + static bool sBlockToplevelDataUriNavigations; + // These timestamps are needed for collecting telemetry on PR_Connect, // PR_ConnectContinue and PR_Close blocking time. If we spend very long // time in any of these functions we want to know if and what network -- cgit v1.2.3 From f1e5578718ea8883438cfea06d3c55d25f5c0278 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 22 Apr 2018 19:03:22 +0200 Subject: moebius#226: Consider blocking top level window data: URIs (part 2/2 without tests) https://github.com/MoonchildProductions/moebius/pull/226 --- docshell/base/nsDSURIContentListener.cpp | 9 ++++ docshell/base/nsDocShell.cpp | 10 +--- dom/security/nsContentSecurityManager.cpp | 59 +++++++++------------- dom/security/nsContentSecurityManager.h | 5 +- dom/security/test/general/browser.ini | 6 +++ .../test/general/browser_test_data_download.js | 37 ++++++++++++++ .../test/general/browser_test_data_text_csv.js | 37 ++++++++++++++ dom/security/test/general/file_data_download.html | 14 +++++ dom/security/test/general/file_data_text_csv.html | 14 +++++ .../test_block_toplevel_data_img_navigation.html | 18 ++++--- .../test_block_toplevel_data_navigation.html | 16 +++--- ipc/glue/BackgroundUtils.cpp | 2 + netwerk/base/LoadInfo.cpp | 23 +++++++++ netwerk/base/LoadInfo.h | 2 + netwerk/base/nsILoadInfo.idl | 7 +++ netwerk/ipc/NeckoChannelParams.ipdlh | 1 + 16 files changed, 194 insertions(+), 66 deletions(-) create mode 100644 dom/security/test/general/browser_test_data_download.js create mode 100644 dom/security/test/general/browser_test_data_text_csv.js create mode 100644 dom/security/test/general/file_data_download.html create mode 100644 dom/security/test/general/file_data_text_csv.html diff --git a/docshell/base/nsDSURIContentListener.cpp b/docshell/base/nsDSURIContentListener.cpp index 93ce3cb26..ee6a4dd62 100644 --- a/docshell/base/nsDSURIContentListener.cpp +++ b/docshell/base/nsDSURIContentListener.cpp @@ -17,6 +17,7 @@ #include "nsIHttpChannel.h" #include "nsIScriptSecurityManager.h" #include "nsError.h" +#include "nsContentSecurityManager.h" #include "nsCharSeparatedTokenizer.h" #include "nsIConsoleService.h" #include "nsIScriptError.h" @@ -93,6 +94,14 @@ nsDSURIContentListener::DoContent(const nsACString& aContentType, if (aOpenedChannel) { aOpenedChannel->GetLoadFlags(&loadFlags); + + // block top-level data URI navigations if triggered by the web + if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(aOpenedChannel)) { + // logging to console happens within AllowTopLevelNavigationToDataURI + aRequest->Cancel(NS_ERROR_DOM_BAD_URI); + *aAbortProcess = true; + return NS_OK; + } } if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) { diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index ae97a7c9e..596bd5d84 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -9885,15 +9885,6 @@ nsDocShell::InternalLoad(nsIURI* aURI, contentType = nsIContentPolicy::TYPE_DOCUMENT; } - if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI( - aURI, - contentType, - aTriggeringPrincipal, - (aLoadType == LOAD_NORMAL_EXTERNAL))) { - // logging to console happens within AllowTopLevelNavigationToDataURI - return NS_OK; - } - // If there's no targetDocShell, that means we are about to create a new window, // perform a content policy check before creating the window. if (!targetDocShell) { @@ -10962,6 +10953,7 @@ nsDocShell::DoURILoad(nsIURI* aURI, if (aPrincipalToInherit) { loadInfo->SetPrincipalToInherit(aPrincipalToInherit); } + loadInfo->SetLoadTriggeredFromExternal(aLoadFromExternal); // We have to do this in case our OriginAttributes are different from the // OriginAttributes of the parent document. Or in case there isn't a diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 069e7d6a7..c987fed67 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -10,20 +10,16 @@ #include "nsIStreamListener.h" #include "nsIDocument.h" #include "nsMixedContentBlocker.h" -#include "nsNullPrincipal.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/TabChild.h" NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager, nsIChannelEventSink) /* static */ bool -nsContentSecurityManager::AllowTopLevelNavigationToDataURI( - nsIURI* aURI, - nsContentPolicyType aContentPolicyType, - nsIPrincipal* aTriggeringPrincipal, - bool aLoadFromExternal) +nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel) { // Let's block all toplevel document navigations to a data: URI. // In all cases where the toplevel document is navigated to a @@ -36,17 +32,24 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI( if (!mozilla::net::nsIOService::BlockToplevelDataUriNavigations()) { return true; } - if (aContentPolicyType != nsIContentPolicy::TYPE_DOCUMENT) { + nsCOMPtr loadInfo = aChannel->GetLoadInfo(); + if (!loadInfo) { + return true; + } + if (loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) { return true; } + nsCOMPtr uri; + nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, true); bool isDataURI = - (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI); + (NS_SUCCEEDED(uri->SchemeIs("data", &isDataURI)) && isDataURI); if (!isDataURI) { return true; } // Whitelist data: images as long as they are not SVGs nsAutoCString filePath; - aURI->GetFilePath(filePath); + uri->GetFilePath(filePath); if (StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/")) && !StringBeginsWith(filePath, NS_LITERAL_CSTRING("image/svg+xml"))) { return true; @@ -56,22 +59,29 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI( StringBeginsWith(filePath, NS_LITERAL_CSTRING("application/json"))) { return true; } - if (!aLoadFromExternal && - nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) { + // Redirecting to a toplevel data: URI is not allowed, hence we make + // sure the RedirectChain is empty. + if (!loadInfo->GetLoadTriggeredFromExternal() && + nsContentUtils::IsSystemPrincipal(loadInfo->TriggeringPrincipal()) && + loadInfo->RedirectChain().IsEmpty()) { return true; } nsAutoCString dataSpec; - aURI->GetSpec(dataSpec); + uri->GetSpec(dataSpec); if (dataSpec.Length() > 50) { dataSpec.Truncate(50); dataSpec.AppendLiteral("..."); } + nsCOMPtr tabChild = do_QueryInterface(loadInfo->ContextForTopLevelLoad()); + nsCOMPtr doc; + if (tabChild) { + doc = static_cast(tabChild.get())->GetDocument(); + } NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec)); const char16_t* params[] = { specUTF16.get() }; nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DATA_URI_BLOCKED"), - // no doc available, log to browser console - nullptr, + doc, nsContentUtils::eSECURITY_PROPERTIES, "BlockTopLevelDataURINavigation", params, ArrayLength(params)); @@ -541,27 +551,6 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel, } } - // Redirecting to a toplevel data: URI is not allowed, hence we pass - // a NullPrincipal as the TriggeringPrincipal to - // AllowTopLevelNavigationToDataURI() which definitely blocks any - // data: URI load. - nsCOMPtr newLoadInfo = aNewChannel->GetLoadInfo(); - if (newLoadInfo) { - nsCOMPtr uri; - nsresult rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr nullTriggeringPrincipal = nsNullPrincipal::Create(); - if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI( - uri, - newLoadInfo->GetExternalContentPolicyType(), - nullTriggeringPrincipal, - false)) { - // logging to console happens within AllowTopLevelNavigationToDataURI - aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI); - return NS_ERROR_DOM_BAD_URI; - } - } - // Also verify that the redirecting server is allowed to redirect to the // given URI nsCOMPtr oldPrincipal; diff --git a/dom/security/nsContentSecurityManager.h b/dom/security/nsContentSecurityManager.h index 09b6c86aa..bab847743 100644 --- a/dom/security/nsContentSecurityManager.h +++ b/dom/security/nsContentSecurityManager.h @@ -32,10 +32,7 @@ public: static nsresult doContentSecurityCheck(nsIChannel* aChannel, nsCOMPtr& aInAndOutListener); - static bool AllowTopLevelNavigationToDataURI(nsIURI* aURI, - nsContentPolicyType aContentPolicyType, - nsIPrincipal* aTriggeringPrincipal, - bool aLoadFromExternal); + static bool AllowTopLevelNavigationToDataURI(nsIChannel* aChannel); private: static nsresult CheckChannel(nsIChannel* aChannel); diff --git a/dom/security/test/general/browser.ini b/dom/security/test/general/browser.ini index 97ddae3bf..73ae72ddd 100644 --- a/dom/security/test/general/browser.ini +++ b/dom/security/test/general/browser.ini @@ -3,3 +3,9 @@ support-files = file_toplevel_data_navigations.sjs file_toplevel_data_meta_redirect.html +[browser_test_data_download.js] +support-files = + file_data_download.html +[browser_test_data_text_csv.js] +support-files = + file_data_text_csv.html diff --git a/dom/security/test/general/browser_test_data_download.js b/dom/security/test/general/browser_test_data_download.js new file mode 100644 index 000000000..1ee8d5844 --- /dev/null +++ b/dom/security/test/general/browser_test_data_download.js @@ -0,0 +1,37 @@ +"use strict"; + +const kTestPath = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content", "http://example.com") +const kTestURI = kTestPath + "file_data_download.html"; + +function addWindowListener(aURL, aCallback) { + Services.wm.addListener({ + onOpenWindow(aXULWindow) { + info("window opened, waiting for focus"); + Services.wm.removeListener(this); + var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + waitForFocus(function() { + is(domwindow.document.location.href, aURL, "should have seen the right window open"); + aCallback(domwindow); + }, domwindow); + }, + onCloseWindow(aXULWindow) { }, + onWindowTitleChange(aXULWindow, aNewTitle) { } + }); +} + +function test() { + waitForExplicitFinish(); + Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true); + registerCleanupFunction(function() { + Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations"); + }); + addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) { + is(win.document.getElementById("location").value, "data-foo.html", + "file name of download should match"); + win.close(); + finish(); + }); + gBrowser.loadURI(kTestURI); +} diff --git a/dom/security/test/general/browser_test_data_text_csv.js b/dom/security/test/general/browser_test_data_text_csv.js new file mode 100644 index 000000000..c45e40cc2 --- /dev/null +++ b/dom/security/test/general/browser_test_data_text_csv.js @@ -0,0 +1,37 @@ +"use strict"; + +const kTestPath = getRootDirectory(gTestPath) + .replace("chrome://mochitests/content", "http://example.com") +const kTestURI = kTestPath + "file_data_text_csv.html"; + +function addWindowListener(aURL, aCallback) { + Services.wm.addListener({ + onOpenWindow(aXULWindow) { + info("window opened, waiting for focus"); + Services.wm.removeListener(this); + var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + waitForFocus(function() { + is(domwindow.document.location.href, aURL, "should have seen the right window open"); + aCallback(domwindow); + }, domwindow); + }, + onCloseWindow(aXULWindow) { }, + onWindowTitleChange(aXULWindow, aNewTitle) { } + }); +} + +function test() { + waitForExplicitFinish(); + Services.prefs.setBoolPref("security.data_uri.block_toplevel_data_uri_navigations", true); + registerCleanupFunction(function() { + Services.prefs.clearUserPref("security.data_uri.block_toplevel_data_uri_navigations"); + }); + addWindowListener("chrome://mozapps/content/downloads/unknownContentType.xul", function(win) { + is(win.document.getElementById("location").value, "text/csv;foo,bar,foobar", + "file name of download should match"); + win.close(); + finish(); + }); + gBrowser.loadURI(kTestURI); +} diff --git a/dom/security/test/general/file_data_download.html b/dom/security/test/general/file_data_download.html new file mode 100644 index 000000000..4cc92fe8f --- /dev/null +++ b/dom/security/test/general/file_data_download.html @@ -0,0 +1,14 @@ + + + + Test download attribute for data: URI + + + download data + + + diff --git a/dom/security/test/general/file_data_text_csv.html b/dom/security/test/general/file_data_text_csv.html new file mode 100644 index 000000000..a9ac369d1 --- /dev/null +++ b/dom/security/test/general/file_data_text_csv.html @@ -0,0 +1,14 @@ + + + + Test open data:text/csv + + + test text/csv + + + diff --git a/dom/security/test/general/test_block_toplevel_data_img_navigation.html b/dom/security/test/general/test_block_toplevel_data_img_navigation.html index 2b8f62760..7f8dfc748 100644 --- a/dom/security/test/general/test_block_toplevel_data_img_navigation.html +++ b/dom/security/test/general/test_block_toplevel_data_img_navigation.html @@ -34,15 +34,17 @@ function test_toplevel_data_image_svg() { const DATA_SVG = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg=="; let win2 = window.open(DATA_SVG); - let wrappedWin2 = SpecialPowers.wrap(win2); - setTimeout(function () { - isnot(wrappedWin2.document.documentElement.localName, "svg", - "Loading data:image/svg+xml should be blocked"); - wrappedWin2.close(); - SimpleTest.finish(); - }, 1000); + // Unfortunately we can't detect whether the window was closed using some event, + // hence we are constantly polling till we see that win == null. + // Test times out on failure. + var win2Closed = setInterval(function() { + if (win2 == null || win2.closed) { + clearInterval(win2Closed); + ok(true, "Loading data:image/svg+xml should be blocked"); + SimpleTest.finish(); + } + }, 200); } - // fire up the tests test_toplevel_data_image(); diff --git a/dom/security/test/general/test_block_toplevel_data_navigation.html b/dom/security/test/general/test_block_toplevel_data_navigation.html index fc91f2ec0..cef232b65 100644 --- a/dom/security/test/general/test_block_toplevel_data_navigation.html +++ b/dom/security/test/general/test_block_toplevel_data_navigation.html @@ -21,16 +21,12 @@ function test1() { // simple data: URI click navigation should be prevented let TEST_FILE = "file_block_toplevel_data_navigation.html"; let win1 = window.open(TEST_FILE); - var readyStateCheckInterval = setInterval(function() { - let state = win1.document.readyState; - if (state === "interactive" || state === "complete") { - clearInterval(readyStateCheckInterval); - ok(win1.document.body.innerHTML.indexOf("test1:") !== -1, - "toplevel data: URI navigation through click() should be blocked"); - win1.close(); - test2(); - } - }, 200); + setTimeout(function () { + ok(SpecialPowers.wrap(win1).document.body.innerHTML.indexOf("test1:") !== -1, + "toplevel data: URI navigation through click() should be blocked"); + win1.close(); + test2(); + }, 1000); } function test2() { diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index b335f5c23..4cfbe8758 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -294,6 +294,7 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, aLoadInfo->CorsUnsafeHeaders(), aLoadInfo->GetForcePreflight(), aLoadInfo->GetIsPreflight(), + aLoadInfo->GetLoadTriggeredFromExternal(), aLoadInfo->GetForceHSTSPriming(), aLoadInfo->GetMixedContentWouldBlock()); @@ -370,6 +371,7 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, loadInfoArgs.corsUnsafeHeaders(), loadInfoArgs.forcePreflight(), loadInfoArgs.isPreflight(), + loadInfoArgs.loadTriggeredFromExternal(), loadInfoArgs.forceHSTSPriming(), loadInfoArgs.mixedContentWouldBlock() ); diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 42fdea4a1..2f10261cb 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -7,6 +7,7 @@ #include "mozilla/LoadInfo.h" #include "mozilla/Assertions.h" +#include "mozilla/dom/TabChild.h" #include "mozilla/dom/ToJSValue.h" #include "mozIThirdPartyUtil.h" #include "nsFrameLoader.h" @@ -63,6 +64,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mIsThirdPartyContext(false) , mForcePreflight(false) , mIsPreflight(false) + , mLoadTriggeredFromExternal(false) , mForceHSTSPriming(false) , mMixedContentWouldBlock(false) { @@ -235,6 +237,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, , mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party. , mForcePreflight(false) , mIsPreflight(false) + , mLoadTriggeredFromExternal(false) , mForceHSTSPriming(false) , mMixedContentWouldBlock(false) { @@ -297,6 +300,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) , mCorsUnsafeHeaders(rhs.mCorsUnsafeHeaders) , mForcePreflight(rhs.mForcePreflight) , mIsPreflight(rhs.mIsPreflight) + , mLoadTriggeredFromExternal(rhs.mLoadTriggeredFromExternal) , mForceHSTSPriming(rhs.mForceHSTSPriming) , mMixedContentWouldBlock(rhs.mMixedContentWouldBlock) { @@ -325,6 +329,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, const nsTArray& aCorsUnsafeHeaders, bool aForcePreflight, bool aIsPreflight, + bool aLoadTriggeredFromExternal, bool aForceHSTSPriming, bool aMixedContentWouldBlock) : mLoadingPrincipal(aLoadingPrincipal) @@ -348,6 +353,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mCorsUnsafeHeaders(aCorsUnsafeHeaders) , mForcePreflight(aForcePreflight) , mIsPreflight(aIsPreflight) + , mLoadTriggeredFromExternal(aLoadTriggeredFromExternal) , mForceHSTSPriming (aForceHSTSPriming) , mMixedContentWouldBlock(aMixedContentWouldBlock) { @@ -872,6 +878,23 @@ LoadInfo::GetIsPreflight(bool* aIsPreflight) return NS_OK; } +NS_IMETHODIMP +LoadInfo::SetLoadTriggeredFromExternal(bool aLoadTriggeredFromExternal) +{ + MOZ_ASSERT(!aLoadTriggeredFromExternal || + mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT, + "can only set load triggered from external for TYPE_DOCUMENT"); + mLoadTriggeredFromExternal = aLoadTriggeredFromExternal; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetLoadTriggeredFromExternal(bool* aLoadTriggeredFromExternal) +{ + *aLoadTriggeredFromExternal = mLoadTriggeredFromExternal; + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetForceHSTSPriming(bool* aForceHSTSPriming) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 3e1b92ff4..99deae2d2 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -108,6 +108,7 @@ private: const nsTArray& aUnsafeHeaders, bool aForcePreflight, bool aIsPreflight, + bool aLoadTriggeredFromExternal, bool aForceHSTSPriming, bool aMixedContentWouldBlock); LoadInfo(const LoadInfo& rhs); @@ -152,6 +153,7 @@ private: nsTArray mCorsUnsafeHeaders; bool mForcePreflight; bool mIsPreflight; + bool mLoadTriggeredFromExternal; bool mForceHSTSPriming : 1; bool mMixedContentWouldBlock : 1; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 78433c8b8..5b5eb425a 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -574,6 +574,13 @@ interface nsILoadInfo : nsISupports */ [infallible] attribute boolean initialSecurityCheckDone; + /** + * Returns true if the load was triggered from an external application + * (e.g. Thunderbird). Please note that this flag will only ever be true + * if the load is of TYPE_DOCUMENT. + */ + [infallible] attribute boolean loadTriggeredFromExternal; + /** * Whenever a channel gets redirected, append the principal of the * channel [before the channels got redirected] to the loadinfo, diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 9365397d1..e1438cacc 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -53,6 +53,7 @@ struct LoadInfoArgs nsCString[] corsUnsafeHeaders; bool forcePreflight; bool isPreflight; + bool loadTriggeredFromExternal; bool forceHSTSPriming; bool mixedContentWouldBlock; }; -- cgit v1.2.3 From 7ab45761af606c813f77c228f260807e46ccc16a Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 22 Apr 2018 13:08:18 +0200 Subject: Remove NPAPI deprecation statement from about:plugins. --- dom/locales/en-US/chrome/plugins.properties | 3 --- toolkit/content/plugins.html | 9 --------- 2 files changed, 12 deletions(-) diff --git a/dom/locales/en-US/chrome/plugins.properties b/dom/locales/en-US/chrome/plugins.properties index ee8d25c88..fe03be59e 100644 --- a/dom/locales/en-US/chrome/plugins.properties +++ b/dom/locales/en-US/chrome/plugins.properties @@ -21,9 +21,6 @@ description_label=Description suffixes_label=Suffixes learn_more_label=Learn More -deprecation_description=Missing something? Some plugins are no longer supported. -deprecation_learn_more=Learn More. - # GMP Plugins gmp_license_info=License information gmp_privacy_info=Privacy Information diff --git a/toolkit/content/plugins.html b/toolkit/content/plugins.html index d389f52dd..15bbed9bb 100644 --- a/toolkit/content/plugins.html +++ b/toolkit/content/plugins.html @@ -75,15 +75,6 @@ enabledplugins.appendChild(document.createTextNode(pluginsbundle.GetStringFromName(label))); fragment.appendChild(enabledplugins); - var deprecation = document.createElement("p"); - deprecation.setAttribute("class", "notice"); - deprecation.textContent = pluginsbundle.GetStringFromName("deprecation_description") + " \u00A0 "; - var deprecationLink = document.createElement("a"); - deprecationLink.textContent = pluginsbundle.GetStringFromName("deprecation_learn_more"); - deprecationLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "npapi"; - deprecation.appendChild(deprecationLink); - fragment.appendChild(deprecation); - var stateNames = {}; ["STATE_SOFTBLOCKED", "STATE_BLOCKED", -- cgit v1.2.3 From 420458002d54d85e042d83d7205b04062807cbdb Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 22 Apr 2018 13:16:44 +0200 Subject: Disable Mozilla health report service. --- browser/confvars.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/confvars.sh b/browser/confvars.sh index 03b4cea97..41c0be3d7 100755 --- a/browser/confvars.sh +++ b/browser/confvars.sh @@ -58,7 +58,7 @@ MOZ_WEBEXTENSIONS=1 MOZ_DEVTOOLS=1 MOZ_SERVICES_COMMON=1 MOZ_SERVICES_SYNC=1 -MOZ_SERVICES_HEALTHREPORT=1 +MOZ_SERVICES_HEALTHREPORT= # Disable checking that add-ons are signed by the trusted root MOZ_ADDON_SIGNING=0 -- cgit v1.2.3 From 3dbe5b2d7bd2e8728868c4c3f315de620c421d32 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 22 Apr 2018 13:19:49 +0200 Subject: Remove undesired system add-ons (all except PDFjs) --- browser/extensions/aushelper/bootstrap.js | 189 ---- browser/extensions/aushelper/install.rdf.in | 32 - browser/extensions/aushelper/moz.build | 16 - browser/extensions/e10srollout/bootstrap.js | 197 ----- browser/extensions/e10srollout/install.rdf.in | 32 - browser/extensions/e10srollout/moz.build | 16 - browser/extensions/flyweb/bootstrap.js | 297 ------- browser/extensions/flyweb/install.rdf.in | 32 - browser/extensions/flyweb/jar.mn | 10 - browser/extensions/flyweb/moz.build | 18 - browser/extensions/flyweb/skin/flyweb-icon.svg | 40 - browser/extensions/flyweb/skin/linux/flyweb.css | 5 - browser/extensions/flyweb/skin/linux/icon-16.png | Bin 1251 -> 0 bytes .../flyweb/skin/linux/icon-32-anchored.png | Bin 2711 -> 0 bytes browser/extensions/flyweb/skin/linux/icon-32.png | Bin 699 -> 0 bytes .../flyweb/skin/linux/icon-64-anchored.png | Bin 6468 -> 0 bytes browser/extensions/flyweb/skin/linux/icon-64.png | Bin 1311 -> 0 bytes browser/extensions/flyweb/skin/osx/flyweb.css | 5 - browser/extensions/flyweb/skin/osx/icon-16.png | Bin 1646 -> 0 bytes .../flyweb/skin/osx/icon-32-anchored.png | Bin 2711 -> 0 bytes browser/extensions/flyweb/skin/osx/icon-32.png | Bin 2595 -> 0 bytes .../flyweb/skin/osx/icon-64-anchored.png | Bin 6468 -> 0 bytes browser/extensions/flyweb/skin/osx/icon-64.png | Bin 3168 -> 0 bytes browser/extensions/flyweb/skin/shared/flyweb.css | 54 -- browser/extensions/flyweb/skin/windows/flyweb.css | 5 - browser/extensions/flyweb/skin/windows/icon-16.png | Bin 1251 -> 0 bytes .../flyweb/skin/windows/icon-32-anchored.png | Bin 2711 -> 0 bytes browser/extensions/flyweb/skin/windows/icon-32.png | Bin 699 -> 0 bytes .../flyweb/skin/windows/icon-64-anchored.png | Bin 6468 -> 0 bytes browser/extensions/flyweb/skin/windows/icon-64.png | Bin 1311 -> 0 bytes browser/extensions/formautofill/.eslintrc.js | 474 ---------- browser/extensions/formautofill/bootstrap.js | 12 - .../formautofill/content/FormAutofillContent.jsm | 134 --- .../formautofill/content/FormAutofillParent.jsm | 173 ---- .../formautofill/content/ProfileStorage.jsm | 251 ------ browser/extensions/formautofill/install.rdf.in | 32 - browser/extensions/formautofill/jar.mn | 7 - browser/extensions/formautofill/moz.build | 18 - browser/extensions/moz.build | 10 - browser/extensions/pocket/bootstrap.js | 511 ----------- browser/extensions/pocket/content/AboutPocket.jsm | 93 -- browser/extensions/pocket/content/Pocket.jsm | 93 -- browser/extensions/pocket/content/main.js | 737 ---------------- .../pocket/content/panels/css/firasans.css | 6 - .../pocket/content/panels/css/normalize.css | 424 --------- .../extensions/pocket/content/panels/css/saved.css | 825 ------------------ .../pocket/content/panels/css/signup.css | 424 --------- .../content/panels/fonts/FiraSans-Regular.woff | Bin 179188 -> 0 bytes .../pocket/content/panels/img/pocket.svg | 22 - .../pocket/content/panels/img/pocketerror@1x.png | Bin 1479 -> 0 bytes .../pocket/content/panels/img/pocketerror@2x.png | Bin 3131 -> 0 bytes .../pocket/content/panels/img/pocketlogo@1x.png | Bin 3539 -> 0 bytes .../pocket/content/panels/img/pocketlogo@2x.png | Bin 7378 -> 0 bytes .../content/panels/img/pocketlogosolo@1x.png | Bin 1256 -> 0 bytes .../content/panels/img/pocketlogosolo@2x.png | Bin 2566 -> 0 bytes .../pocket/content/panels/img/pocketmenuitem16.png | Bin 264 -> 0 bytes .../content/panels/img/pocketmenuitem16@2x.png | Bin 641 -> 0 bytes .../content/panels/img/pocketsignup_button@1x.png | Bin 7315 -> 0 bytes .../content/panels/img/pocketsignup_button@2x.png | Bin 13480 -> 0 bytes .../content/panels/img/pocketsignup_devices@1x.png | Bin 22496 -> 0 bytes .../content/panels/img/pocketsignup_devices@2x.png | Bin 73925 -> 0 bytes .../content/panels/img/pocketsignup_hero@1x.png | Bin 44964 -> 0 bytes .../content/panels/img/pocketsignup_hero@2x.png | Bin 148877 -> 0 bytes .../content/panels/img/signup_firefoxlogo@1x.png | Bin 635 -> 0 bytes .../content/panels/img/signup_firefoxlogo@2x.png | Bin 1375 -> 0 bytes .../pocket/content/panels/img/signup_help@1x.png | Bin 659 -> 0 bytes .../pocket/content/panels/img/signup_help@2x.png | Bin 1420 -> 0 bytes .../pocket/content/panels/img/signup_or@1x.png | Bin 1843 -> 0 bytes .../pocket/content/panels/img/signup_or@2x.png | Bin 2925 -> 0 bytes .../pocket/content/panels/img/tag_close@1x.png | Bin 287 -> 0 bytes .../pocket/content/panels/img/tag_close@2x.png | Bin 508 -> 0 bytes .../content/panels/img/tag_closeactive@1x.png | Bin 208 -> 0 bytes .../content/panels/img/tag_closeactive@2x.png | Bin 354 -> 0 bytes .../pocket/content/panels/js/messages.js | 78 -- .../extensions/pocket/content/panels/js/saved.js | 608 ------------- .../extensions/pocket/content/panels/js/signup.js | 193 ----- .../extensions/pocket/content/panels/js/tmpl.js | 242 ------ .../content/panels/js/vendor/handlebars.runtime.js | 660 -------------- .../content/panels/js/vendor/jquery-2.1.1.min.js | 4 - .../panels/js/vendor/jquery.tokeninput.min.js | 954 --------------------- .../extensions/pocket/content/panels/license.txt | 35 - .../extensions/pocket/content/panels/saved.html | 19 - .../extensions/pocket/content/panels/signup.html | 18 - .../panels/tmpl/saved_premiumextras.handlebars | 2 - .../panels/tmpl/saved_premiumshell.handlebars | 6 - .../content/panels/tmpl/saved_shell.handlebars | 29 - .../content/panels/tmpl/signup_shell.handlebars | 32 - .../panels/tmpl/signupstoryboard_shell.handlebars | 43 - browser/extensions/pocket/content/pktApi.jsm | 657 -------------- .../pocket/content/pocket-content-process.js | 54 -- browser/extensions/pocket/install.rdf.in | 32 - browser/extensions/pocket/jar.mn | 32 - .../extensions/pocket/locale/ast/pocket.properties | 43 - .../extensions/pocket/locale/az/pocket.properties | 43 - .../extensions/pocket/locale/bg/pocket.properties | 43 - .../pocket/locale/bn-BD/pocket.properties | 43 - .../extensions/pocket/locale/cs/pocket.properties | 43 - .../extensions/pocket/locale/da/pocket.properties | 43 - .../extensions/pocket/locale/de/pocket.properties | 43 - .../extensions/pocket/locale/dsb/pocket.properties | 43 - .../pocket/locale/en-GB/pocket.properties | 43 - .../pocket/locale/en-US/pocket.properties | 43 - .../pocket/locale/es-AR/pocket.properties | 43 - .../pocket/locale/es-CL/pocket.properties | 43 - .../pocket/locale/es-ES/pocket.properties | 43 - .../pocket/locale/es-MX/pocket.properties | 43 - .../extensions/pocket/locale/et/pocket.properties | 43 - .../extensions/pocket/locale/fi/pocket.properties | 43 - .../extensions/pocket/locale/fr/pocket.properties | 43 - .../pocket/locale/fy-NL/pocket.properties | 43 - .../pocket/locale/gu-IN/pocket.properties | 43 - .../extensions/pocket/locale/hr/pocket.properties | 43 - .../extensions/pocket/locale/hsb/pocket.properties | 43 - .../extensions/pocket/locale/hu/pocket.properties | 43 - .../extensions/pocket/locale/it/pocket.properties | 43 - .../extensions/pocket/locale/ja/pocket.properties | 43 - browser/extensions/pocket/locale/jar.mn | 33 - .../extensions/pocket/locale/ka/pocket.properties | 43 - .../extensions/pocket/locale/kab/pocket.properties | 43 - .../extensions/pocket/locale/lt/pocket.properties | 43 - .../extensions/pocket/locale/lv/pocket.properties | 43 - browser/extensions/pocket/locale/moz.build | 7 - .../extensions/pocket/locale/mr/pocket.properties | 43 - .../extensions/pocket/locale/ms/pocket.properties | 43 - .../extensions/pocket/locale/nl/pocket.properties | 43 - .../pocket/locale/nn-NO/pocket.properties | 43 - .../extensions/pocket/locale/or/pocket.properties | 43 - .../extensions/pocket/locale/pl/pocket.properties | 48 -- .../pocket/locale/pt-BR/pocket.properties | 43 - .../pocket/locale/pt-PT/pocket.properties | 43 - .../extensions/pocket/locale/rm/pocket.properties | 43 - .../extensions/pocket/locale/ro/pocket.properties | 43 - .../extensions/pocket/locale/ru/pocket.properties | 43 - .../extensions/pocket/locale/sk/pocket.properties | 43 - .../extensions/pocket/locale/sl/pocket.properties | 43 - .../extensions/pocket/locale/sq/pocket.properties | 43 - .../extensions/pocket/locale/sr/pocket.properties | 43 - .../pocket/locale/sv-SE/pocket.properties | 43 - .../extensions/pocket/locale/te/pocket.properties | 43 - .../extensions/pocket/locale/th/pocket.properties | 43 - .../extensions/pocket/locale/tr/pocket.properties | 43 - .../extensions/pocket/locale/uk/pocket.properties | 43 - .../pocket/locale/zh-CN/pocket.properties | 43 - .../pocket/locale/zh-TW/pocket.properties | 43 - browser/extensions/pocket/moz.build | 20 - .../pocket/skin/linux/Toolbar-inverted.png | Bin 743 -> 0 bytes .../pocket/skin/linux/Toolbar-inverted@2x.png | Bin 2299 -> 0 bytes browser/extensions/pocket/skin/linux/Toolbar.png | Bin 975 -> 0 bytes .../extensions/pocket/skin/linux/Toolbar@2x.png | Bin 3223 -> 0 bytes browser/extensions/pocket/skin/linux/menuPanel.png | Bin 1377 -> 0 bytes .../extensions/pocket/skin/linux/menuPanel@2x.png | Bin 2671 -> 0 bytes browser/extensions/pocket/skin/linux/pocket.css | 10 - .../pocket/skin/osx/Toolbar-inverted.png | Bin 1438 -> 0 bytes .../pocket/skin/osx/Toolbar-inverted@2x.png | Bin 3323 -> 0 bytes .../pocket/skin/osx/Toolbar-yosemite.png | Bin 958 -> 0 bytes .../pocket/skin/osx/Toolbar-yosemite@2x.png | Bin 2129 -> 0 bytes browser/extensions/pocket/skin/osx/Toolbar.png | Bin 1571 -> 0 bytes browser/extensions/pocket/skin/osx/Toolbar@2x.png | Bin 3613 -> 0 bytes .../pocket/skin/osx/menuPanel-yosemite.png | Bin 1570 -> 0 bytes .../pocket/skin/osx/menuPanel-yosemite@2x.png | Bin 3316 -> 0 bytes browser/extensions/pocket/skin/osx/menuPanel.png | Bin 1976 -> 0 bytes .../extensions/pocket/skin/osx/menuPanel@2x.png | Bin 3861 -> 0 bytes browser/extensions/pocket/skin/osx/pocket.css | 42 - browser/extensions/pocket/skin/shared/pocket.css | 79 -- .../extensions/pocket/skin/windows/Toolbar-XP.png | Bin 1141 -> 0 bytes .../pocket/skin/windows/Toolbar-aero.png | Bin 1163 -> 0 bytes .../pocket/skin/windows/Toolbar-aero@2x.png | Bin 2612 -> 0 bytes .../pocket/skin/windows/Toolbar-inverted.png | Bin 825 -> 0 bytes .../pocket/skin/windows/Toolbar-inverted@2x.png | Bin 1767 -> 0 bytes .../pocket/skin/windows/Toolbar-lunaSilver.png | Bin 1155 -> 0 bytes .../pocket/skin/windows/Toolbar-win8.png | Bin 649 -> 0 bytes .../pocket/skin/windows/Toolbar-win8@2x.png | Bin 1036 -> 0 bytes browser/extensions/pocket/skin/windows/Toolbar.png | Bin 635 -> 0 bytes .../extensions/pocket/skin/windows/Toolbar@2x.png | Bin 1001 -> 0 bytes .../pocket/skin/windows/menuPanel-aero.png | Bin 2097 -> 0 bytes .../pocket/skin/windows/menuPanel-aero@2x.png | Bin 5063 -> 0 bytes .../extensions/pocket/skin/windows/menuPanel.png | Bin 1377 -> 0 bytes .../pocket/skin/windows/menuPanel@2x.png | Bin 2671 -> 0 bytes browser/extensions/pocket/skin/windows/pocket.css | 16 - browser/extensions/webcompat/bootstrap.js | 9 - browser/extensions/webcompat/install.rdf.in | 32 - browser/extensions/webcompat/moz.build | 16 - 182 files changed, 11311 deletions(-) delete mode 100644 browser/extensions/aushelper/bootstrap.js delete mode 100644 browser/extensions/aushelper/install.rdf.in delete mode 100644 browser/extensions/aushelper/moz.build delete mode 100644 browser/extensions/e10srollout/bootstrap.js delete mode 100644 browser/extensions/e10srollout/install.rdf.in delete mode 100644 browser/extensions/e10srollout/moz.build delete mode 100644 browser/extensions/flyweb/bootstrap.js delete mode 100644 browser/extensions/flyweb/install.rdf.in delete mode 100644 browser/extensions/flyweb/jar.mn delete mode 100644 browser/extensions/flyweb/moz.build delete mode 100644 browser/extensions/flyweb/skin/flyweb-icon.svg delete mode 100644 browser/extensions/flyweb/skin/linux/flyweb.css delete mode 100644 browser/extensions/flyweb/skin/linux/icon-16.png delete mode 100644 browser/extensions/flyweb/skin/linux/icon-32-anchored.png delete mode 100644 browser/extensions/flyweb/skin/linux/icon-32.png delete mode 100644 browser/extensions/flyweb/skin/linux/icon-64-anchored.png delete mode 100644 browser/extensions/flyweb/skin/linux/icon-64.png delete mode 100644 browser/extensions/flyweb/skin/osx/flyweb.css delete mode 100644 browser/extensions/flyweb/skin/osx/icon-16.png delete mode 100644 browser/extensions/flyweb/skin/osx/icon-32-anchored.png delete mode 100644 browser/extensions/flyweb/skin/osx/icon-32.png delete mode 100644 browser/extensions/flyweb/skin/osx/icon-64-anchored.png delete mode 100644 browser/extensions/flyweb/skin/osx/icon-64.png delete mode 100644 browser/extensions/flyweb/skin/shared/flyweb.css delete mode 100644 browser/extensions/flyweb/skin/windows/flyweb.css delete mode 100644 browser/extensions/flyweb/skin/windows/icon-16.png delete mode 100644 browser/extensions/flyweb/skin/windows/icon-32-anchored.png delete mode 100644 browser/extensions/flyweb/skin/windows/icon-32.png delete mode 100644 browser/extensions/flyweb/skin/windows/icon-64-anchored.png delete mode 100644 browser/extensions/flyweb/skin/windows/icon-64.png delete mode 100644 browser/extensions/formautofill/.eslintrc.js delete mode 100644 browser/extensions/formautofill/bootstrap.js delete mode 100644 browser/extensions/formautofill/content/FormAutofillContent.jsm delete mode 100644 browser/extensions/formautofill/content/FormAutofillParent.jsm delete mode 100644 browser/extensions/formautofill/content/ProfileStorage.jsm delete mode 100644 browser/extensions/formautofill/install.rdf.in delete mode 100644 browser/extensions/formautofill/jar.mn delete mode 100644 browser/extensions/formautofill/moz.build delete mode 100644 browser/extensions/pocket/bootstrap.js delete mode 100644 browser/extensions/pocket/content/AboutPocket.jsm delete mode 100644 browser/extensions/pocket/content/Pocket.jsm delete mode 100644 browser/extensions/pocket/content/main.js delete mode 100644 browser/extensions/pocket/content/panels/css/firasans.css delete mode 100644 browser/extensions/pocket/content/panels/css/normalize.css delete mode 100644 browser/extensions/pocket/content/panels/css/saved.css delete mode 100644 browser/extensions/pocket/content/panels/css/signup.css delete mode 100644 browser/extensions/pocket/content/panels/fonts/FiraSans-Regular.woff delete mode 100644 browser/extensions/pocket/content/panels/img/pocket.svg delete mode 100644 browser/extensions/pocket/content/panels/img/pocketerror@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketerror@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketlogo@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketlogo@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketlogosolo@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketlogosolo@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketmenuitem16.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketmenuitem16@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketsignup_button@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketsignup_button@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketsignup_devices@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketsignup_devices@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketsignup_hero@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/pocketsignup_hero@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/signup_firefoxlogo@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/signup_firefoxlogo@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/signup_help@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/signup_help@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/signup_or@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/signup_or@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/tag_close@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/tag_close@2x.png delete mode 100644 browser/extensions/pocket/content/panels/img/tag_closeactive@1x.png delete mode 100644 browser/extensions/pocket/content/panels/img/tag_closeactive@2x.png delete mode 100644 browser/extensions/pocket/content/panels/js/messages.js delete mode 100644 browser/extensions/pocket/content/panels/js/saved.js delete mode 100644 browser/extensions/pocket/content/panels/js/signup.js delete mode 100644 browser/extensions/pocket/content/panels/js/tmpl.js delete mode 100644 browser/extensions/pocket/content/panels/js/vendor/handlebars.runtime.js delete mode 100644 browser/extensions/pocket/content/panels/js/vendor/jquery-2.1.1.min.js delete mode 100644 browser/extensions/pocket/content/panels/js/vendor/jquery.tokeninput.min.js delete mode 100644 browser/extensions/pocket/content/panels/license.txt delete mode 100644 browser/extensions/pocket/content/panels/saved.html delete mode 100644 browser/extensions/pocket/content/panels/signup.html delete mode 100644 browser/extensions/pocket/content/panels/tmpl/saved_premiumextras.handlebars delete mode 100644 browser/extensions/pocket/content/panels/tmpl/saved_premiumshell.handlebars delete mode 100644 browser/extensions/pocket/content/panels/tmpl/saved_shell.handlebars delete mode 100644 browser/extensions/pocket/content/panels/tmpl/signup_shell.handlebars delete mode 100644 browser/extensions/pocket/content/panels/tmpl/signupstoryboard_shell.handlebars delete mode 100644 browser/extensions/pocket/content/pktApi.jsm delete mode 100644 browser/extensions/pocket/content/pocket-content-process.js delete mode 100644 browser/extensions/pocket/install.rdf.in delete mode 100644 browser/extensions/pocket/jar.mn delete mode 100644 browser/extensions/pocket/locale/ast/pocket.properties delete mode 100644 browser/extensions/pocket/locale/az/pocket.properties delete mode 100644 browser/extensions/pocket/locale/bg/pocket.properties delete mode 100644 browser/extensions/pocket/locale/bn-BD/pocket.properties delete mode 100644 browser/extensions/pocket/locale/cs/pocket.properties delete mode 100644 browser/extensions/pocket/locale/da/pocket.properties delete mode 100644 browser/extensions/pocket/locale/de/pocket.properties delete mode 100644 browser/extensions/pocket/locale/dsb/pocket.properties delete mode 100644 browser/extensions/pocket/locale/en-GB/pocket.properties delete mode 100644 browser/extensions/pocket/locale/en-US/pocket.properties delete mode 100644 browser/extensions/pocket/locale/es-AR/pocket.properties delete mode 100644 browser/extensions/pocket/locale/es-CL/pocket.properties delete mode 100644 browser/extensions/pocket/locale/es-ES/pocket.properties delete mode 100644 browser/extensions/pocket/locale/es-MX/pocket.properties delete mode 100644 browser/extensions/pocket/locale/et/pocket.properties delete mode 100644 browser/extensions/pocket/locale/fi/pocket.properties delete mode 100644 browser/extensions/pocket/locale/fr/pocket.properties delete mode 100644 browser/extensions/pocket/locale/fy-NL/pocket.properties delete mode 100644 browser/extensions/pocket/locale/gu-IN/pocket.properties delete mode 100644 browser/extensions/pocket/locale/hr/pocket.properties delete mode 100644 browser/extensions/pocket/locale/hsb/pocket.properties delete mode 100644 browser/extensions/pocket/locale/hu/pocket.properties delete mode 100644 browser/extensions/pocket/locale/it/pocket.properties delete mode 100644 browser/extensions/pocket/locale/ja/pocket.properties delete mode 100644 browser/extensions/pocket/locale/jar.mn delete mode 100644 browser/extensions/pocket/locale/ka/pocket.properties delete mode 100644 browser/extensions/pocket/locale/kab/pocket.properties delete mode 100644 browser/extensions/pocket/locale/lt/pocket.properties delete mode 100644 browser/extensions/pocket/locale/lv/pocket.properties delete mode 100644 browser/extensions/pocket/locale/moz.build delete mode 100644 browser/extensions/pocket/locale/mr/pocket.properties delete mode 100644 browser/extensions/pocket/locale/ms/pocket.properties delete mode 100644 browser/extensions/pocket/locale/nl/pocket.properties delete mode 100644 browser/extensions/pocket/locale/nn-NO/pocket.properties delete mode 100644 browser/extensions/pocket/locale/or/pocket.properties delete mode 100644 browser/extensions/pocket/locale/pl/pocket.properties delete mode 100644 browser/extensions/pocket/locale/pt-BR/pocket.properties delete mode 100644 browser/extensions/pocket/locale/pt-PT/pocket.properties delete mode 100644 browser/extensions/pocket/locale/rm/pocket.properties delete mode 100644 browser/extensions/pocket/locale/ro/pocket.properties delete mode 100644 browser/extensions/pocket/locale/ru/pocket.properties delete mode 100644 browser/extensions/pocket/locale/sk/pocket.properties delete mode 100644 browser/extensions/pocket/locale/sl/pocket.properties delete mode 100644 browser/extensions/pocket/locale/sq/pocket.properties delete mode 100644 browser/extensions/pocket/locale/sr/pocket.properties delete mode 100644 browser/extensions/pocket/locale/sv-SE/pocket.properties delete mode 100644 browser/extensions/pocket/locale/te/pocket.properties delete mode 100644 browser/extensions/pocket/locale/th/pocket.properties delete mode 100644 browser/extensions/pocket/locale/tr/pocket.properties delete mode 100644 browser/extensions/pocket/locale/uk/pocket.properties delete mode 100644 browser/extensions/pocket/locale/zh-CN/pocket.properties delete mode 100644 browser/extensions/pocket/locale/zh-TW/pocket.properties delete mode 100644 browser/extensions/pocket/moz.build delete mode 100644 browser/extensions/pocket/skin/linux/Toolbar-inverted.png delete mode 100644 browser/extensions/pocket/skin/linux/Toolbar-inverted@2x.png delete mode 100644 browser/extensions/pocket/skin/linux/Toolbar.png delete mode 100644 browser/extensions/pocket/skin/linux/Toolbar@2x.png delete mode 100644 browser/extensions/pocket/skin/linux/menuPanel.png delete mode 100644 browser/extensions/pocket/skin/linux/menuPanel@2x.png delete mode 100644 browser/extensions/pocket/skin/linux/pocket.css delete mode 100644 browser/extensions/pocket/skin/osx/Toolbar-inverted.png delete mode 100644 browser/extensions/pocket/skin/osx/Toolbar-inverted@2x.png delete mode 100644 browser/extensions/pocket/skin/osx/Toolbar-yosemite.png delete mode 100644 browser/extensions/pocket/skin/osx/Toolbar-yosemite@2x.png delete mode 100644 browser/extensions/pocket/skin/osx/Toolbar.png delete mode 100644 browser/extensions/pocket/skin/osx/Toolbar@2x.png delete mode 100644 browser/extensions/pocket/skin/osx/menuPanel-yosemite.png delete mode 100644 browser/extensions/pocket/skin/osx/menuPanel-yosemite@2x.png delete mode 100644 browser/extensions/pocket/skin/osx/menuPanel.png delete mode 100644 browser/extensions/pocket/skin/osx/menuPanel@2x.png delete mode 100644 browser/extensions/pocket/skin/osx/pocket.css delete mode 100644 browser/extensions/pocket/skin/shared/pocket.css delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-XP.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-aero.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-aero@2x.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-inverted.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-inverted@2x.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-lunaSilver.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-win8.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar-win8@2x.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar.png delete mode 100644 browser/extensions/pocket/skin/windows/Toolbar@2x.png delete mode 100644 browser/extensions/pocket/skin/windows/menuPanel-aero.png delete mode 100644 browser/extensions/pocket/skin/windows/menuPanel-aero@2x.png delete mode 100644 browser/extensions/pocket/skin/windows/menuPanel.png delete mode 100644 browser/extensions/pocket/skin/windows/menuPanel@2x.png delete mode 100644 browser/extensions/pocket/skin/windows/pocket.css delete mode 100644 browser/extensions/webcompat/bootstrap.js delete mode 100644 browser/extensions/webcompat/install.rdf.in delete mode 100644 browser/extensions/webcompat/moz.build diff --git a/browser/extensions/aushelper/bootstrap.js b/browser/extensions/aushelper/bootstrap.js deleted file mode 100644 index f57f621e1..000000000 --- a/browser/extensions/aushelper/bootstrap.js +++ /dev/null @@ -1,189 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* 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/. */ - -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -const APP_UPDATE_URL_PREF = "app.update.url"; -const REPLACE_KEY = "%OS_VERSION%"; - -const AUSHELPER_CPU_RESULT_CODE_HISTOGRAM_ID = "AUSHELPER_CPU_RESULT_CODE"; -// The system is not vulnerable to Bug 1296630. -const CPU_NO_BUG1296630 = 1; -// The system is vulnerable to Bug 1296630. -const CPU_YES_BUG1296630 = 2; -// An error occured when checking if the system is vulnerable to Bug 1296630. -const CPU_ERR_BUG1296630 = 3; -// It is unknown whether the system is vulnerable to Bug 1296630 (should never happen). -const CPU_UNKNOWN_BUG1296630 = 4; - -const AUSHELPER_CPU_ERROR_CODE_HISTOGRAM_ID = "AUSHELPER_CPU_ERROR_CODE"; -const CPU_SUCCESS = 0; -const CPU_REG_OPEN_ERROR = 1; -const CPU_VENDOR_ID_ERROR = 2; -const CPU_ID_ERROR = 4; -const CPU_REV_ERROR = 8; - -const AUSHELPER_WEBSENSE_REG_VERSION_SCALAR_NAME = "aushelper.websense_reg_version"; -const AUSHELPER_WEBSENSE_REG_EXISTS_HISTOGRAM_ID = "AUSHELPER_WEBSENSE_REG_EXISTS"; - -const AUSHELPER_WEBSENSE_ERROR_CODE_HISTOGRAM_ID = "AUSHELPER_WEBSENSE_ERROR_CODE"; -const WEBSENSE_SUCCESS = 0; -const WEBSENSE_REG_OPEN_ERROR = 1; -const WEBSENSE_REG_READ_ERROR = 2; -const WEBSENSE_ALREADY_MODIFIED = 4; - -Cu.import("resource://gre/modules/Services.jsm"); - -function startup() { - if (Services.appinfo.OS != "WINNT") { - return; - } - - const regCPUPath = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; - let wrk; - let cpuErrorCode = CPU_SUCCESS; - try { - wrk = Cc["@mozilla.org/windows-registry-key;1"].createInstance(Ci.nsIWindowsRegKey); - wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE, regCPUPath, wrk.ACCESS_READ); - } catch (e) { - Cu.reportError("AUSHelper - unable to open registry. Exception: " + e); - cpuErrorCode |= CPU_REG_OPEN_ERROR; - } - - // If any of the following values are successfully retrieved and they don't - // match the condition for that value then it is safe to update. Hence why the - // following checks are somewhat convoluted. The possible values for the - // variable set by each check is as follows: - // - // | Match | No Match | Error | - // variable | true | false | null | - - let cpuVendorIDMatch = false; - try { - let cpuVendorID = wrk.readStringValue("VendorIdentifier"); - if (cpuVendorID.toLowerCase() == "genuineintel") { - cpuVendorIDMatch = true; - } - } catch (e) { - Cu.reportError("AUSHelper - error getting CPU vendor indentifier. Exception: " + e); - cpuVendorIDMatch = null; - cpuErrorCode |= CPU_VENDOR_ID_ERROR; - } - - let cpuIDMatch = false; - try { - let cpuID = wrk.readStringValue("Identifier"); - if (cpuID.toLowerCase().indexOf("family 6 model 61 stepping 4") != -1) { - cpuIDMatch = true; - } - } catch (e) { - Cu.reportError("AUSHelper - error getting CPU indentifier. Exception: " + e); - cpuIDMatch = null; - cpuErrorCode |= CPU_ID_ERROR; - } - - let microCodeVersions = [0xe, 0x11, 0x12, 0x13, 0x16, 0x18, 0x19]; - let cpuRevMatch = null; - try { - let keyNames = ["Update Revision", "Update Signature"]; - for (let i = 0; i < keyNames.length; ++i) { - try { - let regVal = wrk.readBinaryValue(keyNames[i]); - if (regVal.length == 8) { - let hexVal = []; - // We are only inyterested in the upper 4 bytes and the little endian - // value for it. - for (let j = 4; j < 8; j++) { - let c = regVal.charCodeAt(j).toString(16); - if (c.length == 1) { - c = "0" + c; - } - hexVal.unshift(c); - } - cpuRevMatch = false; - if (microCodeVersions.indexOf(parseInt(hexVal.join(''))) != -1) { - cpuRevMatch = true; - } - break; - } - } catch (e) { - if (i == keyNames.length - 1) { - // The registry key name's value was not successfully queried. - cpuRevMatch = null; - cpuErrorCode |= CPU_REV_ERROR; - } - } - } - wrk.close(); - } catch (ex) { - Cu.reportError("AUSHelper - error getting CPU revision. Exception: " + ex); - cpuRevMatch = null; - cpuErrorCode |= CPU_REV_ERROR; - } - - let cpuResult = CPU_UNKNOWN_BUG1296630; - let cpuValue = "(unkBug1296630v1)"; - // The following uses strict equality checks since the values can be true, - // false, or null. - if (cpuVendorIDMatch === false || cpuIDMatch === false || cpuRevMatch === false) { - // Since one of the values is false then the system won't be affected by - // bug 1296630 according to the conditions set out in bug 1311515. - cpuValue = "(noBug1296630v1)"; - cpuResult = CPU_NO_BUG1296630; - } else if (cpuVendorIDMatch === null || cpuIDMatch === null || cpuRevMatch === null) { - // Since one of the values is null we can't say for sure if the system will - // be affected by bug 1296630. - cpuValue = "(errBug1296630v1)"; - cpuResult = CPU_ERR_BUG1296630; - } else if (cpuVendorIDMatch === true && cpuIDMatch === true && cpuRevMatch === true) { - // Since all of the values are true we can say that the system will be - // affected by bug 1296630. - cpuValue = "(yesBug1296630v1)"; - cpuResult = CPU_YES_BUG1296630; - } - - Services.telemetry.getHistogramById(AUSHELPER_CPU_RESULT_CODE_HISTOGRAM_ID).add(cpuResult); - Services.telemetry.getHistogramById(AUSHELPER_CPU_ERROR_CODE_HISTOGRAM_ID).add(cpuErrorCode); - - const regWebsensePath = "Websense\\Agent"; - let websenseErrorCode = WEBSENSE_SUCCESS; - let websenseVersion = ""; - try { - let regModes = [wrk.ACCESS_READ, wrk.ACCESS_READ | wrk.WOW64_64]; - for (let i = 0; i < regModes.length; ++i) { - wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE, "SOFTWARE", regModes[i]); - try { - if (wrk.hasChild(regWebsensePath)) { - let childKey = wrk.openChild(regWebsensePath, wrk.ACCESS_READ); - websenseVersion = childKey.readStringValue("InstallVersion"); - Services.telemetry.scalarSet(AUSHELPER_WEBSENSE_REG_VERSION_SCALAR_NAME, websenseVersion); - } - wrk.close(); - } catch (e) { - Cu.reportError("AUSHelper - unable to read registry. Exception: " + e); - websenseErrorCode |= WEBSENSE_REG_READ_ERROR; - } - } - } catch (ex) { - Cu.reportError("AUSHelper - unable to open registry. Exception: " + ex); - websenseErrorCode |= WEBSENSE_REG_OPEN_ERROR; - } - - Services.telemetry.getHistogramById(AUSHELPER_WEBSENSE_REG_EXISTS_HISTOGRAM_ID).add(!!websenseVersion); - let websenseValue = "(" + (websenseVersion ? "websense-" + websenseVersion : "nowebsense") + ")"; - - let branch = Services.prefs.getDefaultBranch(""); - let curValue = branch.getCharPref(APP_UPDATE_URL_PREF); - if (curValue.indexOf(REPLACE_KEY + "/") > -1) { - let newValue = curValue.replace(REPLACE_KEY + "/", REPLACE_KEY + cpuValue + websenseValue + "/"); - branch.setCharPref(APP_UPDATE_URL_PREF, newValue); - } else { - websenseErrorCode |= WEBSENSE_ALREADY_MODIFIED; - } - Services.telemetry.getHistogramById(AUSHELPER_WEBSENSE_ERROR_CODE_HISTOGRAM_ID).add(websenseErrorCode); -} -function shutdown() {} -function install() {} -function uninstall() {} diff --git a/browser/extensions/aushelper/install.rdf.in b/browser/extensions/aushelper/install.rdf.in deleted file mode 100644 index 78e841d88..000000000 --- a/browser/extensions/aushelper/install.rdf.in +++ /dev/null @@ -1,32 +0,0 @@ - - - -#filter substitution - - - - - aushelper@mozilla.org - 2.0 - 2 - true - true - - - - - {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @MOZ_APP_VERSION@ - @MOZ_APP_MAXVERSION@ - - - - - Application Update Service Helper - Sets value(s) in the update url based on custom checks. - - diff --git a/browser/extensions/aushelper/moz.build b/browser/extensions/aushelper/moz.build deleted file mode 100644 index a4ff06055..000000000 --- a/browser/extensions/aushelper/moz.build +++ /dev/null @@ -1,16 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] -DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] - -FINAL_TARGET_FILES.features['aushelper@mozilla.org'] += [ - 'bootstrap.js' -] - -FINAL_TARGET_PP_FILES.features['aushelper@mozilla.org'] += [ - 'install.rdf.in' -] diff --git a/browser/extensions/e10srollout/bootstrap.js b/browser/extensions/e10srollout/bootstrap.js deleted file mode 100644 index 0da7ac225..000000000 --- a/browser/extensions/e10srollout/bootstrap.js +++ /dev/null @@ -1,197 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/UpdateUtils.jsm"); -Cu.import("resource://gre/modules/AppConstants.jsm"); - - // The amount of people to be part of e10s -const TEST_THRESHOLD = { - "beta" : 0.5, // 50% - "release" : 1.0, // 100% - "esr" : 1.0, // 100% -}; - -const ADDON_ROLLOUT_POLICY = { - "beta" : "51alladdons", // Any WebExtension or addon except with mpc = false - "release" : "51set1", - "esr" : "esrA", // WebExtensions and Addons with mpc=true -}; - -if (AppConstants.RELEASE_OR_BETA) { - // Bug 1348576 - e10s is never enabled for non-official release builds - // This is hacky, but the problem it solves is the following: - // the e10s rollout is controlled by the channel name, which - // is the only way to distinguish between Beta and Release. - // However, non-official release builds (like the ones done by distros - // to ship Firefox on their package managers) do not set a value - // for the release channel, which gets them to the default value - // of.. (drumroll) "default". - // But we can't just always configure the same settings for the - // "default" channel because that's also the name that a locally - // built Firefox gets, and e10s is managed in a different way - // there (directly by prefs, on Nightly and Aurora). - TEST_THRESHOLD.default = TEST_THRESHOLD.release; - ADDON_ROLLOUT_POLICY.default = ADDON_ROLLOUT_POLICY.release; -} - - -const PREF_COHORT_SAMPLE = "e10s.rollout.cohortSample"; -const PREF_COHORT_NAME = "e10s.rollout.cohort"; -const PREF_E10S_OPTED_IN = "browser.tabs.remote.autostart"; -const PREF_E10S_FORCE_ENABLED = "browser.tabs.remote.force-enable"; -const PREF_E10S_FORCE_DISABLED = "browser.tabs.remote.force-disable"; -const PREF_TOGGLE_E10S = "browser.tabs.remote.autostart.2"; -const PREF_E10S_ADDON_POLICY = "extensions.e10s.rollout.policy"; -const PREF_E10S_ADDON_BLOCKLIST = "extensions.e10s.rollout.blocklist"; -const PREF_E10S_HAS_NONEXEMPT_ADDON = "extensions.e10s.rollout.hasAddon"; - -function startup() { - // In theory we only need to run this once (on install()), but - // it's better to also run it on every startup. If the user has - // made manual changes to the prefs, this will keep the data - // reported more accurate. - // It's also fine (and preferred) to just do it here on startup - // (instead of observing prefs), because e10s takes a restart - // to take effect, so we keep the data based on how it was when - // the session started. - defineCohort(); -} - -function install() { - defineCohort(); -} - -let cohortDefinedOnThisSession = false; - -function defineCohort() { - // Avoid running twice when it was called by install() first - if (cohortDefinedOnThisSession) { - return; - } - cohortDefinedOnThisSession = true; - - let updateChannel = UpdateUtils.getUpdateChannel(false); - if (!(updateChannel in TEST_THRESHOLD)) { - setCohort("unsupportedChannel"); - return; - } - - let addonPolicy = "unknown"; - if (updateChannel in ADDON_ROLLOUT_POLICY) { - addonPolicy = ADDON_ROLLOUT_POLICY[updateChannel]; - Preferences.set(PREF_E10S_ADDON_POLICY, addonPolicy); - // This is also the proper place to set the blocklist pref - // in case it is necessary. - - Preferences.set(PREF_E10S_ADDON_BLOCKLIST, - // bug 1185672 - Tab Mix Plus - "{dc572301-7619-498c-a57d-39143191b318};" + - // bug 1332692 - LastPass - "support@lastpass.com;"); - } else { - Preferences.reset(PREF_E10S_ADDON_POLICY); - } - - let userOptedOut = optedOut(); - let userOptedIn = optedIn(); - let disqualified = (Services.appinfo.multiprocessBlockPolicy != 0); - let testGroup = (getUserSample() < TEST_THRESHOLD[updateChannel]); - let hasNonExemptAddon = Preferences.get(PREF_E10S_HAS_NONEXEMPT_ADDON, false); - let temporaryDisqualification = getTemporaryDisqualification(); - - let cohortPrefix = ""; - if (disqualified) { - cohortPrefix = "disqualified-"; - } else if (hasNonExemptAddon) { - cohortPrefix = `addons-set${addonPolicy}-`; - } - - if (userOptedOut) { - setCohort("optedOut"); - } else if (userOptedIn) { - setCohort("optedIn"); - } else if (temporaryDisqualification != "") { - // Users who are disqualified by the backend (from multiprocessBlockPolicy) - // can be put into either the test or control groups, because e10s will - // still be denied by the backend, which is useful so that the E10S_STATUS - // telemetry probe can be correctly set. - - // For these volatile disqualification reasons, however, we must not try - // to activate e10s because the backend doesn't know about it. E10S_STATUS - // here will be accumulated as "2 - Disabled", which is fine too. - setCohort(`temp-disqualified-${temporaryDisqualification}`); - Preferences.reset(PREF_TOGGLE_E10S); - } else if (testGroup) { - setCohort(`${cohortPrefix}test`); - Preferences.set(PREF_TOGGLE_E10S, true); - } else { - setCohort(`${cohortPrefix}control`); - Preferences.reset(PREF_TOGGLE_E10S); - } -} - -function shutdown(data, reason) { -} - -function uninstall() { -} - -function getUserSample() { - let prefValue = Preferences.get(PREF_COHORT_SAMPLE, undefined); - let value = 0.0; - - if (typeof(prefValue) == "string") { - value = parseFloat(prefValue, 10); - return value; - } - - if (typeof(prefValue) == "number") { - // convert old integer value - value = prefValue / 100; - } else { - value = Math.random(); - } - - Preferences.set(PREF_COHORT_SAMPLE, value.toString().substr(0, 8)); - return value; -} - -function setCohort(cohortName) { - Preferences.set(PREF_COHORT_NAME, cohortName); - try { - if (Ci.nsICrashReporter) { - Services.appinfo.QueryInterface(Ci.nsICrashReporter).annotateCrashReport("E10SCohort", cohortName); - } - } catch (e) {} -} - -function optedIn() { - return Preferences.get(PREF_E10S_OPTED_IN, false) || - Preferences.get(PREF_E10S_FORCE_ENABLED, false); -} - -function optedOut() { - // Users can also opt-out by toggling back the pref to false. - // If they reset the pref instead they might be re-enabled if - // they are still part of the threshold. - return Preferences.get(PREF_E10S_FORCE_DISABLED, false) || - (Preferences.isSet(PREF_TOGGLE_E10S) && - Preferences.get(PREF_TOGGLE_E10S) == false); -} - -/* If this function returns a non-empty string, it - * means that this particular user should be temporarily - * disqualified due to some particular reason. - * If a user shouldn't be disqualified, then an empty - * string must be returned. - */ -function getTemporaryDisqualification() { - return ""; -} diff --git a/browser/extensions/e10srollout/install.rdf.in b/browser/extensions/e10srollout/install.rdf.in deleted file mode 100644 index 19ff58471..000000000 --- a/browser/extensions/e10srollout/install.rdf.in +++ /dev/null @@ -1,32 +0,0 @@ - - - -#filter substitution - - - - - e10srollout@mozilla.org - 1.10 - 2 - true - true - - - - - {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @MOZ_APP_VERSION@ - @MOZ_APP_MAXVERSION@ - - - - - Multi-process staged rollout - Staged rollout of Firefox multi-process feature. - - diff --git a/browser/extensions/e10srollout/moz.build b/browser/extensions/e10srollout/moz.build deleted file mode 100644 index 9b5a16d5a..000000000 --- a/browser/extensions/e10srollout/moz.build +++ /dev/null @@ -1,16 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] -DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] - -FINAL_TARGET_FILES.features['e10srollout@mozilla.org'] += [ - 'bootstrap.js' -] - -FINAL_TARGET_PP_FILES.features['e10srollout@mozilla.org'] += [ - 'install.rdf.in' -] diff --git a/browser/extensions/flyweb/bootstrap.js b/browser/extensions/flyweb/bootstrap.js deleted file mode 100644 index 089226519..000000000 --- a/browser/extensions/flyweb/bootstrap.js +++ /dev/null @@ -1,297 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* 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/. */ - -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI", - "resource:///modules/CustomizableUI.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Console", - "resource://gre/modules/Console.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Services", - "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Integration", - "resource://gre/modules/Integration.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PermissionUI", - "resource:///modules/PermissionUI.jsm"); - -XPCOMUtils.defineLazyGetter(this, "gFlyWebBundle", function() { - const tns = { - "flyweb-button.label": "FlyWeb", - "flyweb-button.tooltiptext": "Discover nearby FlyWeb services", - "flyweb-items-empty": "There are no FlyWeb services currently nearby" - }; - return { - GetStringFromName(name) { - return tns[name]; - } - }; -}); - -const FLYWEB_ENABLED_PREF = "dom.flyweb.enabled"; - -function install(aData, aReason) {} - -function uninstall(aData, aReason) {} - -function startup(aData, aReason) { - // Observe pref changes and enable/disable as necessary. - Services.prefs.addObserver(FLYWEB_ENABLED_PREF, prefObserver, false); - - // Only initialize if pref is enabled. - let enabled = Services.prefs.getBoolPref(FLYWEB_ENABLED_PREF); - if (enabled) { - FlyWebView.init(); - } -} - -function shutdown(aData, aReason) { - Services.prefs.removeObserver(FLYWEB_ENABLED_PREF, prefObserver); - - let enabled = Services.prefs.getBoolPref(FLYWEB_ENABLED_PREF); - if (enabled) { - FlyWebView.uninit(); - } -} - -// use enabled pref as a way for tests (e.g. test_contextmenu.html) to disable -// the addon when running. -function prefObserver(aSubject, aTopic, aData) { - let enabled = Services.prefs.getBoolPref(FLYWEB_ENABLED_PREF); - if (enabled) { - FlyWebView.init(); - } else { - FlyWebView.uninit(); - } -} - -let gDiscoveryManagerInstance; - -class DiscoveryManager { - constructor(aWindow) { - this._discoveryManager = new aWindow.FlyWebDiscoveryManager(); - } - - destroy() { - if (this._id) { - this.stop(); - } - - this._discoveryManager = null; - } - - start(callback) { - if (!this._id) { - this._id = this._discoveryManager.startDiscovery(this); - } - - this._callback = callback; - } - - stop() { - this._discoveryManager.stopDiscovery(this._id); - - this._id = null; - } - - pairWith(serviceId, callback) { - this._discoveryManager.pairWithService(serviceId, { - pairingSucceeded(service) { - callback(service); - }, - - pairingFailed(error) { - console.error("FlyWeb failed to pair with service " + serviceId, error); - } - }); - } - - onDiscoveredServicesChanged(services) { - if (!this._id || !this._callback) { - return; - } - - this._callback(services); - } -} - -const FlyWebPermissionPromptIntegration = (base) => ({ - __proto__: base, - createPermissionPrompt(type, request) { - if (type != "flyweb-publish-server") { - return super.createPermissionPrompt(...arguments); - } - - return { - __proto__: PermissionUI.PermissionPromptForRequestPrototype, - get request() { - return request; - }, - get permissionKey() { - return "flyweb-publish-server"; - }, - get popupOptions() { - return { - learnMoreURL: "https://flyweb.github.io", - popupIconURL: "chrome://flyweb/skin/icon-64.png", - }; - }, - get notificationID() { - return "flyweb-publish-server"; - }, - get anchorID() { - const kAnchorID = "flyweb-publish-server-notification-icon"; - let chromeDoc = this.browser.ownerDocument; - let anchor = chromeDoc.getElementById(kAnchorID); - if (!anchor) { - let notificationPopupBox = - chromeDoc.getElementById("notification-popup-box"); - let notificationIcon = chromeDoc.createElement("image"); - notificationIcon.id = kAnchorID; - notificationIcon.setAttribute("src", - "chrome://flyweb/skin/icon-64.png"); - notificationIcon.classList.add("notification-anchor-icon"); - notificationIcon.setAttribute("role", "button"); - notificationIcon.setAttribute("aria-label", - "View the publish-server request"); - notificationIcon.style.filter = - "url('chrome://browser/skin/filters.svg#fill')"; - notificationIcon.style.fill = "currentcolor"; - notificationIcon.style.opacity = "0.4"; - notificationPopupBox.appendChild(notificationIcon); - } - - return kAnchorID; - }, - get message() { - return "Would you like to let this site start a server accessible " + - "to nearby devices and people?"; - }, - get promptActions() { - return [{ - label: "Allow Server", - accessKey: "A", - action: Ci.nsIPermissionManager.ALLOW_ACTION, - expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, - }, { - label: "Block Server", - accessKey: "B", - action: Ci.nsIPermissionManager.DENY_ACTION, - expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, - }]; - }, - }; - }, -}); - -let FlyWebView = { - init() { - // Create widget and add it to the menu panel. - CustomizableUI.createWidget({ - id: "flyweb-button", - type: "view", - viewId: "flyweb-panel", - label: gFlyWebBundle.GetStringFromName("flyweb-button.label"), - tooltiptext: gFlyWebBundle.GetStringFromName("flyweb-button.tooltiptext"), - - onBeforeCreated(aDocument) { - let panel = aDocument.createElement("panelview"); - panel.id = "flyweb-panel"; - panel.setAttribute("class", "PanelUI-subView"); - panel.setAttribute("flex", "1"); - - let label = aDocument.createElement("label"); - label.setAttribute("class", "panel-subview-header"); - label.setAttribute("value", gFlyWebBundle.GetStringFromName("flyweb-button.label")); - - let empty = aDocument.createElement("description"); - empty.id = "flyweb-items-empty"; - empty.setAttribute("mousethrough", "always"); - empty.textContent = gFlyWebBundle.GetStringFromName("flyweb-items-empty"); - - let items = aDocument.createElement("vbox"); - items.id = "flyweb-items"; - items.setAttribute("class", "panel-subview-body"); - - panel.appendChild(label); - panel.appendChild(empty); - panel.appendChild(items); - - panel.addEventListener("command", this); - - aDocument.getElementById("PanelUI-multiView").appendChild(panel); - - this._sheetURI = Services.io.newURI("chrome://flyweb/skin/flyweb.css", null, null); - aDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils).loadSheet(this._sheetURI, 1); - }, - - onDestroyed(aDocument) { - aDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIDOMWindowUtils).removeSheet(this._sheetURI, 1); - }, - - onViewShowing(aEvent) { - let doc = aEvent.target.ownerDocument; - - let items = doc.getElementById("flyweb-items"); - let empty = doc.getElementById("flyweb-items-empty"); - - if (!gDiscoveryManagerInstance) { - gDiscoveryManagerInstance = new DiscoveryManager(doc.defaultView); - } - - gDiscoveryManagerInstance.start((services) => { - while (items.firstChild) { - items.firstChild.remove(); - } - - let fragment = doc.createDocumentFragment(); - - for (let service of services) { - let button = doc.createElement("toolbarbutton"); - button.setAttribute("class", "subviewbutton cui-withicon"); - button.setAttribute("label", service.displayName); - button.setAttribute("data-service-id", service.serviceId); - fragment.appendChild(button); - } - - items.appendChild(fragment); - - empty.hidden = services.length > 0; - }); - }, - - onViewHiding(aEvent) { - gDiscoveryManagerInstance.stop(); - }, - - handleEvent(aEvent) { - if (aEvent.type === "command") { - let serviceId = aEvent.target.getAttribute("data-service-id"); - gDiscoveryManagerInstance.pairWith(serviceId, (service) => { - aEvent.view.openUILinkIn(service.uiUrl, "tab"); - }); - } - } - }); - - Integration.contentPermission - .register(FlyWebPermissionPromptIntegration); - }, - - uninit() { - CustomizableUI.destroyWidget("flyweb-button"); - - if (gDiscoveryManagerInstance) { - gDiscoveryManagerInstance.destroy(); - gDiscoveryManagerInstance = null; - } - - Integration.contentPermission - .unregister(FlyWebPermissionPromptIntegration); - } -}; diff --git a/browser/extensions/flyweb/install.rdf.in b/browser/extensions/flyweb/install.rdf.in deleted file mode 100644 index 17f746f9b..000000000 --- a/browser/extensions/flyweb/install.rdf.in +++ /dev/null @@ -1,32 +0,0 @@ - - - -#filter substitution - - - - - flyweb@mozilla.org - 1.0.0 - 2 - true - true - - - - - {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @MOZ_APP_VERSION@ - @MOZ_APP_MAXVERSION@ - - - - - FlyWeb - Discover nearby services in the browser - - diff --git a/browser/extensions/flyweb/jar.mn b/browser/extensions/flyweb/jar.mn deleted file mode 100644 index 8eed2135b..000000000 --- a/browser/extensions/flyweb/jar.mn +++ /dev/null @@ -1,10 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -[features/flyweb@mozilla.org] chrome.jar: -% skin flyweb classic/1.0 %skin/linux/ -% skin flyweb classic/1.0 %skin/osx/ os=Darwin -% skin flyweb classic/1.0 %skin/windows/ os=WINNT -% skin flyweb-shared classic/1.0 %skin/shared/ - skin/ (skin/*) diff --git a/browser/extensions/flyweb/moz.build b/browser/extensions/flyweb/moz.build deleted file mode 100644 index 7f71bfb55..000000000 --- a/browser/extensions/flyweb/moz.build +++ /dev/null @@ -1,18 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] -DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] - -FINAL_TARGET_FILES.features['flyweb@mozilla.org'] += [ - 'bootstrap.js' -] - -FINAL_TARGET_PP_FILES.features['flyweb@mozilla.org'] += [ - 'install.rdf.in' -] - -JAR_MANIFESTS += ['jar.mn'] diff --git a/browser/extensions/flyweb/skin/flyweb-icon.svg b/browser/extensions/flyweb/skin/flyweb-icon.svg deleted file mode 100644 index 1b247e645..000000000 --- a/browser/extensions/flyweb/skin/flyweb-icon.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browser/extensions/flyweb/skin/linux/flyweb.css b/browser/extensions/flyweb/skin/linux/flyweb.css deleted file mode 100644 index c549248da..000000000 --- a/browser/extensions/flyweb/skin/linux/flyweb.css +++ /dev/null @@ -1,5 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -@import url("chrome://flyweb-shared/skin/flyweb.css"); diff --git a/browser/extensions/flyweb/skin/linux/icon-16.png b/browser/extensions/flyweb/skin/linux/icon-16.png deleted file mode 100644 index 3a6c2e43a..000000000 Binary files a/browser/extensions/flyweb/skin/linux/icon-16.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/linux/icon-32-anchored.png b/browser/extensions/flyweb/skin/linux/icon-32-anchored.png deleted file mode 100644 index b05590dda..000000000 Binary files a/browser/extensions/flyweb/skin/linux/icon-32-anchored.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/linux/icon-32.png b/browser/extensions/flyweb/skin/linux/icon-32.png deleted file mode 100644 index a04ec20b9..000000000 Binary files a/browser/extensions/flyweb/skin/linux/icon-32.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/linux/icon-64-anchored.png b/browser/extensions/flyweb/skin/linux/icon-64-anchored.png deleted file mode 100644 index b617b9208..000000000 Binary files a/browser/extensions/flyweb/skin/linux/icon-64-anchored.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/linux/icon-64.png b/browser/extensions/flyweb/skin/linux/icon-64.png deleted file mode 100644 index be8ece467..000000000 Binary files a/browser/extensions/flyweb/skin/linux/icon-64.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/osx/flyweb.css b/browser/extensions/flyweb/skin/osx/flyweb.css deleted file mode 100644 index c549248da..000000000 --- a/browser/extensions/flyweb/skin/osx/flyweb.css +++ /dev/null @@ -1,5 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -@import url("chrome://flyweb-shared/skin/flyweb.css"); diff --git a/browser/extensions/flyweb/skin/osx/icon-16.png b/browser/extensions/flyweb/skin/osx/icon-16.png deleted file mode 100644 index 7c87435a4..000000000 Binary files a/browser/extensions/flyweb/skin/osx/icon-16.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/osx/icon-32-anchored.png b/browser/extensions/flyweb/skin/osx/icon-32-anchored.png deleted file mode 100644 index b05590dda..000000000 Binary files a/browser/extensions/flyweb/skin/osx/icon-32-anchored.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/osx/icon-32.png b/browser/extensions/flyweb/skin/osx/icon-32.png deleted file mode 100644 index 5b0140ffa..000000000 Binary files a/browser/extensions/flyweb/skin/osx/icon-32.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/osx/icon-64-anchored.png b/browser/extensions/flyweb/skin/osx/icon-64-anchored.png deleted file mode 100644 index b617b9208..000000000 Binary files a/browser/extensions/flyweb/skin/osx/icon-64-anchored.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/osx/icon-64.png b/browser/extensions/flyweb/skin/osx/icon-64.png deleted file mode 100644 index eb67c29ec..000000000 Binary files a/browser/extensions/flyweb/skin/osx/icon-64.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/shared/flyweb.css b/browser/extensions/flyweb/skin/shared/flyweb.css deleted file mode 100644 index acc8a743d..000000000 --- a/browser/extensions/flyweb/skin/shared/flyweb.css +++ /dev/null @@ -1,54 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#flyweb-panel { - width: 20em; -} - -#flyweb-items-empty { - box-sizing: border-box; - color: GrayText; - padding: 10px 20px; - text-align: center; -} - -#flyweb-button { - list-style-image: url("chrome://flyweb/skin/icon-16.png"); -} - -#flyweb-button[cui-areatype="menu-panel"], -toolbarpaletteitem[place="palette"] > #flyweb-button { - list-style-image: url("chrome://flyweb/skin/icon-32.png"); -} - -#flyweb-button[cui-areatype="menu-panel"][panel-multiview-anchor="true"] { - list-style-image: url("chrome://flyweb/skin/icon-32-anchored.png"); -} - -#flyweb-items > toolbarbutton { - list-style-image: url("chrome://flyweb/skin/icon-16.png"); -} - -@media (min-resolution: 2dppx) { - #flyweb-button { - list-style-image: url("chrome://flyweb/skin/icon-32.png"); - } - - #flyweb-button[cui-areatype="menu-panel"], - toolbarpaletteitem[place="palette"] > #flyweb-button { - list-style-image: url("chrome://flyweb/skin/icon-64.png"); - } - - #flyweb-button[cui-areatype="menu-panel"][panel-multiview-anchor="true"] { - list-style-image: url("chrome://flyweb/skin/icon-64-anchored.png"); - } - - #flyweb-items > toolbarbutton { - list-style-image: url("chrome://flyweb/skin/icon-32.png"); - } - - #flyweb-items > toolbarbutton > .toolbarbutton-icon { - width: 16px; - } -} diff --git a/browser/extensions/flyweb/skin/windows/flyweb.css b/browser/extensions/flyweb/skin/windows/flyweb.css deleted file mode 100644 index c549248da..000000000 --- a/browser/extensions/flyweb/skin/windows/flyweb.css +++ /dev/null @@ -1,5 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -@import url("chrome://flyweb-shared/skin/flyweb.css"); diff --git a/browser/extensions/flyweb/skin/windows/icon-16.png b/browser/extensions/flyweb/skin/windows/icon-16.png deleted file mode 100644 index 3a6c2e43a..000000000 Binary files a/browser/extensions/flyweb/skin/windows/icon-16.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/windows/icon-32-anchored.png b/browser/extensions/flyweb/skin/windows/icon-32-anchored.png deleted file mode 100644 index b05590dda..000000000 Binary files a/browser/extensions/flyweb/skin/windows/icon-32-anchored.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/windows/icon-32.png b/browser/extensions/flyweb/skin/windows/icon-32.png deleted file mode 100644 index a04ec20b9..000000000 Binary files a/browser/extensions/flyweb/skin/windows/icon-32.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/windows/icon-64-anchored.png b/browser/extensions/flyweb/skin/windows/icon-64-anchored.png deleted file mode 100644 index b617b9208..000000000 Binary files a/browser/extensions/flyweb/skin/windows/icon-64-anchored.png and /dev/null differ diff --git a/browser/extensions/flyweb/skin/windows/icon-64.png b/browser/extensions/flyweb/skin/windows/icon-64.png deleted file mode 100644 index be8ece467..000000000 Binary files a/browser/extensions/flyweb/skin/windows/icon-64.png and /dev/null differ diff --git a/browser/extensions/formautofill/.eslintrc.js b/browser/extensions/formautofill/.eslintrc.js deleted file mode 100644 index ec89029e5..000000000 --- a/browser/extensions/formautofill/.eslintrc.js +++ /dev/null @@ -1,474 +0,0 @@ -"use strict"; - -module.exports = { // eslint-disable-line no-undef - "extends": "../../.eslintrc.js", - - "globals": { - "Components": true, - "dump": true, - "TextDecoder": false, - "TextEncoder": false, - }, - - "rules": { - // Rules from the mozilla plugin - "mozilla/balanced-listeners": "error", - "mozilla/no-aArgs": "warn", - "mozilla/no-cpows-in-tests": "warn", - "mozilla/var-only-at-top-level": "warn", - - "valid-jsdoc": ["error", { - "prefer": { - "return": "returns", - }, - "preferType": { - "Boolean": "boolean", - "Number": "number", - "String": "string", - "bool": "boolean", - }, - "requireParamDescription": false, - "requireReturn": false, - "requireReturnDescription": false, - }], - - // Braces only needed for multi-line arrow function blocks - // "arrow-body-style": ["error", "as-needed"], - - // Require spacing around => - "arrow-spacing": "error", - - // Always require spacing around a single line block - "block-spacing": "warn", - - // Forbid spaces inside the square brackets of array literals. - "array-bracket-spacing": ["error", "never"], - - // Forbid spaces inside the curly brackets of object literals. - "object-curly-spacing": ["error", "never"], - - // No space padding in parentheses - "space-in-parens": ["error", "never"], - - // Enforce one true brace style (opening brace on the same line) and avoid - // start and end braces on the same line. - "brace-style": ["error", "1tbs", {"allowSingleLine": true}], - - // No space before always a space after a comma - "comma-spacing": ["error", {"before": false, "after": true}], - - // Commas at the end of the line not the start - "comma-style": "error", - - // Don't require spaces around computed properties - "computed-property-spacing": ["warn", "never"], - - // Functions are not required to consistently return something or nothing - "consistent-return": "off", - - // Require braces around blocks that start a new line - "curly": ["error", "all"], - - // Always require a trailing EOL - "eol-last": "error", - - // Require function* name() - "generator-star-spacing": ["error", {"before": false, "after": true}], - - // Two space indent - "indent": ["error", 2, {"SwitchCase": 1}], - - // Space after colon not before in property declarations - "key-spacing": ["error", {"beforeColon": false, "afterColon": true, "mode": "minimum"}], - - // Require spaces before and after finally, catch, etc. - "keyword-spacing": "error", - - // Unix linebreaks - "linebreak-style": ["error", "unix"], - - // Always require parenthesis for new calls - "new-parens": "error", - - // Use [] instead of Array() - "no-array-constructor": "error", - - // No duplicate arguments in function declarations - "no-dupe-args": "error", - - // No duplicate keys in object declarations - "no-dupe-keys": "error", - - // No duplicate cases in switch statements - "no-duplicate-case": "error", - - // If an if block ends with a return no need for an else block - // "no-else-return": "error", - - // Disallow empty statements. This will report an error for: - // try { something(); } catch (e) {} - // but will not report it for: - // try { something(); } catch (e) { /* Silencing the error because ...*/ } - // which is a valid use case. - "no-empty": "error", - - // No empty character classes in regex - "no-empty-character-class": "error", - - // Disallow empty destructuring - "no-empty-pattern": "error", - - // No assiging to exception variable - "no-ex-assign": "error", - - // No using !! where casting to boolean is already happening - "no-extra-boolean-cast": "warn", - - // No double semicolon - "no-extra-semi": "error", - - // No overwriting defined functions - "no-func-assign": "error", - - // No invalid regular expresions - "no-invalid-regexp": "error", - - // No odd whitespace characters - "no-irregular-whitespace": "error", - - // No single if block inside an else block - "no-lonely-if": "warn", - - // No mixing spaces and tabs in indent - "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], - - // Disallow use of multiple spaces (sometimes used to align const values, - // array or object items, etc.). It's hard to maintain and doesn't add that - // much benefit. - "no-multi-spaces": "warn", - - // No reassigning native JS objects - "no-native-reassign": "error", - - // No (!foo in bar) - "no-negated-in-lhs": "error", - - // Nested ternary statements are confusing - "no-nested-ternary": "error", - - // Use {} instead of new Object() - "no-new-object": "error", - - // No Math() or JSON() - "no-obj-calls": "error", - - // No octal literals - "no-octal": "error", - - // No redeclaring variables - "no-redeclare": "error", - - // No unnecessary comparisons - "no-self-compare": "error", - - // No spaces between function name and parentheses - "no-spaced-func": "warn", - - // No trailing whitespace - "no-trailing-spaces": "error", - - // Error on newline where a semicolon is needed - "no-unexpected-multiline": "error", - - // No unreachable statements - "no-unreachable": "error", - - // No expressions where a statement is expected - "no-unused-expressions": "error", - - // No declaring variables that are never used - "no-unused-vars": ["error", {"args": "none", "varsIgnorePattern": "^(Cc|Ci|Cr|Cu|EXPORTED_SYMBOLS)$"}], - - // No using variables before defined - "no-use-before-define": "error", - - // No using with - "no-with": "error", - - // Always require semicolon at end of statement - "semi": ["error", "always"], - - // Require space before blocks - "space-before-blocks": "error", - - // Never use spaces before function parentheses - "space-before-function-paren": ["error", {"anonymous": "never", "named": "never"}], - - // Require spaces around operators, except for a|"off". - "space-infix-ops": ["error", {"int32Hint": true}], - - // ++ and -- should not need spacing - "space-unary-ops": ["warn", {"nonwords": false}], - - // No comparisons to NaN - "use-isnan": "error", - - // Only check typeof against valid results - "valid-typeof": "error", - - // Disallow using variables outside the blocks they are defined (especially - // since only let and const are used, see "no-var"). - "block-scoped-var": "error", - - // Allow trailing commas for easy list extension. Having them does not - // impair readability, but also not required either. - "comma-dangle": ["error", "always-multiline"], - - // Warn about cyclomatic complexity in functions. - "complexity": "warn", - - // Don't warn for inconsistent naming when capturing this (not so important - // with auto-binding fat arrow functions). - // "consistent-this": ["error", "self"], - - // Don't require a default case in switch statements. Avoid being forced to - // add a bogus default when you know all possible cases are handled. - "default-case": "off", - - // Enforce dots on the next line with property name. - "dot-location": ["error", "property"], - - // Encourage the use of dot notation whenever possible. - "dot-notation": "error", - - // Allow using == instead of ===, in the interest of landing something since - // the devtools codebase is split on convention here. - "eqeqeq": "off", - - // Don't require function expressions to have a name. - // This makes the code more verbose and hard to read. Our engine already - // does a fantastic job assigning a name to the function, which includes - // the enclosing function name, and worst case you have a line number that - // you can just look up. - "func-names": "off", - - // Allow use of function declarations and expressions. - "func-style": "off", - - // Don't enforce the maximum depth that blocks can be nested. The complexity - // rule is a better rule to check this. - "max-depth": "off", - - // Maximum length of a line. - // Disabled because we exceed this in too many places. - "max-len": ["off", 80], - - // Maximum depth callbacks can be nested. - "max-nested-callbacks": ["error", 4], - - // Don't limit the number of parameters that can be used in a function. - "max-params": "off", - - // Don't limit the maximum number of statement allowed in a function. We - // already have the complexity rule that's a better measurement. - "max-statements": "off", - - // Don't require a capital letter for constructors, only check if all new - // operators are followed by a capital letter. Don't warn when capitalized - // functions are used without the new operator. - "new-cap": ["off", {"capIsNew": false}], - - // Allow use of bitwise operators. - "no-bitwise": "off", - - // Disallow use of arguments.caller or arguments.callee. - "no-caller": "error", - - // Disallow the catch clause parameter name being the same as a variable in - // the outer scope, to avoid confusion. - "no-catch-shadow": "off", - - // Disallow assignment in conditional expressions. - "no-cond-assign": "error", - - // Disallow using the console API. - "no-console": "error", - - // Allow using constant expressions in conditions like while (true) - "no-constant-condition": "off", - - // Allow use of the continue statement. - "no-continue": "off", - - // Disallow control characters in regular expressions. - "no-control-regex": "error", - - // Disallow use of debugger. - "no-debugger": "error", - - // Disallow deletion of variables (deleting properties is fine). - "no-delete-var": "error", - - // Allow division operators explicitly at beginning of regular expression. - "no-div-regex": "off", - - // Disallow use of eval(). We have other APIs to evaluate code in content. - "no-eval": "error", - - // Disallow adding to native types - "no-extend-native": "error", - - // Disallow unnecessary function binding. - "no-extra-bind": "error", - - // Allow unnecessary parentheses, as they may make the code more readable. - "no-extra-parens": "off", - - // Disallow fallthrough of case statements, except if there is a comment. - "no-fallthrough": "error", - - // Allow the use of leading or trailing decimal points in numeric literals. - "no-floating-decimal": "off", - - // Allow comments inline after code. - "no-inline-comments": "off", - - // Disallow use of labels for anything other then loops and switches. - "no-labels": ["error", {"allowLoop": true}], - - // Disallow use of multiline strings (use template strings instead). - "no-multi-str": "warn", - - // Disallow multiple empty lines. - "no-multiple-empty-lines": ["warn", {"max": 2}], - - // Allow reassignment of function parameters. - "no-param-reassign": "off", - - // Allow string concatenation with __dirname and __filename (not a node env). - "no-path-concat": "off", - - // Allow use of unary operators, ++ and --. - "no-plusplus": "off", - - // Allow using process.env (not a node environment). - "no-process-env": "off", - - // Allow using process.exit (not a node environment). - "no-process-exit": "off", - - // Disallow usage of __proto__ property. - "no-proto": "error", - - // Disallow multiple spaces in a regular expression literal. - "no-regex-spaces": "error", - - // Allow reserved words being used as object literal keys. - "no-reserved-keys": "off", - - // Don't restrict usage of specified node modules (not a node environment). - "no-restricted-modules": "off", - - // Disallow use of assignment in return statement. It is preferable for a - // single line of code to have only one easily predictable effect. - "no-return-assign": "error", - - // Don't warn about declaration of variables already declared in the outer scope. - "no-shadow": "off", - - // Disallow shadowing of names such as arguments. - "no-shadow-restricted-names": "error", - - // Allow use of synchronous methods (not a node environment). - "no-sync": "off", - - // Allow the use of ternary operators. - "no-ternary": "off", - - // Disallow throwing literals (eg. throw "error" instead of - // throw new Error("error")). - "no-throw-literal": "error", - - // Disallow use of undeclared variables unless mentioned in a /* global */ - // block. Note that globals from head.js are automatically imported in tests - // by the import-headjs-globals rule form the mozilla eslint plugin. - "no-undef": "error", - - // Allow dangling underscores in identifiers (for privates). - "no-underscore-dangle": "off", - - // Allow use of undefined variable. - "no-undefined": "off", - - // Disallow the use of Boolean literals in conditional expressions. - "no-unneeded-ternary": "error", - - // We use var-only-at-top-level instead of no-var as we allow top level - // vars. - "no-var": "off", - - // Allow using TODO/FIXME comments. - "no-warning-comments": "off", - - // Don't require method and property shorthand syntax for object literals. - // We use this in the code a lot, but not consistently, and this seems more - // like something to check at code review time. - "object-shorthand": "off", - - // Allow more than one variable declaration per function. - "one-var": "off", - - // Disallow padding within blocks. - "padded-blocks": ["warn", "never"], - - // Don't require quotes around object literal property names. - "quote-props": "off", - - // Double quotes should be used. - "quotes": ["warn", "double", {"avoidEscape": true, "allowTemplateLiterals": true}], - - // Require use of the second argument for parseInt(). - "radix": "error", - - // Enforce spacing after semicolons. - "semi-spacing": ["error", {"before": false, "after": true}], - - // Don't require to sort variables within the same declaration block. - // Anyway, one-var is disabled. - "sort-vars": "off", - - // Require a space immediately following the // in a line comment. - "spaced-comment": ["error", "always"], - - // Require "use strict" to be defined globally in the script. - "strict": ["error", "global"], - - // Allow vars to be declared anywhere in the scope. - "vars-on-top": "off", - - // Don't require immediate function invocation to be wrapped in parentheses. - "wrap-iife": "off", - - // Don't require regex literals to be wrapped in parentheses (which - // supposedly prevent them from being mistaken for division operators). - "wrap-regex": "off", - - // Disallow Yoda conditions (where literal value comes first). - "yoda": "error", - - // disallow use of eval()-like methods - "no-implied-eval": "error", - - // Disallow function or variable declarations in nested blocks - "no-inner-declarations": "error", - - // Disallow usage of __iterator__ property - "no-iterator": "error", - - // Disallow labels that share a name with a variable - "no-label-var": "error", - - // Disallow creating new instances of String, Number, and Boolean - "no-new-wrappers": "error", - }, -}; diff --git a/browser/extensions/formautofill/bootstrap.js b/browser/extensions/formautofill/bootstrap.js deleted file mode 100644 index 0b3f355bd..000000000 --- a/browser/extensions/formautofill/bootstrap.js +++ /dev/null @@ -1,12 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -/* exported startup, shutdown, install, uninstall */ - -function startup() {} -function shutdown() {} -function install() {} -function uninstall() {} diff --git a/browser/extensions/formautofill/content/FormAutofillContent.jsm b/browser/extensions/formautofill/content/FormAutofillContent.jsm deleted file mode 100644 index bde397580..000000000 --- a/browser/extensions/formautofill/content/FormAutofillContent.jsm +++ /dev/null @@ -1,134 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * Implements a service used by DOM content to request Form Autofill. - */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -/** - * Handles profile autofill for a DOM Form element. - * @param {HTMLFormElement} form Form that need to be auto filled - */ -function FormAutofillHandler(form) { - this.form = form; - this.fieldDetails = []; -} - -FormAutofillHandler.prototype = { - /** - * DOM Form element to which this object is attached. - */ - form: null, - - /** - * Array of collected data about relevant form fields. Each item is an object - * storing the identifying details of the field and a reference to the - * originally associated element from the form. - * - * The "section", "addressType", "contactType", and "fieldName" values are - * used to identify the exact field when the serializable data is received - * from the backend. There cannot be multiple fields which have - * the same exact combination of these values. - * - * A direct reference to the associated element cannot be sent to the user - * interface because processing may be done in the parent process. - */ - fieldDetails: null, - - /** - * Returns information from the form about fields that can be autofilled, and - * populates the fieldDetails array on this object accordingly. - * - * @returns {Array} Serializable data structure that can be sent to the user - * interface, or null if the operation failed because the constraints - * on the allowed fields were not honored. - */ - collectFormFields() { - let autofillData = []; - - for (let element of this.form.elements) { - // Query the interface and exclude elements that cannot be autocompleted. - if (!(element instanceof Ci.nsIDOMHTMLInputElement)) { - continue; - } - - // Exclude elements to which no autocomplete field has been assigned. - let info = element.getAutocompleteInfo(); - if (!info.fieldName || ["on", "off"].includes(info.fieldName)) { - continue; - } - - // Store the association between the field metadata and the element. - if (this.fieldDetails.some(f => f.section == info.section && - f.addressType == info.addressType && - f.contactType == info.contactType && - f.fieldName == info.fieldName)) { - // A field with the same identifier already exists. - return null; - } - - let inputFormat = { - section: info.section, - addressType: info.addressType, - contactType: info.contactType, - fieldName: info.fieldName, - }; - // Clone the inputFormat for caching the fields and elements together - let formatWithElement = Object.assign({}, inputFormat); - - inputFormat.index = autofillData.length; - autofillData.push(inputFormat); - - formatWithElement.element = element; - this.fieldDetails.push(formatWithElement); - } - - return autofillData; - }, - - /** - * Processes form fields that can be autofilled, and populates them with the - * data provided by backend. - * - * @param {Array} autofillResult - * Data returned by the user interface. - * [{ - * section: Value originally provided to the user interface. - * addressType: Value originally provided to the user interface. - * contactType: Value originally provided to the user interface. - * fieldName: Value originally provided to the user interface. - * value: String with which the field should be updated. - * index: Index to match the input in fieldDetails - * }], - * } - */ - autofillFormFields(autofillResult) { - for (let field of autofillResult) { - // Get the field details, if it was processed by the user interface. - let fieldDetail = this.fieldDetails[field.index]; - - // Avoid the invalid value set - if (!fieldDetail || !field.value) { - continue; - } - - let info = fieldDetail.element.getAutocompleteInfo(); - if (field.section != info.section || - field.addressType != info.addressType || - field.contactType != info.contactType || - field.fieldName != info.fieldName) { - Cu.reportError("Autocomplete tokens mismatched"); - continue; - } - - fieldDetail.element.setUserInput(field.value); - } - }, -}; - -this.EXPORTED_SYMBOLS = ["FormAutofillHandler"]; diff --git a/browser/extensions/formautofill/content/FormAutofillParent.jsm b/browser/extensions/formautofill/content/FormAutofillParent.jsm deleted file mode 100644 index bdfe0f478..000000000 --- a/browser/extensions/formautofill/content/FormAutofillParent.jsm +++ /dev/null @@ -1,173 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * Implements a service used to access storage and communicate with content. - * - * A "fields" array is used to communicate with FormAutofillContent. Each item - * represents a single input field in the content page as well as its - * @autocomplete properties. The schema is as below. Please refer to - * FormAutofillContent.jsm for more details. - * - * [ - * { - * section, - * addressType, - * contactType, - * fieldName, - * value, - * index - * }, - * { - * // ... - * } - * ] - */ - -/* exported FormAutofillParent */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ProfileStorage", - "resource://formautofill/ProfileStorage.jsm"); - -const PROFILE_JSON_FILE_NAME = "autofill-profiles.json"; - -let FormAutofillParent = { - _profileStore: null, - - /** - * Initializes ProfileStorage and registers the message handler. - */ - init: function() { - let storePath = - OS.Path.join(OS.Constants.Path.profileDir, PROFILE_JSON_FILE_NAME); - - this._profileStore = new ProfileStorage(storePath); - this._profileStore.initialize(); - - let mm = Cc["@mozilla.org/globalmessagemanager;1"] - .getService(Ci.nsIMessageListenerManager); - mm.addMessageListener("FormAutofill:PopulateFieldValues", this); - }, - - /** - * Handles the message coming from FormAutofillContent. - * - * @param {string} message.name The name of the message. - * @param {object} message.data The data of the message. - * @param {nsIFrameMessageManager} message.target Caller's message manager. - */ - receiveMessage: function({name, data, target}) { - switch (name) { - case "FormAutofill:PopulateFieldValues": - this._populateFieldValues(data, target); - break; - } - }, - - /** - * Returns the instance of ProfileStorage. To avoid syncing issues, anyone - * who needs to access the profile should request the instance by this instead - * of creating a new one. - * - * @returns {ProfileStorage} - */ - getProfileStore: function() { - return this._profileStore; - }, - - /** - * Uninitializes FormAutofillParent. This is for testing only. - * - * @private - */ - _uninit: function() { - if (this._profileStore) { - this._profileStore._saveImmediately(); - this._profileStore = null; - } - - let mm = Cc["@mozilla.org/globalmessagemanager;1"] - .getService(Ci.nsIMessageListenerManager); - mm.removeMessageListener("FormAutofill:PopulateFieldValues", this); - }, - - /** - * Populates the field values and notifies content to fill in. Exception will - * be thrown if there's no matching profile. - * - * @private - * @param {string} data.guid - * Indicates which profile to populate - * @param {Fields} data.fields - * The "fields" array collected from content. - * @param {nsIFrameMessageManager} target - * Content's message manager. - */ - _populateFieldValues({guid, fields}, target) { - this._profileStore.notifyUsed(guid); - this._fillInFields(this._profileStore.get(guid), fields); - target.sendAsyncMessage("FormAutofill:fillForm", {fields}); - }, - - /** - * Transforms a word with hyphen into camel case. - * (e.g. transforms "address-type" into "addressType".) - * - * @private - * @param {string} str The original string with hyphen. - * @returns {string} The camel-cased output string. - */ - _camelCase(str) { - return str.toLowerCase().replace(/-([a-z])/g, s => s[1].toUpperCase()); - }, - - /** - * Get the corresponding value from the specified profile according to a valid - * @autocomplete field name. - * - * Note that the field name doesn't need to match the property name defined in - * Profile object. This method can transform the raw data to fulfill it. (e.g. - * inputting "country-name" as "fieldName" will get a full name transformed - * from the country code that is recorded in "country" field.) - * - * @private - * @param {Profile} profile The specified profile. - * @param {string} fieldName A valid @autocomplete field name. - * @returns {string} The corresponding value. Returns "undefined" if there's - * no matching field. - */ - _getDataByFieldName(profile, fieldName) { - let key = this._camelCase(fieldName); - - // TODO: Transform the raw profile data to fulfill "fieldName" here. - - return profile[key]; - }, - - /** - * Fills in the "fields" array by the specified profile. - * - * @private - * @param {Profile} profile The specified profile to fill in. - * @param {Fields} fields The "fields" array collected from content. - */ - _fillInFields(profile, fields) { - for (let field of fields) { - let value = this._getDataByFieldName(profile, field.fieldName); - if (value !== undefined) { - field.value = value; - } - } - }, -}; - -this.EXPORTED_SYMBOLS = ["FormAutofillParent"]; diff --git a/browser/extensions/formautofill/content/ProfileStorage.jsm b/browser/extensions/formautofill/content/ProfileStorage.jsm deleted file mode 100644 index 843177d4e..000000000 --- a/browser/extensions/formautofill/content/ProfileStorage.jsm +++ /dev/null @@ -1,251 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * Implements an interface of the storage of Form Autofill. - * - * The data is stored in JSON format, without indentation, using UTF-8 encoding. - * With indentation applied, the file would look like this: - * - * { - * version: 1, - * profiles: [ - * { - * guid, // 12 character... - * - * // profile - * organization, // Company - * streetAddress, // (Multiline) - * addressLevel2, // City/Town - * addressLevel1, // Province (Standardized code if possible) - * postalCode, - * country, // ISO 3166 - * tel, - * email, - * - * // metadata - * timeCreated, // in ms - * timeLastUsed, // in ms - * timeLastModified, // in ms - * timesUsed - * }, - * { - * // ... - * } - * ] - * } - */ - -"use strict"; - -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "JSONFile", - "resource://gre/modules/JSONFile.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator", - "@mozilla.org/uuid-generator;1", - "nsIUUIDGenerator"); - -const SCHEMA_VERSION = 1; - -// Name-related fields will be handled in follow-up bugs due to the complexity. -const VALID_FIELDS = [ - "organization", - "streetAddress", - "addressLevel2", - "addressLevel1", - "postalCode", - "country", - "tel", - "email", -]; - -function ProfileStorage(path) { - this._path = path; -} - -ProfileStorage.prototype = { - /** - * Loads the profile data from file to memory. - * - * @returns {Promise} - * @resolves When the operation finished successfully. - * @rejects JavaScript exception. - */ - initialize() { - this._store = new JSONFile({ - path: this._path, - dataPostProcessor: this._dataPostProcessor.bind(this), - }); - return this._store.load(); - }, - - /** - * Adds a new profile. - * - * @param {Profile} profile - * The new profile for saving. - */ - add(profile) { - this._store.ensureDataReady(); - - let profileToSave = this._normalizeProfile(profile); - - profileToSave.guid = gUUIDGenerator.generateUUID().toString() - .replace(/[{}-]/g, "").substring(0, 12); - - // Metadata - let now = Date.now(); - profileToSave.timeCreated = now; - profileToSave.timeLastModified = now; - profileToSave.timeLastUsed = 0; - profileToSave.timesUsed = 0; - - this._store.data.profiles.push(profileToSave); - - this._store.saveSoon(); - }, - - /** - * Update the specified profile. - * - * @param {string} guid - * Indicates which profile to update. - * @param {Profile} profile - * The new profile used to overwrite the old one. - */ - update(guid, profile) { - this._store.ensureDataReady(); - - let profileFound = this._findByGUID(guid); - if (!profileFound) { - throw new Error("No matching profile."); - } - - let profileToUpdate = this._normalizeProfile(profile); - for (let field of VALID_FIELDS) { - if (profileToUpdate[field] !== undefined) { - profileFound[field] = profileToUpdate[field]; - } else { - delete profileFound[field]; - } - } - - profileFound.timeLastModified = Date.now(); - - this._store.saveSoon(); - }, - - /** - * Notifies the stroage of the use of the specified profile, so we can update - * the metadata accordingly. - * - * @param {string} guid - * Indicates which profile to be notified. - */ - notifyUsed(guid) { - this._store.ensureDataReady(); - - let profileFound = this._findByGUID(guid); - if (!profileFound) { - throw new Error("No matching profile."); - } - - profileFound.timesUsed++; - profileFound.timeLastUsed = Date.now(); - - this._store.saveSoon(); - }, - - /** - * Removes the specified profile. No error occurs if the profile isn't found. - * - * @param {string} guid - * Indicates which profile to remove. - */ - remove(guid) { - this._store.ensureDataReady(); - - this._store.data.profiles = - this._store.data.profiles.filter(profile => profile.guid != guid); - this._store.saveSoon(); - }, - - /** - * Returns the profile with the specified GUID. - * - * @param {string} guid - * Indicates which profile to retrieve. - * @returns {Profile} - * A clone of the profile. - */ - get(guid) { - this._store.ensureDataReady(); - - let profileFound = this._findByGUID(guid); - if (!profileFound) { - throw new Error("No matching profile."); - } - - // Profile is cloned to avoid accidental modifications from outside. - return this._clone(profileFound); - }, - - /** - * Returns all profiles. - * - * @returns {Array.} - * An array containing clones of all profiles. - */ - getAll() { - this._store.ensureDataReady(); - - // Profiles are cloned to avoid accidental modifications from outside. - return this._store.data.profiles.map(this._clone); - }, - - _clone(profile) { - return Object.assign({}, profile); - }, - - _findByGUID(guid) { - return this._store.data.profiles.find(profile => profile.guid == guid); - }, - - _normalizeProfile(profile) { - let result = {}; - for (let key in profile) { - if (!VALID_FIELDS.includes(key)) { - throw new Error(`"${key}" is not a valid field.`); - } - if (typeof profile[key] !== "string" && - typeof profile[key] !== "number") { - throw new Error(`"${key}" contains invalid data type.`); - } - - result[key] = profile[key]; - } - return result; - }, - - _dataPostProcessor(data) { - data.version = SCHEMA_VERSION; - if (!data.profiles) { - data.profiles = []; - } - return data; - }, - - // For test only. - _saveImmediately() { - return this._store._save(); - }, -}; - -this.EXPORTED_SYMBOLS = ["ProfileStorage"]; diff --git a/browser/extensions/formautofill/install.rdf.in b/browser/extensions/formautofill/install.rdf.in deleted file mode 100644 index 5e34051ba..000000000 --- a/browser/extensions/formautofill/install.rdf.in +++ /dev/null @@ -1,32 +0,0 @@ - - - -#filter substitution - - - - - formautofill@mozilla.org - 1.0 - 2 - true - true - - - - - {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @MOZ_APP_VERSION@ - @MOZ_APP_MAXVERSION@ - - - - - Form Autofill - Autofill forms with saved profiles - - diff --git a/browser/extensions/formautofill/jar.mn b/browser/extensions/formautofill/jar.mn deleted file mode 100644 index 0cba721ef..000000000 --- a/browser/extensions/formautofill/jar.mn +++ /dev/null @@ -1,7 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -[features/formautofill@mozilla.org] chrome.jar: -% resource formautofill %content/ - content/ (content/*) diff --git a/browser/extensions/formautofill/moz.build b/browser/extensions/formautofill/moz.build deleted file mode 100644 index abcc659ee..000000000 --- a/browser/extensions/formautofill/moz.build +++ /dev/null @@ -1,18 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] -DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] - -FINAL_TARGET_FILES.features['formautofill@mozilla.org'] += [ - 'bootstrap.js' -] - -FINAL_TARGET_PP_FILES.features['formautofill@mozilla.org'] += [ - 'install.rdf.in' -] - -JAR_MANIFESTS += ['jar.mn'] diff --git a/browser/extensions/moz.build b/browser/extensions/moz.build index 4f95704e6..69d6af6d6 100644 --- a/browser/extensions/moz.build +++ b/browser/extensions/moz.build @@ -5,16 +5,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. DIRS += [ -# 'aushelper', -# 'e10srollout', 'pdfjs', -# 'pocket', -# 'webcompat', ] -# Only include the following system add-ons if building Aurora or Nightly -if 'a' in CONFIG['GRE_MILESTONE']: - DIRS += [ - 'flyweb', - 'formautofill', - ] diff --git a/browser/extensions/pocket/bootstrap.js b/browser/extensions/pocket/bootstrap.js deleted file mode 100644 index c470eb8d3..000000000 --- a/browser/extensions/pocket/bootstrap.js +++ /dev/null @@ -1,511 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* 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/. */ - -const {classes: Cc, interfaces: Ci, utils: Cu, manager: Cm} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://services-common/utils.js"); -Cu.import("resource://gre/modules/Preferences.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Services", - "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow", - "resource:///modules/RecentWindow.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI", - "resource:///modules/CustomizableUI.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", - "resource://gre/modules/AddonManager.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", - "resource://gre/modules/ReaderMode.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Pocket", - "chrome://pocket/content/Pocket.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "AboutPocket", - "chrome://pocket/content/AboutPocket.jsm"); -XPCOMUtils.defineLazyGetter(this, "gPocketBundle", function() { - return Services.strings.createBundle("chrome://pocket/locale/pocket.properties"); -}); -XPCOMUtils.defineLazyGetter(this, "gPocketStyleURI", function() { - return Services.io.newURI("chrome://pocket/skin/pocket.css", null, null); -}); - -// Due to bug 1051238 frame scripts are cached forever, so we can't update them -// as a restartless add-on. The Math.random() is the work around for this. -const PROCESS_SCRIPT = "chrome://pocket/content/pocket-content-process.js?" + Math.random(); - -const PREF_BRANCH = "extensions.pocket."; -const PREFS = { - enabled: true, // bug 1229937, figure out ui tour support - api: "api.getpocket.com", - site: "getpocket.com", - oAuthConsumerKey: "40249-e88c401e1b1f2242d9e441c4" -}; - -function setDefaultPrefs() { - let branch = Services.prefs.getDefaultBranch(PREF_BRANCH); - for (let [key, val] of Object.entries(PREFS)) { - // If someone beat us to setting a default, don't overwrite it. This can - // happen if distribution.ini sets the default first. - if (branch.getPrefType(key) != branch.PREF_INVALID) - continue; - switch (typeof val) { - case "boolean": - branch.setBoolPref(key, val); - break; - case "number": - branch.setIntPref(key, val); - break; - case "string": - branch.setCharPref(key, val); - break; - } - } -} - -function createElementWithAttrs(document, type, attrs) { - let element = document.createElement(type); - Object.keys(attrs).forEach(function (attr) { - element.setAttribute(attr, attrs[attr]); - }) - return element; -} - -function CreatePocketWidget(reason) { - let id = "pocket-button" - let widget = CustomizableUI.getWidget(id); - // The widget is only null if we've created then destroyed the widget. - // Once we've actually called createWidget the provider will be set to - // PROVIDER_API. - if (widget && widget.provider == CustomizableUI.PROVIDER_API) - return; - // if upgrading from builtin version and the button was placed in ui, - // seenWidget will not be null - let seenWidget = CustomizableUI.getPlacementOfWidget("pocket-button", false, true); - let pocketButton = { - id: "pocket-button", - defaultArea: CustomizableUI.AREA_NAVBAR, - introducedInVersion: "pref", - type: "view", - tabSpecific: true, - viewId: "PanelUI-pocketView", - label: gPocketBundle.GetStringFromName("pocket-button.label"), - tooltiptext: gPocketBundle.GetStringFromName("pocket-button.tooltiptext"), - // Use forwarding functions here to avoid loading Pocket.jsm on startup: - onViewShowing: function() { - return Pocket.onPanelViewShowing.apply(this, arguments); - }, - onViewHiding: function() { - return Pocket.onPanelViewHiding.apply(this, arguments); - }, - onBeforeCreated: function(doc) { - // Bug 1223127,CUI should make this easier to do. - if (doc.getElementById("PanelUI-pocketView")) - return; - let view = doc.createElement("panelview"); - view.id = "PanelUI-pocketView"; - let panel = doc.createElement("vbox"); - panel.setAttribute("class", "panel-subview-body"); - view.appendChild(panel); - doc.getElementById("PanelUI-multiView").appendChild(view); - } - }; - - CustomizableUI.createWidget(pocketButton); - CustomizableUI.addListener(pocketButton); - // placed is null if location is palette - let placed = CustomizableUI.getPlacementOfWidget("pocket-button"); - - // a first time install will always have placed the button somewhere, and will - // not have a placement prior to creating the widget. Thus, !seenWidget && - // placed. - if (reason == ADDON_ENABLE && !seenWidget && placed) { - // initially place the button after the bookmarks button if it is in the UI - let widgets = CustomizableUI.getWidgetIdsInArea(CustomizableUI.AREA_NAVBAR); - let bmbtn = widgets.indexOf("bookmarks-menu-button"); - if (bmbtn > -1) { - CustomizableUI.moveWidgetWithinArea("pocket-button", bmbtn + 1); - } - } - - // Uninstall the Pocket social provider if it exists, but only if we haven't - // already uninstalled it in this manner. That way the user can reinstall - // it if they prefer it without its being uninstalled every time they start - // the browser. - let SocialService; - try { - // For Firefox 51+ - SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService; - } catch (e) { - SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService; - } - - let origin = "https://getpocket.com"; - SocialService.getProvider(origin, provider => { - if (provider) { - let pref = "social.backup.getpocket-com"; - if (!Services.prefs.prefHasUserValue(pref)) { - let str = Cc["@mozilla.org/supports-string;1"]. - createInstance(Ci.nsISupportsString); - str.data = JSON.stringify(provider.manifest); - Services.prefs.setComplexValue(pref, Ci.nsISupportsString, str); - SocialService.uninstallProvider(origin, () => {}); - } - } - }); - -} - -// PocketContextMenu -// When the context menu is opened check if we need to build and enable pocket UI. -var PocketContextMenu = { - init: function() { - Services.obs.addObserver(this, "on-build-contextmenu", false); - }, - shutdown: function() { - Services.obs.removeObserver(this, "on-build-contextmenu"); - // loop through windows and remove context menus - // iterate through all windows and add pocket to them - for (let win of CustomizableUI.windows) { - let document = win.document; - for (let id of ["context-pocket", "context-savelinktopocket"]) { - let element = document.getElementById(id); - if (element) - element.remove(); - } - } - }, - observe: function(aSubject, aTopic, aData) { - let subject = aSubject.wrappedJSObject; - let document = subject.menu.ownerDocument; - let pocketEnabled = CustomizableUI.getPlacementOfWidget("pocket-button"); - - let showSaveCurrentPageToPocket = !(subject.onTextInput || subject.onLink || - subject.isContentSelected || subject.onImage || - subject.onCanvas || subject.onVideo || subject.onAudio); - let targetUrl = subject.onLink ? subject.linkUrl : subject.pageUrl; - let targetURI = Services.io.newURI(targetUrl, null, null); - let canPocket = pocketEnabled && (targetURI.schemeIs("http") || targetURI.schemeIs("https") || - (targetURI.schemeIs("about") && ReaderMode.getOriginalUrl(targetUrl))); - - let showSaveLinkToPocket = canPocket && !showSaveCurrentPageToPocket && subject.onLink; - - // create menu entries if necessary - let menu = document.getElementById("context-pocket"); - if (!menu) { - menu = createElementWithAttrs(document, "menuitem", { - "id": "context-pocket", - "label": gPocketBundle.GetStringFromName("saveToPocketCmd.label"), - "accesskey": gPocketBundle.GetStringFromName("saveToPocketCmd.accesskey"), - "oncommand": "Pocket.savePage(gContextMenu.browser, gContextMenu.browser.currentURI.spec, gContextMenu.browser.contentTitle);" - }); - let sibling = document.getElementById("context-savepage"); - if (sibling.nextSibling) { - sibling.parentNode.insertBefore(menu, sibling.nextSibling); - } else { - sibling.parentNode.appendChild(menu); - } - } - menu.hidden = !(canPocket && showSaveCurrentPageToPocket); - - menu = document.getElementById("context-savelinktopocket"); - if (!menu) { - menu = createElementWithAttrs(document, "menuitem", { - "id": "context-savelinktopocket", - "label": gPocketBundle.GetStringFromName("saveLinkToPocketCmd.label"), - "accesskey": gPocketBundle.GetStringFromName("saveLinkToPocketCmd.accesskey"), - "oncommand": "Pocket.savePage(gContextMenu.browser, gContextMenu.linkURL);" - }); - let sibling = document.getElementById("context-savelink"); - if (sibling.nextSibling) { - sibling.parentNode.insertBefore(menu, sibling.nextSibling); - } else { - sibling.parentNode.appendChild(menu); - } - } - menu.hidden = !showSaveLinkToPocket; - } -} - -// PocketReader -// Listen for reader mode setup and add our button to the reader toolbar -var PocketReader = { - _hidden: true, - get hidden() { - return this._hidden; - }, - set hidden(hide) { - hide = !!hide; - if (hide === this._hidden) - return; - this._hidden = hide; - this.update(); - }, - startup: function() { - // Setup the listeners, update will be called when the widget is added, - // no need to do that now. - let mm = Services.mm; - mm.addMessageListener("Reader:OnSetup", this); - mm.addMessageListener("Reader:Clicked-pocket-button", this); - }, - shutdown: function() { - let mm = Services.mm; - mm.removeMessageListener("Reader:OnSetup", this); - mm.removeMessageListener("Reader:Clicked-pocket-button", this); - this.hidden = true; - }, - update: function() { - if (this.hidden) { - Services.mm.broadcastAsyncMessage("Reader:RemoveButton", { id: "pocket-button" }); - } else { - Services.mm.broadcastAsyncMessage("Reader:AddButton", - { id: "pocket-button", - title: gPocketBundle.GetStringFromName("pocket-button.tooltiptext"), - image: "chrome://pocket/content/panels/img/pocket.svg#pocket-mark" }); - } - }, - receiveMessage: function(message) { - switch (message.name) { - case "Reader:OnSetup": { - // Tell the reader about our button. - if (this.hidden) - break; - message.target.messageManager. - sendAsyncMessage("Reader:AddButton", { id: "pocket-button", - title: gPocketBundle.GetStringFromName("pocket-button.tooltiptext"), - image: "chrome://pocket/content/panels/img/pocket.svg#pocket-mark"}); - break; - } - case "Reader:Clicked-pocket-button": { - let doc = message.target.ownerDocument; - let pocketWidget = doc.getElementById("pocket-button"); - let placement = CustomizableUI.getPlacementOfWidget("pocket-button"); - if (placement) { - if (placement.area == CustomizableUI.AREA_PANEL) { - doc.defaultView.PanelUI.show().then(function() { - // The DOM node might not exist yet if the panel wasn't opened before. - pocketWidget = doc.getElementById("pocket-button"); - pocketWidget.doCommand(); - }); - } else { - pocketWidget.doCommand(); - } - } - break; - } - } - } -} - - -function pktUIGetter(prop, window) { - return { - get: function() { - // delete any getters for properties loaded from main.js so we only load main.js once - delete window.pktUI; - delete window.pktApi; - delete window.pktUIMessaging; - Services.scriptloader.loadSubScript("chrome://pocket/content/main.js", window); - return window[prop]; - }, - configurable: true, - enumerable: true - }; -} - -var PocketOverlay = { - startup: function(reason) { - let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"] - .getService(Ci.nsIStyleSheetService); - this._sheetType = styleSheetService.AUTHOR_SHEET; - this._cachedSheet = styleSheetService.preloadSheet(gPocketStyleURI, - this._sheetType); - Services.ppmm.loadProcessScript(PROCESS_SCRIPT, true); - PocketReader.startup(); - CustomizableUI.addListener(this); - CreatePocketWidget(reason); - PocketContextMenu.init(); - - for (let win of CustomizableUI.windows) { - this.onWindowOpened(win); - } - }, - shutdown: function(reason) { - let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"] - .getService(Ci.nsIMessageBroadcaster); - ppmm.broadcastAsyncMessage("PocketShuttingDown"); - // Although the ppmm loads the scripts into the chrome process as well, - // we need to manually unregister here anyway to ensure these aren't part - // of the chrome process and avoid errors. - AboutPocket.aboutSaved.unregister(); - AboutPocket.aboutSignup.unregister(); - - CustomizableUI.removeListener(this); - for (let window of CustomizableUI.windows) { - for (let id of ["panelMenu_pocket", "menu_pocket", "BMB_pocket", - "panelMenu_pocketSeparator", "menu_pocketSeparator", - "BMB_pocketSeparator"]) { - let element = window.document.getElementById(id); - if (element) - element.remove(); - } - this.removeStyles(window); - // remove script getters/objects - delete window.Pocket; - delete window.pktApi; - delete window.pktUI; - delete window.pktUIMessaging; - } - CustomizableUI.destroyWidget("pocket-button"); - PocketContextMenu.shutdown(); - PocketReader.shutdown(); - }, - onWindowOpened: function(window) { - if (window.hasOwnProperty("pktUI")) - return; - this.setWindowScripts(window); - this.addStyles(window); - this.updateWindow(window); - }, - setWindowScripts: function(window) { - XPCOMUtils.defineLazyModuleGetter(window, "Pocket", - "chrome://pocket/content/Pocket.jsm"); - // Can't use XPCOMUtils for these because the scripts try to define the variables - // on window, and so the defineProperty inside defineLazyGetter fails. - Object.defineProperty(window, "pktApi", pktUIGetter("pktApi", window)); - Object.defineProperty(window, "pktUI", pktUIGetter("pktUI", window)); - Object.defineProperty(window, "pktUIMessaging", pktUIGetter("pktUIMessaging", window)); - }, - // called for each window as it is opened - updateWindow: function(window) { - // insert our three menu items - let document = window.document; - let hidden = !CustomizableUI.getPlacementOfWidget("pocket-button"); - - // add to bookmarksMenu - let sib = document.getElementById("menu_bookmarkThisPage"); - if (sib && !document.getElementById("menu_pocket")) { - let menu = createElementWithAttrs(document, "menuitem", { - "id": "menu_pocket", - "label": gPocketBundle.GetStringFromName("pocketMenuitem.label"), - "class": "menuitem-iconic", // OSX only - "oncommand": "openUILink(Pocket.listURL, event);", - "hidden": hidden - }); - let sep = createElementWithAttrs(document, "menuseparator", { - "id": "menu_pocketSeparator", - "hidden": hidden - }); - sib.parentNode.insertBefore(menu, sib); - sib.parentNode.insertBefore(sep, sib); - } - - // add to bookmarks-menu-button - sib = document.getElementById("BMB_bookmarksToolbar"); - if (sib && !document.getElementById("BMB_pocket")) { - let menu = createElementWithAttrs(document, "menuitem", { - "id": "BMB_pocket", - "label": gPocketBundle.GetStringFromName("pocketMenuitem.label"), - "class": "menuitem-iconic bookmark-item subviewbutton", - "oncommand": "openUILink(Pocket.listURL, event);", - "hidden": hidden - }); - let sep = createElementWithAttrs(document, "menuseparator", { - "id": "BMB_pocketSeparator", - "hidden": hidden - }); - sib.parentNode.insertBefore(menu, sib); - sib.parentNode.insertBefore(sep, sib); - } - - // add to PanelUI-bookmarks - sib = document.getElementById("panelMenuBookmarkThisPage"); - if (sib && !document.getElementById("panelMenu_pocket")) { - let menu = createElementWithAttrs(document, "toolbarbutton", { - "id": "panelMenu_pocket", - "label": gPocketBundle.GetStringFromName("pocketMenuitem.label"), - "class": "subviewbutton cui-withicon", - "oncommand": "openUILink(Pocket.listURL, event);", - "hidden": hidden - }); - let sep = createElementWithAttrs(document, "toolbarseparator", { - "id": "panelMenu_pocketSeparator", - "hidden": hidden - }); - // nextSibling is no-id toolbarseparator - // insert separator first then button - sib = sib.nextSibling; - sib.parentNode.insertBefore(sep, sib); - sib.parentNode.insertBefore(menu, sib); - } - }, - onWidgetAfterDOMChange: function(aWidgetNode) { - if (aWidgetNode.id != "pocket-button") { - return; - } - let doc = aWidgetNode.ownerDocument; - let hidden = !CustomizableUI.getPlacementOfWidget("pocket-button"); - for (let prefix of ["panelMenu_", "menu_", "BMB_"]) { - let element = doc.getElementById(prefix + "pocket"); - if (element) { - element.hidden = hidden; - doc.getElementById(prefix + "pocketSeparator").hidden = hidden; - } - } - // enable or disable reader button - PocketReader.hidden = hidden; - }, - - addStyles: function(win) { - let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - utils.addSheet(this._cachedSheet, this._sheetType); - }, - - removeStyles: function(win) { - let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - utils.removeSheet(gPocketStyleURI, this._sheetType); - } - -} - -// use enabled pref as a way for tests (e.g. test_contextmenu.html) to disable -// the addon when running. -function prefObserver(aSubject, aTopic, aData) { - let enabled = Services.prefs.getBoolPref("extensions.pocket.enabled"); - if (enabled) - PocketOverlay.startup(ADDON_ENABLE); - else - PocketOverlay.shutdown(ADDON_DISABLE); -} - -function startup(data, reason) { - AddonManager.getAddonByID("isreaditlater@ideashower.com", addon => { - if (addon && addon.isActive) - return; - setDefaultPrefs(); - // migrate enabled pref - if (Services.prefs.prefHasUserValue("browser.pocket.enabled")) { - Services.prefs.setBoolPref("extensions.pocket.enabled", Services.prefs.getBoolPref("browser.pocket.enabled")); - Services.prefs.clearUserPref("browser.pocket.enabled"); - } - // watch pref change and enable/disable if necessary - Services.prefs.addObserver("extensions.pocket.enabled", prefObserver, false); - if (!Services.prefs.getBoolPref("extensions.pocket.enabled")) - return; - PocketOverlay.startup(reason); - }); -} - -function shutdown(data, reason) { - // For speed sake, we should only do a shutdown if we're being disabled. - // On an app shutdown, just let it fade away... - if (reason != APP_SHUTDOWN) { - Services.prefs.removeObserver("extensions.pocket.enabled", prefObserver); - PocketOverlay.shutdown(reason); - } -} - -function install() { -} - -function uninstall() { -} diff --git a/browser/extensions/pocket/content/AboutPocket.jsm b/browser/extensions/pocket/content/AboutPocket.jsm deleted file mode 100644 index c7f57aa87..000000000 --- a/browser/extensions/pocket/content/AboutPocket.jsm +++ /dev/null @@ -1,93 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -"use strict"; - -const { interfaces: Ci, results: Cr, manager: Cm, utils: Cu } = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error". -const PREF_LOG_LEVEL = "loop.debug.loglevel"; - -XPCOMUtils.defineLazyGetter(this, "log", () => { - let ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI; - let consoleOptions = { - maxLogLevelPref: PREF_LOG_LEVEL, - prefix: "Loop" - }; - return new ConsoleAPI(consoleOptions); -}); - - -function AboutPage(chromeURL, aboutHost, classID, description, uriFlags) { - this.chromeURL = chromeURL; - this.aboutHost = aboutHost; - this.classID = Components.ID(classID); - this.description = description; - this.uriFlags = uriFlags; -} - -AboutPage.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]), - getURIFlags: function(aURI) { // eslint-disable-line no-unused-vars - return this.uriFlags; - }, - - newChannel: function(aURI, aLoadInfo) { - let newURI = Services.io.newURI(this.chromeURL, null, null); - let channel = Services.io.newChannelFromURIWithLoadInfo(newURI, - aLoadInfo); - channel.originalURI = aURI; - - if (this.uriFlags & Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT) { - let principal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(aURI); - channel.owner = principal; - } - return channel; - }, - - createInstance: function(outer, iid) { - if (outer !== null) { - throw Cr.NS_ERROR_NO_AGGREGATION; - } - return this.QueryInterface(iid); - }, - - register: function() { - Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory( - this.classID, this.description, - "@mozilla.org/network/protocol/about;1?what=" + this.aboutHost, this); - }, - - unregister: function() { - Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory( - this.classID, this); - } -}; - -/* exported AboutPocket */ -var AboutPocket = {}; - -XPCOMUtils.defineLazyGetter(AboutPocket, "aboutSaved", () => - new AboutPage("chrome://pocket/content/panels/saved.html", - "pocket-saved", - "{3e759f54-37af-7843-9824-f71b5993ceed}", - "About Pocket Saved", - Ci.nsIAboutModule.ALLOW_SCRIPT | - Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT | - Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT) -); - -XPCOMUtils.defineLazyGetter(AboutPocket, "aboutSignup", () => - new AboutPage("chrome://pocket/content/panels/signup.html", - "pocket-signup", - "{8548329d-00c4-234e-8f17-75026db3b56e}", - "About Pocket Signup", - Ci.nsIAboutModule.ALLOW_SCRIPT | - Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT | - Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT) -); - -this.EXPORTED_SYMBOLS = ["AboutPocket"]; diff --git a/browser/extensions/pocket/content/Pocket.jsm b/browser/extensions/pocket/content/Pocket.jsm deleted file mode 100644 index 54f9cdf11..000000000 --- a/browser/extensions/pocket/content/Pocket.jsm +++ /dev/null @@ -1,93 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -this.EXPORTED_SYMBOLS = ["Pocket"]; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI", - "resource:///modules/CustomizableUI.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", - "resource://gre/modules/ReaderMode.jsm"); - -var Pocket = { - get site() { return Services.prefs.getCharPref("extensions.pocket.site"); }, - get listURL() { return "https://" + Pocket.site + "/?src=ff_ext"; }, - - /** - * Functions related to the Pocket panel UI. - */ - onPanelViewShowing(event) { - let document = event.target.ownerDocument; - let window = document.defaultView; - let iframe = window.pktUI.getPanelFrame(); - - let urlToSave = Pocket._urlToSave; - let titleToSave = Pocket._titleToSave; - Pocket._urlToSave = null; - Pocket._titleToSave = null; - // ViewShowing fires immediately before it creates the contents, - // in lieu of an AfterViewShowing event, just spin the event loop. - window.setTimeout(function() { - if (urlToSave) { - window.pktUI.tryToSaveUrl(urlToSave, titleToSave); - } else { - window.pktUI.tryToSaveCurrentPage(); - } - - // pocketPanelDidHide in main.js set iframe to about:blank when it was - // hidden, make sure we're loading the save panel. - if (iframe.contentDocument && - iframe.contentDocument.readyState == "complete" && - iframe.contentDocument.documentURI != "about:blank") { - window.pktUI.pocketPanelDidShow(); - } else { - // iframe didn't load yet. This seems to always be the case when in - // the toolbar panel, but never the case for a subview. - // XXX this only being fired when it's a _capturing_ listener! - iframe.addEventListener("load", Pocket.onFrameLoaded, true); - } - }, 0); - }, - - onFrameLoaded(event) { - let document = event.currentTarget.ownerDocument; - let window = document.defaultView; - let iframe = window.pktUI.getPanelFrame(); - - iframe.removeEventListener("load", Pocket.onFrameLoaded, true); - window.pktUI.pocketPanelDidShow(); - }, - - onPanelViewHiding(event) { - let window = event.target.ownerGlobal; - window.pktUI.pocketPanelDidHide(event); - }, - - _urlToSave: null, - _titleToSave: null, - savePage(browser, url, title) { - let document = browser.ownerDocument; - let pocketWidget = document.getElementById("pocket-button"); - let placement = CustomizableUI.getPlacementOfWidget("pocket-button"); - if (!placement) - return; - - this._urlToSave = url; - this._titleToSave = title; - if (placement.area == CustomizableUI.AREA_PANEL) { - let win = document.defaultView; - win.PanelUI.show().then(function() { - pocketWidget = document.getElementById("pocket-button"); - pocketWidget.doCommand(); - }); - } else { - pocketWidget.doCommand(); - } - }, -}; diff --git a/browser/extensions/pocket/content/main.js b/browser/extensions/pocket/content/main.js deleted file mode 100644 index 3c1c5785e..000000000 --- a/browser/extensions/pocket/content/main.js +++ /dev/null @@ -1,737 +0,0 @@ -/* - * LICENSE - * - * POCKET MARKS - * - * Notwithstanding the permitted uses of the Software (as defined below) pursuant to the license set forth below, "Pocket," "Read It Later" and the Pocket icon and logos (collectively, the “Pocket Marks”) are registered and common law trademarks of Read It Later, Inc. This means that, while you have considerable freedom to redistribute and modify the Software, there are tight restrictions on your ability to use the Pocket Marks. This license does not grant you any rights to use the Pocket Marks except as they are embodied in the Software. - * - * --- - * - * SOFTWARE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Pocket UI module - * - * Handles interactions with Pocket buttons, panels and menus. - * - */ - -// TODO : Get the toolbar icons from Firefox's build (Nikki needs to give us a red saved icon) -// TODO : [needs clarificaiton from Fx] Firefox's plan was to hide Pocket from context menus until the user logs in. Now that it's an extension I'm wondering if we still need to do this. -// TODO : [needs clarificaiton from Fx] Reader mode (might be a something they need to do since it's in html, need to investigate their code) -// TODO : [needs clarificaiton from Fx] Move prefs within pktApi.s to sqlite or a local file so it's not editable (and is safer) -// TODO : [nice to have] - Immediately save, buffer the actions in a local queue and send (so it works offline, works like our native extensions) - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", - "resource://gre/modules/PrivateBrowsingUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", - "resource://gre/modules/ReaderMode.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "pktApi", - "chrome://pocket/content/pktApi.jsm"); - -var pktUI = (function() { - - // -- Initialization (on startup and new windows) -- // - var _currentPanelDidShow; - var _currentPanelDidHide; - - // Init panel id at 0. The first actual panel id will have the number 1 so - // in case at some point any panel has the id 0 we know there is something - // wrong - var _panelId = 0; - - var overflowMenuWidth = 230; - var overflowMenuHeight = 475; - var savePanelWidth = 350; - var savePanelHeights = {collapsed: 153, expanded: 272}; - - // -- Event Handling -- // - - /** - * Event handler when Pocket toolbar button is pressed - */ - - function pocketPanelDidShow(event) { - if (_currentPanelDidShow) { - _currentPanelDidShow(event); - } - - } - - function pocketPanelDidHide(event) { - if (_currentPanelDidHide) { - _currentPanelDidHide(event); - } - - // clear the panel - getPanelFrame().setAttribute('src', 'about:blank'); - } - - - // -- Communication to API -- // - - /** - * Either save or attempt to log the user in - */ - function tryToSaveCurrentPage() { - tryToSaveUrl(getCurrentUrl(), getCurrentTitle()); - } - - function tryToSaveUrl(url, title) { - - // If the user is logged in, go ahead and save the current page - if (pktApi.isUserLoggedIn()) { - saveAndShowConfirmation(url, title); - return; - } - - // If the user is not logged in, show the logged-out state to prompt them to authenticate - showSignUp(); - } - - - // -- Panel UI -- // - - /** - * Show the sign-up panel - */ - function showSignUp() { - // AB test: Direct logged-out users to tab vs panel - if (pktApi.getSignupPanelTabTestVariant() == 'v2') - { - let site = Services.prefs.getCharPref("extensions.pocket.site"); - openTabWithUrl('https://' + site + '/firefox_learnmore?s=ffi&t=autoredirect&tv=page_learnmore&src=ff_ext', true); - - // force the panel closed before it opens - getPanel().hidePopup(); - - return; - } - - // Control: Show panel as normal - getFirefoxAccountSignedInUser(function(userdata) - { - var fxasignedin = (typeof userdata == 'object' && userdata !== null) ? '1' : '0'; - var startheight = 490; - var inOverflowMenu = isInOverflowMenu(); - var controlvariant = pktApi.getSignupPanelTabTestVariant() == 'control'; - - if (inOverflowMenu) - { - startheight = overflowMenuHeight; - } - else - { - startheight = 460; - if (fxasignedin == '1') - { - startheight = 406; - } - } - if (!controlvariant) { - startheight = 427; - } - var variant; - if (inOverflowMenu) - { - variant = 'overflow'; - } - else - { - variant = 'storyboard_lm'; - } - - showPanel("about:pocket-signup?pockethost=" - + Services.prefs.getCharPref("extensions.pocket.site") - + "&fxasignedin=" - + fxasignedin - + "&variant=" - + variant - + '&controlvariant=' - + controlvariant - + '&inoverflowmenu=' - + inOverflowMenu - + "&locale=" - + getUILocale(), { - onShow: function() { - }, - onHide: panelDidHide, - width: inOverflowMenu ? overflowMenuWidth : 300, - height: startheight - }); - }); - } - - /** - * Show the logged-out state / sign-up panel - */ - function saveAndShowConfirmation(url, title) { - - // Validate input parameter - if (typeof url !== 'undefined' && url.startsWith("about:reader?url=")) { - url = ReaderMode.getOriginalUrl(url); - } - - var isValidURL = (typeof url !== 'undefined' && (url.startsWith("http") || url.startsWith('https'))); - - var inOverflowMenu = isInOverflowMenu(); - var startheight = pktApi.isPremiumUser() && isValidURL ? savePanelHeights.expanded : savePanelHeights.collapsed; - if (inOverflowMenu) { - startheight = overflowMenuHeight; - } - - var panelId = showPanel("about:pocket-saved?pockethost=" + Services.prefs.getCharPref("extensions.pocket.site") + "&premiumStatus=" + (pktApi.isPremiumUser() ? '1' : '0') + '&inoverflowmenu='+inOverflowMenu + "&locale=" + getUILocale(), { - onShow: function() { - var saveLinkMessageId = 'saveLink'; - - // Send error message for invalid url - if (!isValidURL) { - // TODO: Pass key for localized error in error object - let error = { - message: 'Only links can be saved', - localizedKey: "onlylinkssaved" - }; - pktUIMessaging.sendErrorMessageToPanel(panelId, saveLinkMessageId, error); - return; - } - - // Check online state - if (!navigator.onLine) { - // TODO: Pass key for localized error in error object - let error = { - message: 'You must be connected to the Internet in order to save to Pocket. Please connect to the Internet and try again.' - }; - pktUIMessaging.sendErrorMessageToPanel(panelId, saveLinkMessageId, error); - return; - } - - // Add url - var options = { - success: function(data, request) { - var item = data.item; - var successResponse = { - status: "success", - item: item - }; - pktUIMessaging.sendMessageToPanel(panelId, saveLinkMessageId, successResponse); - }, - error: function(error, request) { - // If user is not authorized show singup page - if (request.status === 401) { - showSignUp(); - return; - } - - // If there is no error message in the error use a - // complete catch-all - var errorMessage = error.message || "There was an error when trying to save to Pocket."; - var panelError = { message: errorMessage} - - // Send error message to panel - pktUIMessaging.sendErrorMessageToPanel(panelId, saveLinkMessageId, panelError); - } - } - - // Add title if given - if (typeof title !== "undefined") { - options.title = title; - } - - // Send the link - pktApi.addLink(url, options); - }, - onHide: panelDidHide, - width: inOverflowMenu ? overflowMenuWidth : savePanelWidth, - height: startheight - }); - } - - /** - * Open a generic panel - */ - function showPanel(url, options) { - - // Add new panel id - _panelId += 1; - url += ("&panelId=" + _panelId); - - // We don't have to hide and show the panel again if it's already shown - // as if the user tries to click again on the toolbar button the overlay - // will close instead of the button will be clicked - var iframe = getPanelFrame(); - - // Register event handlers - registerEventMessages(); - - // Load the iframe - iframe.setAttribute('src', url); - - // Uncomment to leave panel open -- for debugging - // panel.setAttribute('noautohide', true); - // panel.setAttribute('consumeoutsideclicks', false); - // - - // For some reason setting onpopupshown and onpopuphidden on the panel directly didn't work, so - // do it this hacky way for now - _currentPanelDidShow = options.onShow; - _currentPanelDidHide = options.onHide; - - resizePanel({ - width: options.width, - height: options.height - }); - return _panelId; - } - - /** - * Resize the panel - * options = { - * width: , - * height: , - * animate [default false] - * } - */ - function resizePanel(options) { - var iframe = getPanelFrame(); - var subview = getSubview(); - - if (subview) { - // Use the subview's size - iframe.style.width = "100%"; - iframe.style.height = subview.parentNode.clientHeight + "px"; - } else { - // Set an explicit size, panel will adapt. - iframe.style.width = options.width + "px"; - iframe.style.height = options.height + "px"; - } - } - - /** - * Called when the signup and saved panel was hidden - */ - function panelDidHide() { - // clear the onShow and onHide values - _currentPanelDidShow = null; - _currentPanelDidHide = null; - } - - /** - * Register all of the messages needed for the panels - */ - function registerEventMessages() { - var iframe = getPanelFrame(); - - // Only register the messages once - var didInitAttributeKey = 'did_init'; - var didInitMessageListener = iframe.getAttribute(didInitAttributeKey); - if (typeof didInitMessageListener !== "undefined" && didInitMessageListener == 1) { - return; - } - iframe.setAttribute(didInitAttributeKey, 1); - - // When the panel is displayed it generated an event called - // "show": we will listen for that event and when it happens, - // send our own "show" event to the panel's script, so the - // script can prepare the panel for display. - var _showMessageId = "show"; - pktUIMessaging.addMessageListener(iframe, _showMessageId, function(panelId, data) { - // Let panel know that it is ready - pktUIMessaging.sendMessageToPanel(panelId, _showMessageId); - }); - - // Open a new tab with a given url and activate if - var _openTabWithUrlMessageId = "openTabWithUrl"; - pktUIMessaging.addMessageListener(iframe, _openTabWithUrlMessageId, function(panelId, data, contentPrincipal) { - try { - urlSecurityCheck(data.url, contentPrincipal, Services.scriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); - } catch (ex) { - return; - } - - // Check if the tab should become active after opening - var activate = true; - if (typeof data.activate !== "undefined") { - activate = data.activate; - } - - var url = data.url; - openTabWithUrl(url, activate); - pktUIMessaging.sendResponseMessageToPanel(panelId, _openTabWithUrlMessageId, url); - }); - - // Close the panel - var _closeMessageId = "close"; - pktUIMessaging.addMessageListener(iframe, _closeMessageId, function(panelId, data) { - getPanel().hidePopup(); - }); - - // Send the current url to the panel - var _getCurrentURLMessageId = "getCurrentURL"; - pktUIMessaging.addMessageListener(iframe, _getCurrentURLMessageId, function(panelId, data) { - pktUIMessaging.sendResponseMessageToPanel(panelId, _getCurrentURLMessageId, getCurrentUrl()); - }); - - var _resizePanelMessageId = "resizePanel"; - pktUIMessaging.addMessageListener(iframe, _resizePanelMessageId, function(panelId, data) { - resizePanel(data); - }); - - // Callback post initialization to tell background script that panel is "ready" for communication. - pktUIMessaging.addMessageListener(iframe, "listenerReady", function(panelId, data) { - - }); - - pktUIMessaging.addMessageListener(iframe, "collapseSavePanel", function(panelId, data) { - if (!pktApi.isPremiumUser() && !isInOverflowMenu()) - resizePanel({width:savePanelWidth, height:savePanelHeights.collapsed}); - }); - - pktUIMessaging.addMessageListener(iframe, "expandSavePanel", function(panelId, data) { - if (!isInOverflowMenu()) - resizePanel({width:savePanelWidth, height:savePanelHeights.expanded}); - }); - - // Ask for recently accessed/used tags for auto complete - var _getTagsMessageId = "getTags"; - pktUIMessaging.addMessageListener(iframe, _getTagsMessageId, function(panelId, data) { - pktApi.getTags(function(tags, usedTags) { - pktUIMessaging.sendResponseMessageToPanel(panelId, _getTagsMessageId, { - tags: tags, - usedTags: usedTags - }); - }); - }); - - // Ask for suggested tags based on passed url - var _getSuggestedTagsMessageId = "getSuggestedTags"; - pktUIMessaging.addMessageListener(iframe, _getSuggestedTagsMessageId, function(panelId, data) { - pktApi.getSuggestedTagsForURL(data.url, { - success: function(data, response) { - var suggestedTags = data.suggested_tags; - var successResponse = { - status: "success", - value: { - suggestedTags: suggestedTags - } - } - pktUIMessaging.sendResponseMessageToPanel(panelId, _getSuggestedTagsMessageId, successResponse); - }, - error: function(error, response) { - pktUIMessaging.sendErrorResponseMessageToPanel(panelId, _getSuggestedTagsMessageId, error); - } - }) - }); - - // Pass url and array list of tags, add to existing save item accordingly - var _addTagsMessageId = "addTags"; - pktUIMessaging.addMessageListener(iframe, _addTagsMessageId, function(panelId, data) { - pktApi.addTagsToURL(data.url, data.tags, { - success: function(data, response) { - var successResponse = {status: "success"}; - pktUIMessaging.sendResponseMessageToPanel(panelId, _addTagsMessageId, successResponse); - }, - error: function(error, response) { - pktUIMessaging.sendErrorResponseMessageToPanel(panelId, _addTagsMessageId, error); - } - }); - }); - - // Based on clicking "remove page" CTA, and passed unique item id, remove the item - var _deleteItemMessageId = "deleteItem"; - pktUIMessaging.addMessageListener(iframe, _deleteItemMessageId, function(panelId, data) { - pktApi.deleteItem(data.itemId, { - success: function(data, response) { - var successResponse = {status: "success"}; - pktUIMessaging.sendResponseMessageToPanel(panelId, _deleteItemMessageId, successResponse); - }, - error: function(error, response) { - pktUIMessaging.sendErrorResponseMessageToPanel(panelId, _deleteItemMessageId, error); - } - }) - }); - - var _initL10NMessageId = "initL10N"; - pktUIMessaging.addMessageListener(iframe, _initL10NMessageId, function(panelId, data) { - var strings = {}; - var bundle = Services.strings.createBundle("chrome://pocket/locale/pocket.properties"); - var e = bundle.getSimpleEnumeration(); - while (e.hasMoreElements()) { - var str = e.getNext().QueryInterface(Components.interfaces.nsIPropertyElement); - if (str.key in data) { - strings[str.key] = bundle.formatStringFromName(str.key, data[str.key], data[str.key].length); - } else { - strings[str.key] = str.value; - } - } - pktUIMessaging.sendResponseMessageToPanel(panelId, _initL10NMessageId, { strings: strings }); - }); - - } - - // -- Browser Navigation -- // - - /** - * Open a new tab with a given url and notify the iframe panel that it was opened - */ - - function openTabWithUrl(url) { - let recentWindow = Services.wm.getMostRecentWindow("navigator:browser"); - if (!recentWindow) { - Cu.reportError("Pocket: No open browser windows to openTabWithUrl"); - return; - } - - // If the user is in permanent private browsing than this is not an issue, - // since the current window will always share the same cookie jar as the other - // windows. - if (!PrivateBrowsingUtils.isWindowPrivate(recentWindow) || - PrivateBrowsingUtils.permanentPrivateBrowsing) { - recentWindow.openUILinkIn(url, "tab"); - return; - } - - let windows = Services.wm.getEnumerator("navigator:browser"); - while (windows.hasMoreElements()) { - let win = windows.getNext(); - if (!PrivateBrowsingUtils.isWindowPrivate(win)) { - win.openUILinkIn(url, "tab"); - return; - } - } - - // If there were no non-private windows opened already. - recentWindow.openUILinkIn(url, "window"); - } - - - // -- Helper Functions -- // - - function getCurrentUrl() { - return getBrowser().currentURI.spec; - } - - function getCurrentTitle() { - return getBrowser().contentTitle; - } - - function getPanel() { - var frame = getPanelFrame(); - var panel = frame; - while (panel && panel.localName != "panel") { - panel = panel.parentNode; - } - return panel; - } - - function getPanelFrame() { - var frame = document.getElementById('pocket-panel-iframe'); - if (!frame) { - var frameParent = document.getElementById("PanelUI-pocketView").firstChild; - frame = document.createElement("iframe"); - frame.id = 'pocket-panel-iframe'; - frame.setAttribute("type", "content"); - frameParent.appendChild(frame); - } - return frame; - } - - function getSubview() { - var view = document.getElementById("PanelUI-pocketView"); - if (view && view.getAttribute("current") == "true") - return view; - return null; - } - - function isInOverflowMenu() { - var subview = getSubview(); - return !!subview; - } - - function getFirefoxAccountSignedInUser(callback) { - fxAccounts.getSignedInUser().then(userData => { - callback(userData); - }).then(null, error => { - callback(); - }); - } - - function getUILocale() { - var locale = Cc["@mozilla.org/chrome/chrome-registry;1"]. - getService(Ci.nsIXULChromeRegistry). - getSelectedLocale("browser"); - return locale; - } - - /** - * Public functions - */ - return { - getPanelFrame: getPanelFrame, - - openTabWithUrl: openTabWithUrl, - - pocketPanelDidShow: pocketPanelDidShow, - pocketPanelDidHide: pocketPanelDidHide, - - tryToSaveUrl: tryToSaveUrl, - tryToSaveCurrentPage: tryToSaveCurrentPage - }; -}()); - -// -- Communication to Background -- // -// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Interaction_between_privileged_and_non-privileged_pages -var pktUIMessaging = (function() { - - /** - * Prefix message id for message listening - */ - function prefixedMessageId(messageId) { - return 'PKT_' + messageId; - } - - /** - * Register a listener and callback for a specific messageId - */ - function addMessageListener(iframe, messageId, callback) { - iframe.addEventListener(prefixedMessageId(messageId), function(e) { - var nodePrincipal = e.target.nodePrincipal; - // ignore to ensure we do not pick up other events in the browser - if (!nodePrincipal || !nodePrincipal.URI || !nodePrincipal.URI.spec.startsWith("about:pocket")) { - return; - } - - // Pass in information to callback - var payload = JSON.parse(e.target.getAttribute("payload"))[0]; - var panelId = payload.panelId; - var data = payload.data; - callback(panelId, data, nodePrincipal); - - // Cleanup the element - e.target.parentNode.removeChild(e.target); - - }, false, true); - } - - /** - * Send a message to the panel's iframe - */ - function sendMessageToPanel(panelId, messageId, payload) { - - if (!isPanelIdValid(panelId)) { return; } - - var panelFrame = pktUI.getPanelFrame(); - if (!isPocketPanelFrameValid(panelFrame)) { return; } - - var doc = panelFrame.contentWindow.document; - var documentElement = doc.documentElement; - - // Send message to panel - var panelMessageId = prefixedMessageId(panelId + '_' + messageId); - - var AnswerEvt = doc.createElement("PKTMessage"); - AnswerEvt.setAttribute("payload", JSON.stringify([payload])); - documentElement.appendChild(AnswerEvt); - - var event = doc.createEvent("HTMLEvents"); - event.initEvent(panelMessageId, true, false); - AnswerEvt.dispatchEvent(event); - } - - function sendResponseMessageToPanel(panelId, messageId, payload) { - var responseMessageId = messageId + "Response"; - sendMessageToPanel(panelId, responseMessageId, payload); - } - - /** - * Helper function to package an error object and send it to the panel - * iframe as a message response - */ - function sendErrorMessageToPanel(panelId, messageId, error) { - var errorResponse = {status: "error", error: error}; - sendMessageToPanel(panelId, messageId, errorResponse); - } - - function sendErrorResponseMessageToPanel(panelId, messageId, error) { - var errorResponse = {status: "error", error: error}; - sendResponseMessageToPanel(panelId, messageId, errorResponse); - } - - /** - * Validation - */ - - function isPanelIdValid(panelId) { - // First check if panelId has a valid value > 0. We set the panelId to - // 0 to start. But if for some reason the message is attempted to be - // sent before the panel has a panelId, then it's going to send out - // a message with panelId 0, which is never going to be heard. If this - // happens, it means some race condition occurred where the panel was - // trying to communicate before it should. - if (panelId === 0) { - console.warn("Tried to send message to panel with id 0.") - return false; - } - - return true - } - - function isPocketPanelFrameValid(panelFrame) { - // Check if panel is available if not throw a warning and bailout. - // We likely try to send to a panel that is not visible anymore - if (typeof panelFrame === "undefined") { - console.warn("Pocket panel frame is undefined"); - return false; - } - - var contentWindow = panelFrame.contentWindow; - if (typeof contentWindow == "undefined") { - console.warn("Pocket panel frame content window is undefined"); - return false; - } - - var doc = contentWindow.document; - if (typeof doc === "undefined") { - console.warn("Pocket panel frame content window document is undefined"); - return false; - } - - var documentElement = doc.documentElement; - if (typeof documentElement === "undefined") { - console.warn("Pocket panel frame content window document document element is undefined"); - return false; - } - - return true; - } - - /** - * Public - */ - return { - addMessageListener: addMessageListener, - sendMessageToPanel: sendMessageToPanel, - sendResponseMessageToPanel: sendResponseMessageToPanel, - sendErrorMessageToPanel: sendErrorMessageToPanel, - sendErrorResponseMessageToPanel: sendErrorResponseMessageToPanel - } -}()); diff --git a/browser/extensions/pocket/content/panels/css/firasans.css b/browser/extensions/pocket/content/panels/css/firasans.css deleted file mode 100644 index 5915345d6..000000000 --- a/browser/extensions/pocket/content/panels/css/firasans.css +++ /dev/null @@ -1,6 +0,0 @@ -@font-face { - font-family: 'FiraSans'; - src: url('../fonts/FiraSans-Regular.woff') format('woff'); - font-weight: normal; - font-style: normal; -} \ No newline at end of file diff --git a/browser/extensions/pocket/content/panels/css/normalize.css b/browser/extensions/pocket/content/panels/css/normalize.css deleted file mode 100644 index b7b4b746e..000000000 --- a/browser/extensions/pocket/content/panels/css/normalize.css +++ /dev/null @@ -1,424 +0,0 @@ -/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ - -/** - * 1. Set default font family to sans-serif. - * 2. Prevent iOS text size adjust after orientation change, without disabling - * user zoom. - */ - -html { - font-family: sans-serif; /* 1 */ -} - -/** - * Remove default margin. - */ - -body { - margin: 0; -} - -/* HTML5 display definitions - ========================================================================== */ - -/** - * Correct `block` display not defined for any HTML5 element in IE 8/9. - * Correct `block` display not defined for `details` or `summary` in IE 10/11 - * and Firefox. - * Correct `block` display not defined for `main` in IE 11. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -nav, -section, -summary { - display: block; -} - -/** - * 1. Correct `inline-block` display not defined in IE 8/9. - * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. - */ - -audio, -canvas, -progress, -video { - display: inline-block; /* 1 */ - vertical-align: baseline; /* 2 */ -} - -/** - * Prevent modern browsers from displaying `audio` without controls. - * Remove excess height in iOS 5 devices. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/** - * Address `[hidden]` styling not present in IE 8/9/10. - * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. - */ - -[hidden], -template { - display: none; -} - -/* Links - ========================================================================== */ - -/** - * Remove the gray background color from active links in IE 10. - */ - -a { - background-color: transparent; -} - -/** - * Improve readability when focused and also mouse hovered in all browsers. - */ - -a:active, -a:hover { - outline: 0; -} - -/* Text-level semantics - ========================================================================== */ - -/** - * Address styling not present in IE 8/9/10/11, Safari, and Chrome. - */ - -abbr[title] { - border-bottom: 1px dotted; -} - -/** - * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. - */ - -b, -strong { - font-weight: bold; -} - -/** - * Address styling not present in Safari and Chrome. - */ - -dfn { - font-style: italic; -} - -/** - * Address variable `h1` font-size and margin within `section` and `article` - * contexts in Firefox 4+, Safari, and Chrome. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/** - * Address styling not present in IE 8/9. - */ - -mark { - background: #ff0; - color: #000; -} - -/** - * Address inconsistent and variable font size in all browsers. - */ - -small { - font-size: 80%; -} - -/** - * Prevent `sub` and `sup` affecting `line-height` in all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -/* Embedded content - ========================================================================== */ - -/** - * Remove border when inside `a` element in IE 8/9/10. - */ - -img { - border: 0; -} - -/** - * Correct overflow not hidden in IE 9/10/11. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* Grouping content - ========================================================================== */ - -/** - * Address margin not present in IE 8/9 and Safari. - */ - -figure { - margin: 1em 40px; -} - -/** - * Address differences between Firefox and other browsers. - */ - -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -/** - * Contain overflow in all browsers. - */ - -pre { - overflow: auto; -} - -/** - * Address odd `em`-unit font size rendering in all browsers. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} - -/* Forms - ========================================================================== */ - -/** - * Known limitation: by default, Chrome and Safari on OS X allow very limited - * styling of `select`, unless a `border` property is set. - */ - -/** - * 1. Correct color not being inherited. - * Known issue: affects color of disabled elements. - * 2. Correct font properties not being inherited. - * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. - */ - -button, -input, -optgroup, -select, -textarea { - color: inherit; /* 1 */ - font: inherit; /* 2 */ - margin: 0; /* 3 */ -} - -/** - * Address `overflow` set to `hidden` in IE 8/9/10/11. - */ - -button { - overflow: visible; -} - -/** - * Address inconsistent `text-transform` inheritance for `button` and `select`. - * All other form control elements do not inherit `text-transform` values. - * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. - * Correct `select` style inheritance in Firefox. - */ - -button, -select { - text-transform: none; -} - -/** - * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` - * and `video` controls. - * 2. Correct inability to style clickable `input` types in iOS. - * 3. Improve usability and consistency of cursor style between image-type - * `input` and others. - */ - -button, -html input[type="button"], /* 1 */ -input[type="reset"], -input[type="submit"] { - cursor: pointer; /* 3 */ -} - -/** - * Re-set default cursor for disabled elements. - */ - -button[disabled], -html input[disabled] { - cursor: default; -} - -/** - * Remove inner padding and border in Firefox 4+. - */ - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -/** - * Address Firefox 4+ setting `line-height` on `input` using `!important` in - * the UA stylesheet. - */ - -input { - line-height: normal; -} - -/** - * It's recommended that you don't attempt to style these elements. - * Firefox's implementation doesn't respect box-sizing, padding, or width. - * - * 1. Address box sizing set to `content-box` in IE 8/9/10. - * 2. Remove excess padding in IE 8/9/10. - */ - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * 1. Address `appearance` set to `searchfield` in Safari and Chrome. - * 2. Address `box-sizing` set to `border-box` in Safari and Chrome - * (include `-moz` to future-proof). - */ - -input[type="search"] { - box-sizing: content-box; -} - -/** - * Define consistent border, margin, and padding. - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/** - * 1. Correct `color` not being inherited in IE 8/9/10/11. - * 2. Remove padding so people aren't caught out if they zero out fieldsets. - */ - -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * Remove default vertical scrollbar in IE 8/9/10/11. - */ - -textarea { - overflow: auto; -} - -/** - * Don't inherit the `font-weight` (applied by a rule above). - * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. - */ - -optgroup { - font-weight: bold; -} - -/* Tables - ========================================================================== */ - -/** - * Remove most spacing between table cells. - */ - -table { - border-collapse: collapse; - border-spacing: 0; -} - -td, -th { - padding: 0; -} - -/* Normalization for FF panel defauts - ========================================================================== */ -html { - outline: none; - padding: 0; -} - -a { - color: #0095dd; - margin: 0; - outline: none; - padding: 0; - text-decoration: none; -} - -a:hover, -a:active { - color: #008acb; - text-decoration: underline; -} - -a:active { - color: #006b9d; -} diff --git a/browser/extensions/pocket/content/panels/css/saved.css b/browser/extensions/pocket/content/panels/css/saved.css deleted file mode 100644 index d3f88d04c..000000000 --- a/browser/extensions/pocket/content/panels/css/saved.css +++ /dev/null @@ -1,825 +0,0 @@ -/* saved.css - * - * Description: - * With base elements out of the way, this sets all custom styling for the page saved dialog. - * - * Contents: - * Global - * Loading spinner - * Core detail - * Tag entry - * Recent/suggested tags - * Premium upsell - * Token input/autocomplete - * Overflow mode - * Language overrides - */ - -/*=Global ---------------------------------------------------------------------------------------- */ -.pkt_ext_containersaved { - background-color: #fbfbfb; - border-radius: 4px; - display: block; - font-size: 16px; - font-family: "FiraSans", "Helvetica Neue", Helvetica, Arial, sans-serif; - padding: 0; - position: relative; - text-align: center; -} -.pkt_ext_cf:after { - content: " "; - display:table; - clear:both; -} -.pkt_ext_containersaved .pkt_ext_tag_detail, -.pkt_ext_containersaved .pkt_ext_recenttag_detail, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail { - margin: 0 auto; - padding: 0.25em 1em; - position: relative; - width: auto; -} - -/*=Loading spinner ---------------------------------------------------------------------------------------- */ -@keyframes pkt_ext_spin { - to { - transform: rotate(1turn); - } -} -.pkt_ext_containersaved { - font-size: 16px; -} -.pkt_ext_containersaved .pkt_ext_loadingspinner { - position: relative; - display: inline-block; - height: 2.5em; - left: 50%; - margin: 2em 0 0 -1.25em; - font-size: 10px; - text-indent: 999em; - position: absolute; - top: 4em; - overflow: hidden; - width: 2.5em; - animation: pkt_ext_spin 0.7s infinite steps(8); -} -.pkt_ext_containersaved .pkt_ext_loadingspinner:before, -.pkt_ext_containersaved .pkt_ext_loadingspinner:after, -.pkt_ext_containersaved .pkt_ext_loadingspinner > div:before, -.pkt_ext_containersaved .pkt_ext_loadingspinner > div:after { - content: ''; - position: absolute; - top: 0; - left: 1.125em; - width: 0.25em; - height: 0.75em; - border-radius: .2em; - background: #eee; - box-shadow: 0 1.75em #eee; - transform-origin: 50% 1.25em; -} -.pkt_ext_containersaved .pkt_ext_loadingspinner:before { - background: #555; -} -.pkt_ext_containersaved .pkt_ext_loadingspinner:after { - transform: rotate(-45deg); - background: #777; -} -.pkt_ext_containersaved .pkt_ext_loadingspinner > div:before { - transform: rotate(-90deg); - background: #999; -} -.pkt_ext_containersaved .pkt_ext_loadingspinner > div:after { - transform: rotate(-135deg); - background: #bbb; -} - -/*=Core detail ---------------------------------------------------------------------------------------- */ -.pkt_ext_containersaved .pkt_ext_initload { - left: 0; - position: absolute; - top: 0; - width: 100%; -} -.pkt_ext_containersaved .pkt_ext_detail { - max-height: 0; - opacity: 0; - position: relative; - z-index: 10; -} -.pkt_ext_container_detailactive .pkt_ext_initload { - opacity: 0; -} -.pkt_ext_container_detailactive .pkt_ext_initload .pkt_ext_loadingspinner, -.pkt_ext_container_finalstate .pkt_ext_initload .pkt_ext_loadingspinner { - animation: none; -} -.pkt_ext_container_detailactive .pkt_ext_detail { - max-height: 20em; - opacity: 1; -} -.pkt_ext_container_finalstate .pkt_ext_edit_msg, -.pkt_ext_container_finalstate .pkt_ext_tag_detail, -.pkt_ext_container_finalstate .pkt_ext_suggestedtag_detail, -.pkt_ext_container_finalstate .pkt_ext_item_actions { - opacity: 0; - transition: opacity 0.2s ease-out; -} -.pkt_ext_container_finalerrorstate .pkt_ext_edit_msg, -.pkt_ext_container_finalerrorstate .pkt_ext_tag_detail, -.pkt_ext_container_finalerrorstate .pkt_ext_suggestedtag_detail, -.pkt_ext_container_finalerrorstate .pkt_ext_item_actions { - display: none; - transition: none; -} -.pkt_ext_containersaved h2 { - background: transparent; - border: none; - color: #333; - display: block; - float: none; - font-size: 18px; - font-weight: normal; - letter-spacing: normal; - line-height: 1; - margin: 19px 0 4px; - padding: 0; - position: relative; - text-align: left; - text-transform: none; -} -@keyframes fade_in_out { - 0% { - opacity: 1; - } - 50% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -.pkt_ext_container_finalstate h2 { - animation: fade_in_out 0.4s ease-out; -} -.pkt_ext_container_finalerrorstate h2 { - animation: none; - color: #d74345; -} -.pkt_ext_containersaved .pkt_ext_errordetail { - display: none; - font-size: 12px; - font-weight: normal; - left: 6.4em; - max-width: 21em; - opacity: 0; - position: absolute; - top: 2.7em; - text-align: left; - visibility: hidden; -} -.pkt_ext_container_finalerrorstate .pkt_ext_errordetail { - display: block; - opacity: 1; - visibility: visible; -} -.pkt_ext_containersaved .pkt_ext_logo { - background: url(../img/pocketlogosolo@1x.png) center center no-repeat; - display: block; - float: left; - height: 40px; - padding: 1.25em 1em; - position: relative; - width: 44px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersaved .pkt_ext_logo { - background-image: url(../img/pocketlogosolo@2x.png); - background-size: 44px 40px; - } -} -.pkt_ext_container_finalerrorstate .pkt_ext_logo { - background-image: url(../img/pocketerror@1x.png); - height: 44px; - width: 44px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_container_finalerrorstate .pkt_ext_logo { - background-image: url(../img/pocketerror@2x.png); - background-size: 44px 44px; - } -} -.pkt_ext_containersaved .pkt_ext_topdetail { - float: left; -} -.pkt_ext_containersaved .pkt_ext_edit_msg { - box-sizing: border-box; - display: none; - font-size: 0.75em; - left: auto; - padding: 0 1.4em; - position: absolute; - text-align: left; - top: 8.7em; - width: 100%; -} -.pkt_ext_containersaved .pkt_ext_edit_msg_error { - color: #d74345; -} -.pkt_ext_containersaved .pkt_ext_edit_msg_active { - display: block; -} -.pkt_ext_containersaved .pkt_ext_item_actions { - background: transparent; - float: none; - height: auto; - margin-bottom: 1em; - margin-top: 0; - width: auto; -} -.pkt_ext_containersaved .pkt_ext_item_actions_disabled { - opacity: 0.5; -} -.pkt_ext_container_finalstate .pkt_ext_item_actions_disabled { - opacity: 0; -} -.pkt_ext_containersaved .pkt_ext_item_actions ul { - background: none; - display: block; - float: none; - font-size: 16px; - height: auto; - margin: 0; - padding: 0; - width: 100%; -} -.pkt_ext_containersaved .pkt_ext_item_actions li { - box-sizing: border-box; - background: none; - border: 0; - float: left; - list-style: none; - line-height: 0.8; - height: auto; - padding-right: 0.4em; - width: auto; -} -.pkt_ext_containersaved .pkt_ext_item_actions li:before { - content: none; -} -.pkt_ext_containersaved .pkt_ext_item_actions .pkt_ext_actions_separator { - border-left: 2px solid #777; - height: 0.75em; - margin-top: 0.3em; - padding: 0; - width: 10px; -} -.pkt_ext_containersaved .pkt_ext_item_actions a { - background: transparent; - color: #0095dd; - display: block; - font-feature-settings: normal; - font-size: 12px; - font-weight: normal; - letter-spacing: normal; - line-height: inherit; - height: auto; - margin: 0; - padding: 0.5em; - float: left; - text-align: left; - text-decoration: none; - text-transform: none; -} -.pkt_ext_containersaved .pkt_ext_item_actions a:hover { - color: #008acb; - text-decoration: underline; -} -.pkt_ext_containersaved .pkt_ext_item_actions a:before, -.pkt_ext_containersaved .pkt_ext_item_actions a:after { - background: transparent; - display: none; -} -.pkt_ext_containersaved .pkt_ext_item_actions_disabled a { - cursor: default; -} -.pkt_ext_containersaved .pkt_ext_item_actions .pkt_ext_openpocket { - float: right; - padding-right: 0.7em; - text-align: right; -} -.pkt_ext_containersaved .pkt_ext_item_actions .pkt_ext_removeitem { - padding-left: 0; -} -.pkt_ext_containersaved .pkt_ext_close { - background: url(../img/tag_close@1x.png) center center no-repeat; - color: #333; - display: block; - font-size: 0.8em; - height: 10px; - right: 0.5em; - overflow: hidden; - position: absolute; - text-align: center; - text-indent: -9999px; - top: -1em; - width: 10px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersaved .pkt_ext_close { - background-image: url(../img/tag_close@2x.png); - background-size: 8px 8px; - } -} -.pkt_ext_containersaved .pkt_ext_close:hover { - color: #000; - text-decoration: none; -} - -/*=Tag entry ---------------------------------------------------------------------------------------- */ -.pkt_ext_containersaved .pkt_ext_tag_detail { - border: 1px solid #c1c1c1; - border-radius: 2px; - font-size: 16px; - clear: both; - margin: 1.25em 1em; - padding: 0; - display: flex; -} -.pkt_ext_containersaved .pkt_ext_tag_error { - border: none; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper { - box-sizing: border-box; - flex: 1; - background-color: #fff; - border-right: 1px solid #c3c3c3; - color: #333; - display: block; - float: none; - font-size: 0.875em; - list-style: none; - margin: 0; - overflow: hidden; - padding: 0.25em 0.5em; - width: 14em; - padding-left: 0.5em; - padding-right: 0.5em; -} -.pkt_ext_containersaved .pkt_ext_tag_error .pkt_ext_tag_input_wrapper { - border: 1px solid #d74345; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper .token-input-list { - display: block; - left: 0; - height: 1.7em; - overflow: hidden; - position: relative; - width: 60em; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper .token-input-list, -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper li { - font-size: 14px; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper li { - height: auto; - width: auto; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper li:before { - content: none; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper input { - border: 0; - box-shadow: none; - background-color: #fff; - color: #333; - font-size: 14px; - float: left; - line-height: normal; - height: auto; - min-height: 0; - min-width: 5em; - padding: 3px 2px 1px; - text-transform: none; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper input::placeholder { - color: #a9a9a9; - letter-spacing: normal; - text-transform: none; -} -.pkt_ext_containersaved .input_disabled { - cursor: default; - opacity: 0.5; -} -.pkt_ext_containersaved .pkt_ext_btn { - box-sizing: border-box; - color: #333; - float: none; - font-size: 0.875em; - font-size: 14px; - letter-spacing: normal; - height: 2.2em; - min-width: 4em; - padding: 0.5em 0; - text-decoration: none; - text-transform: none; - width: auto; -} -.pkt_ext_containersaved .pkt_ext_btn:hover { - background-color: #ebebeb; -} -.pkt_ext_containersaved .pkt_ext_btn:active { - background-color: #dadada; -} -.pkt_ext_containersaved .pkt_ext_btn_disabled, -.pkt_ext_containersaved .pkt_ext_btn_disabled:hover, -.pkt_ext_containersaved .pkt_ext_btn_disabled:active { - background-color: transparent; - cursor: default; - opacity: 0.4; -} -.pkt_ext_containersaved .pkt_ext_tag_error .pkt_ext_btn { - border: 1px solid #c3c3c3; - border-width: 1px 1px 1px 0; - height: 2.35em; -} -.pkt_ext_containersaved .autocomplete-suggestions { - margin-top: 2.2em; -} - -/*=Recent/suggested tags ---------------------------------------------------------------------------------------- */ -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detailshown { - border-top: 1px solid #c1c1c1; - bottom: 0; - box-sizing: border-box; - background: #ebebeb; - clear: both; - left: 0; - opacity: 0; - min-height: 110px; - position: fixed; - visibility: hidden; - width: 100%; -} -.pkt_ext_container_detailactive .pkt_ext_suggestedtag_detail, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detailshown { - opacity: 1; - visibility: visible; -} -.pkt_ext_containersaved .pkt_ext_suggestedtag_detailshown { - padding: 4px 0; -} -.pkt_ext_container_finalstate .pkt_ext_suggestedtag_detail { - opacity: 0; - visibility: hidden; -} -.pkt_ext_containersaved -.pkt_ext_containersaved .pkt_ext_recenttag_detail h4, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail h4 { - color: #333; - font-size: 0.8125em; - font-size: 13px; - font-weight: normal; - font-style: normal; - letter-spacing: normal; - margin: 0.5em 0; - text-align: left; - text-transform: none; -} -.pkt_ext_containersaved .pkt_ext_recenttag_detail .pkt_ext_loadingspinner, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail .pkt_ext_loadingspinner { - display: none; - position: absolute; -} -.pkt_ext_containersaved .pkt_ext_recenttag_detail_loading .pkt_ext_loadingspinner, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail_loading .pkt_ext_loadingspinner { - display: block; - font-size: 6px; - left: 48%; -} -.pkt_ext_containersaved .pkt_ext_recenttag_detail ul, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail ul { - display: block; - margin: 0; - height: 2em; - overflow: hidden; - padding: 2px 0 0 0; -} -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail ul { - height: auto; - margin: 0; - max-height: 4em; - padding-top: 6px; -} -.pkt_ext_containersaved .pkt_ext_recenttag_detail li, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail li { - background: none; - float: left; - height: inherit; - line-height: 1.5; - list-style: none; - margin-bottom: 0.5em; - width: inherit; -} -.pkt_ext_containersaved .pkt_ext_recenttag_detail li:before, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail li:before { - content: none; -} -.pkt_ext_containersaved .pkt_ext_recenttag_detail .recenttag_msg, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail .suggestedtag_msg { - color: #333; - font-size: 0.8125em; - line-height: 1.2; - left: auto; - position: absolute; - text-align: left; - top: 2em; -} -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail .suggestedtag_msg { - margin-right: 1.3em; -} -.pkt_ext_containersaved .token_tag { - border-radius: 4px; - background: #f7f7f7; - border: 1px solid #c3c3c3; - color: #333; - font-size: 0.875em; - font-size: 14px; - font-weight: normal; - letter-spacing: normal; - margin-right: 0.5em; - padding: 0.125em 0.625em; - text-decoration: none; - text-transform: none; -} -.pkt_ext_containersaved .token_tag:hover { - background-color: #008acb; - border-color: #008acb; - color: #fff; - text-decoration: none; -} -.pkt_ext_containersaved .token_tag:before, -.pkt_ext_containersaved .token_tag:after { - content: none; -} -.pkt_ext_containersaved .token_tag:hover span { - background-image: url(../img/tag_closeactive@1x.png); -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersaved .token_tag:hover span { - background-image: url(../img/tag_closeactive@2x.png); - background-size: 8px 8px; - } -} -.pkt_ext_containersaved .pkt_ext_recenttag_detail_disabled .token_tag, -.pkt_ext_containersaved .pkt_ext_recenttag_detail_disabled .token_tag:hover, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail_disabled .token_tag, -.pkt_ext_containersaved .pkt_ext_suggestedtag_detail_disabled .token_tag:hover { - background-color: #f7f7f7; - cursor: default; - opacity: 0.5; -} -.pkt_ext_containersaved .token_tag_inactive { - display: none; -} - -/*=Premium upsell ---------------------------------------------------------------------------------------- */ -.pkt_ext_detail .pkt_ext_premupsell { - background-color: #50bbb6; - display: block; - padding: 1.5em 0; - text-align: center; -} -.pkt_ext_premupsell h4 { - color: #fff; - font-size: 1em; - margin-bottom: 1em; -} -.pkt_ext_premupsell a { - color: #28605d; - border-bottom: 1px solid #47a7a3; - font-weight: normal; -} -.pkt_ext_premupsell a:hover { - color: #14302f; -} - -/*=Token input/autocomplete ---------------------------------------------------------------------------------------- */ -.token-input-dropdown-tag { - border-radius: 4px; - box-sizing: border-box; - background: #fff; - border: 1px solid #cdcdcd; - margin-top: 0.5em; - left: 0 !important; - overflow-y: auto; - top: 1.9em !important; - z-index: 9000; -} -.token-input-dropdown-tag ul { - height: inherit; - max-height: 115px; - margin: 0; - overflow: auto; - padding: 0.5em 0; -} -.token-input-dropdown-tag ul li { - background: none; - color: #333; - font-weight: normal; - font-size: 1em; - float: none; - height: inherit; - letter-spacing: normal; - list-style: none; - padding: 0.75em; - text-align: left; - text-transform: none; - width: inherit; -} -.token-input-dropdown-tag ul li:before { - content: none; -} -.token-input-dropdown ul li.token-input-selected-dropdown-item { - background-color: #008acb; - color: #fff; -} -.token-input-list { - list-style: none; - margin: 0; - padding: 0; -} -.token-input-list li { - text-align: left; - list-style: none; -} -.token-input-list li input { - border: 0; - background-color: white; -} -.pkt_ext_containersaved .token-input-token { - background: none; - border-radius: 4px; - border: 1px solid #c3c3c3; - overflow: hidden; - margin: 0; - padding: 0 8px; - background-color: #f7f7f7; - color: #000; - font-weight: normal; - cursor: default; - line-height: 1.5; - display: block; - width: auto; - margin: 0 0.2em; - float: left; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper_disabled { - position: relative; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper_disabled input { - opacity: 0.5; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper_disabled .token-input-list { - opacity: 0.5; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper_disabled .pkt_ext_tag_input_blocker { - height: 100%; - left: 0; - position: absolute; - top: 0; - width: 100%; - z-index: 5; -} -.pkt_ext_containersaved .token-input-token p { - display: inline-block; - font-size: 14px; - font-weight: normal; - line-height: inherit; - letter-spacing: normal; - padding: 0; - margin: 0; - text-transform: none; - vertical-align: top; - width: auto; -} -.pkt_ext_containersaved .token-input-token p:before { - content: none; - width: 0; -} -.pkt_ext_containersaved .token-input-token span { - background: url(../img/tag_close@1x.png) center center no-repeat; - cursor: pointer; - display: inline-block; - height: 8px; - margin: 0 0 0 8px; - overflow: hidden; - width: 8px; - text-indent: -99px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersaved .token-input-token span { - background-image: url(../img/tag_close@2x.png); - background-size: 8px 8px; - } -} -.pkt_ext_containersaved .token-input-selected-token { - background-color: #008acb; - border-color: #008acb; - color: #fff; -} -.pkt_ext_containersaved .token-input-selected-token span { - background-image: url(../img/tag_closeactive@1x.png); -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersaved .token-input-selected-token span { - background-image: url(../img/tag_closeactive@2x.png); - background-size: 8px 8px; - } -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper_disabled .token-input-selected-token { - background-color: #f7f7f7; -} -.pkt_ext_containersaved .pkt_ext_tag_input_wrapper_disabled .token-input-selected-token span { - color: #bbb; -} - -/*=Overflow mode ---------------------------------------------------------------------------------------- */ -.pkt_ext_saved_overflow .pkt_ext_logo { - float: none; - margin: 0.5em auto 0; -} -.pkt_ext_saved_overflow .pkt_ext_initload { - top: -8px; -} -.pkt_ext_saved_overflow .pkt_ext_loadingspinner { - top: 10em; -} -.pkt_ext_saved_overflow .pkt_ext_topdetail { - float: none; - margin: 0 auto; - padding: 0 1em; -} -.pkt_ext_saved_overflow h2 { - margin-bottom: 0.5em; - margin-top: 0; - text-align: center; -} -.pkt_ext_saved_overflow .pkt_ext_item_actions ul { - display: inline-block; - width: auto; -} -.pkt_ext_saved_overflow .pkt_ext_item_actions li { - float: none; - padding-left: 1em; - padding-right: 1em; - text-align: center; -} -.pkt_ext_saved_overflow .pkt_ext_item_actions .pkt_ext_removeitem, -.pkt_ext_saved_overflow .pkt_ext_item_actions .pkt_ext_openpocket { - float: none; - text-align: center; - padding-left: 0; - padding-right: 0; -} -.pkt_ext_saved_overflow .pkt_ext_item_actions .pkt_ext_actions_separator { - display: none; -} -.pkt_ext_saved_overflow .pkt_ext_tag_detail { - margin-top: 0; -} -.pkt_ext_saved_overflow .pkt_ext_suggestedtag_detail, -.pkt_ext_saved_overflow .pkt_ext_suggestedtag_detailshown { - top: 14.75em; -} -.pkt_ext_saved_overflow .pkt_ext_edit_msg { - top: 16em; -} -.pkt_ext_container_finalerrorstate.pkt_ext_saved_overflow .pkt_ext_errordetail { - box-sizing: border-box; - left: 0; - padding-left: 1em; - padding-right: 1em; - text-align: center; - top: 8.3em; - width: 100%; -} - -/*=Language overrides ---------------------------------------------------------------------------------------- */ -.pkt_ext_saved_es .pkt_ext_btn { - min-width: 5em; -} -.pkt_ext_saved_de .pkt_ext_btn, -.pkt_ext_saved_ru .pkt_ext_btn { - min-width: 6em; -} diff --git a/browser/extensions/pocket/content/panels/css/signup.css b/browser/extensions/pocket/content/panels/css/signup.css deleted file mode 100644 index 5c428a29b..000000000 --- a/browser/extensions/pocket/content/panels/css/signup.css +++ /dev/null @@ -1,424 +0,0 @@ -/* signup.css - * - * Description: - * With base elements out of the way, this sets all custom styling for the extension. - * - * Contents: - * Global - * Core detail - * Core detail - storyboard - * Buttons - * Overflow mode - * Language overrides - */ - -/*=Global ---------------------------------------------------------------------------------------- */ -.pkt_ext_containersignup { - background-color: #ebebeb; - color: #333; - display: block; - font-size: 16px; - font-family: "FiraSans", "Helvetica Neue", Helvetica, Arial, sans-serif; - margin: 0; - padding: 0; - position: relative; - text-align: center; -} -.pkt_ext_containersignup_inactive { - animation: pkt_ext_hide 0.3s ease-out; - opacity: 0; - visibility: hidden; -} -.pkt_ext_cf:after { - content: " "; - display: table; - clear: both; -} -@keyframes pkt_ext_hide { - 0% { - opacity: 1; - visibility: visible; - } - 99% { - opacity: 0; - visibility: visible; - } - 100% { - opacity: 0; - visibility: hidden; - } -} - -/*=Core detail ---------------------------------------------------------------------------------------- */ -.pkt_ext_containersignup p { - font-size: 14px; - color: #333; - font-family: "FiraSans", "Helvetica Neue", Helvetica, Arial, sans-serif; - line-height: 1.3; - margin: 0 auto 1.5em; - max-width: 260px; -} -.pkt_ext_containersignup a { - color: #4c8fd0; -} -.pkt_ext_containersignup a:hover { - color: #3076b9; -} -.pkt_ext_containersignup .pkt_ext_introdetail { - background-color: #fbfbfb; - border: 1px solid #c1c1c1; - border-width: 0 0 1px; -} -.pkt_ext_containersignup .pkt_ext_logo { - background: url(../img/pocketlogo@1x.png) center bottom no-repeat; - display: block; - height: 32px; - margin: 0 auto 15px; - padding-top: 25px; - position: relative; - text-indent: -9999px; - width: 123px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersignup .pkt_ext_logo { - background-image: url(../img/pocketlogo@2x.png); - background-size: 123px 32px; - } -} -.pkt_ext_containersignup .pkt_ext_introimg { - background: url(../img/pocketsignup_hero@1x.png) center center no-repeat; - display: block; - height: 125px; - margin: 0 auto; - position: relative; - text-indent: -9999px; - width: 255px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersignup .pkt_ext_introimg { - background-image: url(../img/pocketsignup_hero@2x.png); - background-size: 255px 125px; - } -} -.pkt_ext_containersignup .pkt_ext_tagline { - margin-bottom: 0.5em; -} -.pkt_ext_containersignup .pkt_ext_learnmore { - font-size: 12px; -} -.pkt_ext_containersignup .pkt_ext_learnmoreinactive { - visibility: hidden; -} -.pkt_ext_signupdetail h4 { - font-size: 12px; - font-weight: normal; -} -.pkt_ext_signupdetail .btn-container { - position: relative; - margin-bottom: 0.8em; -} -.pkt_ext_containersignup .ff_signuphelp { - background: url(../img/signup_help@1x.png) center center no-repeat; - display: block; - height: 18px; - margin-top: -9px; - right: -15px; - position: absolute; - text-indent: -9999px; - width: 18px; - top: 50%; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersignup .ff_signuphelp { - background-image: url(../img/signup_help@2x.png); - background-size: 18px 18px; - } -} -.pkt_ext_containersignup .alreadyhave { - font-size: 12px; - max-width: 320px; - margin-top: 15px; -} -.pkt_ext_containersignup .tryitnowspace { - margin-top: 22px; -} -.pkt_ext_signupdetail p.pkt_ext_tos { - color: #777; - font-size: 10px; - line-height: 1.5; - margin-top: 17px; - padding-top: 0; - max-width: 190px; -} - -/*=Core detail - storyboard ---------------------------------------------------------------------------------------- */ -.pkt_ext_introstory { - align-items: center; - display: flex; - padding: 20px; -} -.pkt_ext_introstory:after { - clear: both; - content: ""; - display: table; -} -.pkt_ext_introstory p { - margin-bottom: 0; - text-align: left; -} -.pkt_ext_introstoryone { - padding: 20px 18px 15px 20px; -} -.pkt_ext_introstorytwo { - padding: 3px 0 0 20px; -} -.pkt_ext_introstorytwo .pkt_ext_tagline { - margin-bottom: 1.5em; -} -.pkt_ext_introstory_text { - flex: 1; -} -.pkt_ext_introstoryone_img, -.pkt_ext_introstorytwo_img { - display: block; - overflow: hidden; - position: relative; - text-indent: -999px; -} -.pkt_ext_introstoryone_img { - background: url(../img/pocketsignup_button@1x.png) center right no-repeat; - height: 82px; - padding: 0 0 0 0.7em; - width: 82px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_introstoryone_img { - background-image: url(../img/pocketsignup_button@2x.png); - background-size: 82px 82px; - } -} -.pkt_ext_introstorytwo_img { - background: url(../img/pocketsignup_devices@1x.png) bottom right no-repeat; - height: 110px; - padding: 1em 0 0 0.7em; - width: 124px; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_introstorytwo_img { - background-image: url(../img/pocketsignup_devices@2x.png); - background-size: 124px 110px; - } -} -.pkt_ext_introstorydivider { - border-top: 1px solid #c1c1c1; - height: 1px; - margin: 0 auto; - width: 125px; -} - -/*=Buttons ---------------------------------------------------------------------------------------- */ -.pkt_ext_containersignup .btn { - background-color: #0096dd; - border: 1px solid #0095dd; - border-radius: 2px; - color: #fff; - display: inline-block; - font-family: "FiraSans", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 16px; - font-weight: normal; - line-height: 1; - margin: 0; - padding: 11px 45px; - text-align: center; - text-decoration: none; - text-shadow: 0 -1px 0 rgba(142,4,17,0.5); - transition: background-color 0.1s linear; - width: auto; -} -.pkt_ext_containersignup .btn-secondary { - background-color: #fbfbfb; - border-color: #c1c1c1; - color: #444; - text-shadow: 0 1px 0 rgba(255,255,255,0.5); -} -.pkt_ext_containersignup .btn-small { - padding: 6px 20px; -} -.pkt_ext_containersignup .btn-mini { - font-size: 14px; - padding: 5px 15px 4px; -} -.pkt_ext_containersignup .btn:hover { - background-color: #008acb; - color: #fff; - text-decoration: none; -} -.pkt_ext_containersignup .btn-secondary:hover, -.pkt_ext_containersignup .btn-important:hover { - background-color: #f6f6f6; - color: #222; -} -.pkt_ext_containersignup .btn-disabled { - background-image: none; - color: #ccc; - color: rgba(255,255,255,0.6); - cursor: default; - opacity: 0.9; -} -.pkt_ext_containersignup .signup-btn-firefox, -.pkt_ext_containersignup .signup-btn-tryitnow, -.pkt_ext_containersignup .signup-btn-email, -.pkt_ext_containersignup .signupinterim-btn-login, -.pkt_ext_containersignup .signupinterim-btn-signup, -.pkt_ext_containersignup .forgot-btn-submit, -.pkt_ext_containersignup .forgotreset-btn-change { - min-width: 12.125em; - padding: 0.8em 1.1875em; - box-sizing: content-box; -} -.pkt_ext_containersignup .signup-btn-email { - position: relative; - z-index: 10; -} -.pkt_ext_containersignup .signup-btn-tryitnow, -.pkt_ext_containersignup .signup-btn-firefox { - min-width: 14.5em; - position: relative; - padding: 0; -} -.pkt_ext_containersignup .signup-btn-tryitnow{ - margin-top: 25px; -} -.pkt_ext_containersignup .signup-btn-firefox .logo { - background: url(../img/signup_firefoxlogo@1x.png) center center no-repeat; - height: 2.6em; - left: 10px; - margin: 0; - padding: 0; - width: 22px; - position: absolute; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_containersignup .signup-btn-firefox .logo { - background-image: url(../img/signup_firefoxlogo@2x.png); - background-size: 22px 22px; - } -} -.pkt_ext_containersignup .forgotreset-btn-change { - margin-bottom: 2em; -} -.pkt_ext_containersignup .signup-btn-tryitnow .text, -.pkt_ext_containersignup .signup-btn-firefox .text { - display: inline-block; - padding: 0.8em 1.625em; - position: relative; - text-shadow: none; - white-space: nowrap; -} -.pkt_ext_containersignup .signup-btn-tryitnow .text, -.pkt_ext_containersignup .signup-btn-firefox .text { - color: #fff; -} -.pkt_ext_containersignup .btn-disabled .text { - color: #ccc; - color: rgba(255,255,255,0.6); -} - -/*=Overflow mode ---------------------------------------------------------------------------------------- */ -.pkt_ext_signup_overflow .pkt_ext_tagline { - margin-bottom: 1em; - padding: 0 1em; -} -.pkt_ext_signup_overflow .pkt_ext_introimg { - background-size: 200px 98px; - height: 98px; - width: 200px; -} -.pkt_ext_signup_overflow .signup-btn-firefox, -.pkt_ext_containersignup .signup-btn-tryitnow, -.pkt_ext_signup_overflow .signup-btn-email { - font-size: 14px; - min-width: 12.6em; - padding-left: 0.75em; - padding-right: 0.75em; -} -.pkt_ext_signup_overflow .signup-btn-tryitnow .text, -.pkt_ext_signup_overflow .signup-btn-firefox .text { - padding-left: 0; - padding-right: 0; -} - -/*=Language overrides ---------------------------------------------------------------------------------------- */ -.pkt_ext_signup_de .pkt_ext_introstoryone_img { - margin-right: -5px; - padding-left: 0; -} -.pkt_ext_signup_de .pkt_ext_introstorytwo .pkt_ext_tagline, -.pkt_ext_signup_es .pkt_ext_introstorytwo .pkt_ext_tagline, -.pkt_ext_signup_ja .pkt_ext_introstorytwo .pkt_ext_tagline, -.pkt_ext_signup_ru .pkt_ext_introstorytwo .pkt_ext_tagline { - margin-bottom: 0.5em; -} -.pkt_ext_signup_de .signup-btn-firefox .text, -.pkt_ext_signup_de .signup-btn-tryitnow .text, -.pkt_ext_signup_de .signup-btn-email, -.pkt_ext_signup_es .pkt_ext_signupdetail_hero .signup-btn-firefox .text, -.pkt_ext_signup_es .pkt_ext_signupdetail_hero .signup-btn-email, -.pkt_ext_signup_ja .signup-btn-firefox .text, -.pkt_ext_signup_ja .signup-btn-tryitnow .text, -.pkt_ext_signup_ja .signup-btn-email, -.pkt_ext_signup_ru .signup-btn-firefox .text, -.pkt_ext_signup_ru .signup-btn-tryitnow .text, -.pkt_ext_signup_ru .signup-btn-email { - font-size: 15px; -} -.pkt_ext_signup_ja .signup-btn-firefox .text, -.pkt_ext_signup_ja .signup-btn-tryitnow .text, -.pkt_ext_signup_ru .signup-btn-firefox .text, -.pkt_ext_signup_ru .signup-btn-tryitnow .text { - left: 15px; -} -.pkt_ext_signup_de .signup-btn-firefox .logo, -.pkt_ext_signup_es .pkt_ext_signupdetail_hero .signup-btn-firefox .logo, -.pkt_ext_signup_ja .signup-btn-firefox .logo, -.pkt_ext_signup_ru .signup-btn-firefox .logo { - height: 2.4em; -} -@media (min-resolution: 1.1dppx) { - .pkt_ext_signup_de .signup-btn-firefox .logo, - .pkt_ext_signup_es .pkt_ext_signupdetail_hero .signup-btn-firefox .logo, - .pkt_ext_signup_ja .signup-btn-firefox .logo, - .pkt_ext_signup_ru .signup-btn-firefox .logo { - height: 2.5em; - } -} -.pkt_ext_signup_de .signup-btn-email, -.pkt_ext_signup_es .pkt_ext_signupdetail_hero .signup-btn-email, -.pkt_ext_signup_ja .signup-btn-email, -.pkt_ext_signup_ru .signup-btn-email { - min-width: 13em; - padding: 0.8533em 1.2667em; -} -.pkt_ext_signup_de .pkt_ext_logo, -.pkt_ext_signup_es .pkt_ext_logo, -.pkt_ext_signup_ru .pkt_ext_logo { - padding-top: 15px; -} -.pkt_ext_signup_de .pkt_ext_introdetailhero .pkt_ext_tagline, -.pkt_ext_signup_es .pkt_ext_introdetailhero .pkt_ext_tagline, -.pkt_ext_signup_ja .pkt_ext_introdetailhero .pkt_ext_tagline, -.pkt_ext_signup_ru .pkt_ext_introdetailhero .pkt_ext_tagline { - font-size: 13px; -} -.pkt_ext_signup_overflow.pkt_ext_signup_de .signup-btn-firefox .logo, -.pkt_ext_signup_overflow.pkt_ext_signup_es .signup-btn-firefox .logo, -.pkt_ext_signup_overflow.pkt_ext_signup_ja .signup-btn-firefox .logo, -.pkt_ext_signup_overflow.pkt_ext_signup_ru .signup-btn-firefox .logo { - display: none; -} diff --git a/browser/extensions/pocket/content/panels/fonts/FiraSans-Regular.woff b/browser/extensions/pocket/content/panels/fonts/FiraSans-Regular.woff deleted file mode 100644 index f466cdda9..000000000 Binary files a/browser/extensions/pocket/content/panels/fonts/FiraSans-Regular.woff and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocket.svg b/browser/extensions/pocket/content/panels/img/pocket.svg deleted file mode 100644 index d93fd6a15..000000000 --- a/browser/extensions/pocket/content/panels/img/pocket.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - diff --git a/browser/extensions/pocket/content/panels/img/pocketerror@1x.png b/browser/extensions/pocket/content/panels/img/pocketerror@1x.png deleted file mode 100644 index e2b4d04de..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketerror@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketerror@2x.png b/browser/extensions/pocket/content/panels/img/pocketerror@2x.png deleted file mode 100644 index d501503b0..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketerror@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketlogo@1x.png b/browser/extensions/pocket/content/panels/img/pocketlogo@1x.png deleted file mode 100644 index 62b3db310..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketlogo@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketlogo@2x.png b/browser/extensions/pocket/content/panels/img/pocketlogo@2x.png deleted file mode 100644 index b0e80bff3..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketlogo@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketlogosolo@1x.png b/browser/extensions/pocket/content/panels/img/pocketlogosolo@1x.png deleted file mode 100644 index 77dc16f8c..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketlogosolo@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketlogosolo@2x.png b/browser/extensions/pocket/content/panels/img/pocketlogosolo@2x.png deleted file mode 100644 index c467c5a29..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketlogosolo@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketmenuitem16.png b/browser/extensions/pocket/content/panels/img/pocketmenuitem16.png deleted file mode 100644 index b52db6abf..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketmenuitem16.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketmenuitem16@2x.png b/browser/extensions/pocket/content/panels/img/pocketmenuitem16@2x.png deleted file mode 100644 index 69aa55b03..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketmenuitem16@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketsignup_button@1x.png b/browser/extensions/pocket/content/panels/img/pocketsignup_button@1x.png deleted file mode 100644 index 12326fae3..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketsignup_button@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketsignup_button@2x.png b/browser/extensions/pocket/content/panels/img/pocketsignup_button@2x.png deleted file mode 100644 index 5bdebc5e9..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketsignup_button@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketsignup_devices@1x.png b/browser/extensions/pocket/content/panels/img/pocketsignup_devices@1x.png deleted file mode 100644 index c4a7ad677..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketsignup_devices@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketsignup_devices@2x.png b/browser/extensions/pocket/content/panels/img/pocketsignup_devices@2x.png deleted file mode 100644 index 157304c3e..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketsignup_devices@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketsignup_hero@1x.png b/browser/extensions/pocket/content/panels/img/pocketsignup_hero@1x.png deleted file mode 100644 index 80c5bd486..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketsignup_hero@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/pocketsignup_hero@2x.png b/browser/extensions/pocket/content/panels/img/pocketsignup_hero@2x.png deleted file mode 100644 index 36d0add61..000000000 Binary files a/browser/extensions/pocket/content/panels/img/pocketsignup_hero@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/signup_firefoxlogo@1x.png b/browser/extensions/pocket/content/panels/img/signup_firefoxlogo@1x.png deleted file mode 100644 index 52cbe052c..000000000 Binary files a/browser/extensions/pocket/content/panels/img/signup_firefoxlogo@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/signup_firefoxlogo@2x.png b/browser/extensions/pocket/content/panels/img/signup_firefoxlogo@2x.png deleted file mode 100644 index cd218805e..000000000 Binary files a/browser/extensions/pocket/content/panels/img/signup_firefoxlogo@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/signup_help@1x.png b/browser/extensions/pocket/content/panels/img/signup_help@1x.png deleted file mode 100644 index 5019025c0..000000000 Binary files a/browser/extensions/pocket/content/panels/img/signup_help@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/signup_help@2x.png b/browser/extensions/pocket/content/panels/img/signup_help@2x.png deleted file mode 100644 index 6714bb3bc..000000000 Binary files a/browser/extensions/pocket/content/panels/img/signup_help@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/signup_or@1x.png b/browser/extensions/pocket/content/panels/img/signup_or@1x.png deleted file mode 100644 index 318cea0f6..000000000 Binary files a/browser/extensions/pocket/content/panels/img/signup_or@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/signup_or@2x.png b/browser/extensions/pocket/content/panels/img/signup_or@2x.png deleted file mode 100644 index 837f1814a..000000000 Binary files a/browser/extensions/pocket/content/panels/img/signup_or@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/tag_close@1x.png b/browser/extensions/pocket/content/panels/img/tag_close@1x.png deleted file mode 100644 index 2dd02ba02..000000000 Binary files a/browser/extensions/pocket/content/panels/img/tag_close@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/tag_close@2x.png b/browser/extensions/pocket/content/panels/img/tag_close@2x.png deleted file mode 100644 index 8bd0eec57..000000000 Binary files a/browser/extensions/pocket/content/panels/img/tag_close@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/tag_closeactive@1x.png b/browser/extensions/pocket/content/panels/img/tag_closeactive@1x.png deleted file mode 100644 index ad4239232..000000000 Binary files a/browser/extensions/pocket/content/panels/img/tag_closeactive@1x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/img/tag_closeactive@2x.png b/browser/extensions/pocket/content/panels/img/tag_closeactive@2x.png deleted file mode 100644 index 80c35e3aa..000000000 Binary files a/browser/extensions/pocket/content/panels/img/tag_closeactive@2x.png and /dev/null differ diff --git a/browser/extensions/pocket/content/panels/js/messages.js b/browser/extensions/pocket/content/panels/js/messages.js deleted file mode 100644 index ae08c3e73..000000000 --- a/browser/extensions/pocket/content/panels/js/messages.js +++ /dev/null @@ -1,78 +0,0 @@ -// Documentation of methods used here are at: -// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Interaction_between_privileged_and_non-privileged_pages - -var pktPanelMessaging = (function() { - - function panelIdFromURL(url) { - var panelId = url.match(/panelId=([\w|\d|\.]*)&?/); - if (panelId && panelId.length > 1) { - return panelId[1]; - } - - return 0; - } - - function prefixedMessageId(messageId) { - return 'PKT_' + messageId; - } - - function panelPrefixedMessageId(panelId, messageId) { - return prefixedMessageId(panelId + '_' + messageId); - } - - function addMessageListener(panelId, messageId, callback) { - document.addEventListener(panelPrefixedMessageId(panelId, messageId), function(e) { - - callback(JSON.parse(e.target.getAttribute("payload"))[0]); - - // TODO: Figure out why e.target.parentNode is null - // e.target.parentNode.removeChild(e.target); - - }, false); - - } - - function removeMessageListener(panelId, messageId, callback) { - document.removeEventListener(panelPrefixedMessageId(panelId, messageId), callback); - } - - function sendMessage(panelId, messageId, payload, callback) { - // Payload needs to be an object in format: - // { panelId: panelId, data: {} } - var messagePayload = { - panelId: panelId, - data: (payload || {}) - }; - - // Create a callback to listen for a response - if (callback) { - var messageResponseId = messageId + "Response"; - var responseListener = function(responsePayload) { - callback(responsePayload); - removeMessageListener(panelId, messageResponseId, responseListener); - } - - addMessageListener(panelId, messageResponseId, responseListener); - } - - // Send message - var element = document.createElement("PKTMessageFromPanelElement"); - element.setAttribute("payload", JSON.stringify([messagePayload])); - document.documentElement.appendChild(element); - - var evt = document.createEvent("Events"); - evt.initEvent(prefixedMessageId(messageId), true, false); - element.dispatchEvent(evt); - } - - - /** - * Public functions - */ - return { - panelIdFromURL: panelIdFromURL, - addMessageListener : addMessageListener, - removeMessageListener : removeMessageListener, - sendMessage: sendMessage - }; -}()); diff --git a/browser/extensions/pocket/content/panels/js/saved.js b/browser/extensions/pocket/content/panels/js/saved.js deleted file mode 100644 index 3abc8889a..000000000 --- a/browser/extensions/pocket/content/panels/js/saved.js +++ /dev/null @@ -1,608 +0,0 @@ -/* -PKT_SAVED_OVERLAY is the view itself and contains all of the methods to manipute the overlay and messaging. -It does not contain any logic for saving or communication with the extension or server. -*/ -var PKT_SAVED_OVERLAY = function (options) -{ - var myself = this; - this.inited = false; - this.active = false; - this.wrapper = null; - this.pockethost = "getpocket.com"; - this.savedItemId = 0; - this.savedUrl = ''; - this.premiumStatus = false; - this.preventCloseTimerCancel = false; - this.closeValid = true; - this.mouseInside = false; - this.autocloseTimer = null; - this.inoverflowmenu = false; - this.dictJSON = {}; - this.autocloseTiming = 3500; - this.autocloseTimingFinalState = 2000; - this.mouseInside = false; - this.userTags = []; - this.cxt_suggested_available = 0; - this.cxt_entered = 0; - this.cxt_suggested = 0; - this.cxt_removed = 0; - this.justaddedsuggested = false; - this.fillTagContainer = function(tags, container, tagclass) { - container.children().remove(); - for (var i = 0; i < tags.length; i++) { - var newtag = $('
  • '); - newtag.find('a').text(tags[i]); - newtag.addClass(tagclass); - container.append(newtag); - this.cxt_suggested_available++; - } - }; - this.fillUserTags = function() { - thePKT_SAVED.sendMessage("getTags", {}, function(resp) - { - if (typeof resp == 'object' && typeof resp.tags == 'object') - { - myself.userTags = resp.tags; - } - }); - }; - this.fillSuggestedTags = function() - { - if (!$('.pkt_ext_suggestedtag_detail').length) - { - myself.suggestedTagsLoaded = true; - myself.startCloseTimer(); - return; - } - - thePKT_SAVED.sendMessage("getSuggestedTags", - { - url: myself.savedUrl - }, function(resp) - { - $('.pkt_ext_suggestedtag_detail').removeClass('pkt_ext_suggestedtag_detail_loading'); - if (resp.status == 'success') - { - var newtags = []; - for (var i = 0; i < resp.value.suggestedTags.length; i++) - { - newtags.push(resp.value.suggestedTags[i].tag); - } - myself.suggestedTagsLoaded = true; - if (!myself.mouseInside) { - myself.startCloseTimer(); - } - myself.fillTagContainer(newtags, $('.pkt_ext_suggestedtag_detail ul'), 'token_suggestedtag'); - } - else if (resp.status == 'error') { - var msg = $('

    '); - msg.text(resp.error.message); - $('.pkt_ext_suggestedtag_detail').append(msg); - this.suggestedTagsLoaded = true; - if (!myself.mouseInside) { - myself.startCloseTimer(); - } - } - }); - } - this.initAutoCloseEvents = function() { - this.wrapper.on('mouseenter', function() { - myself.mouseInside = true; - myself.stopCloseTimer(); - }); - this.wrapper.on('mouseleave', function() { - myself.mouseInside = false; - myself.startCloseTimer(); - }); - this.wrapper.on('click', function(e) { - myself.closeValid = false; - }); - }; - this.startCloseTimer = function(manualtime) - { - var settime = manualtime ? manualtime : myself.autocloseTiming; - if (typeof myself.autocloseTimer == 'number') - { - clearTimeout(myself.autocloseTimer); - } - myself.autocloseTimer = setTimeout(function() - { - if (myself.closeValid || myself.preventCloseTimerCancel) - { - myself.preventCloseTimerCancel = false; - myself.closePopup(); - } - }, settime); - }; - this.stopCloseTimer = function() - { - if (myself.preventCloseTimerCancel) - { - return; - } - clearTimeout(myself.autocloseTimer); - }; - this.closePopup = function() { - myself.stopCloseTimer(); - thePKT_SAVED.sendMessage("close"); - }; - this.checkValidTagSubmit = function() { - var inputlength = $.trim($('.pkt_ext_tag_input_wrapper').find('.token-input-input-token').children('input').val()).length; - if ($('.pkt_ext_containersaved').find('.token-input-token').length || (inputlength > 0 && inputlength < 26)) - { - $('.pkt_ext_containersaved').find('.pkt_ext_btn').removeClass('pkt_ext_btn_disabled'); - } - else - { - $('.pkt_ext_containersaved').find('.pkt_ext_btn').addClass('pkt_ext_btn_disabled'); - } - myself.updateSlidingTagList(); - }; - this.updateSlidingTagList = function() { - var inputleft = $('.token-input-input-token input').position().left; - var listleft = $('.token-input-list').position().left; - var listleftmanual = parseInt($('.token-input-list').css('left')); - var listleftnatural = listleft - listleftmanual; - var leftwidth = $('.pkt_ext_tag_input_wrapper').outerWidth(); - - if ((inputleft + listleft + 20) > leftwidth) - { - $('.token-input-list').css('left', Math.min(((inputleft + listleftnatural - leftwidth + 20)*-1), 0) + 'px'); - } - else - { - $('.token-input-list').css('left', '0'); - } - }; - this.checkPlaceholderStatus = function() { - if (this.wrapper.find('.pkt_ext_tag_input_wrapper').find('.token-input-token').length) - { - this.wrapper.find('.token-input-input-token input').attr('placeholder', ''); - } - else - { - this.wrapper.find('.token-input-input-token input').attr('placeholder', $('.pkt_ext_tag_input').attr('placeholder')).css('width', '200px'); - } - }; - this.initTagInput = function() { - var inputwrapper = $('.pkt_ext_tag_input_wrapper'); - inputwrapper.find('.pkt_ext_tag_input').tokenInput([], { - searchDelay: 200, - minChars: 1, - animateDropdown: false, - noResultsHideDropdown: true, - scrollKeyboard: true, - emptyInputLength: 200, - search_function: function(term, cb) { - var returnlist = []; - if (term.length) { - var limit = 15; - var r = new RegExp('^' + term); - for (var i = 0; i < myself.userTags.length; i++) { - if (r.test(myself.userTags[i]) && limit > 0) { - returnlist.push({name:myself.userTags[i]}); - limit--; - } - } - } - if (!$('.token-input-dropdown-tag').data('init')) { - $('.token-input-dropdown-tag').css('width', inputwrapper.outerWidth()).data('init'); - inputwrapper.append($('.token-input-dropdown-tag')); - } - cb(returnlist); - }, - textToData: function(text) { - if ($.trim(text).length > 25 || !$.trim(text).length) { - if (text.length > 25) { - myself.showTagsError(myself.dictJSON.maxtaglength); - changestamp = Date.now(); - setTimeout(function() { - $('.token-input-input-token input').val(text).focus(); - }, 10); - } - return null; - } - myself.hideTagsError(); - return {name:myself.sanitizeText(text.toLowerCase())}; - }, - onReady: function() { - $('.token-input-dropdown').addClass('token-input-dropdown-tag'); - inputwrapper.find('.token-input-input-token input').attr('placeholder', $('.tag-input').attr('placeholder')).css('width', '200px'); - if ($('.pkt_ext_suggestedtag_detail').length) { - myself.wrapper.find('.pkt_ext_suggestedtag_detail').on('click', '.token_tag', function(e) { - e.preventDefault(); - var tag = $(e.target); - if ($(this).parents('.pkt_ext_suggestedtag_detail_disabled').length) { - return; - } - myself.justaddedsuggested = true; - inputwrapper.find('.pkt_ext_tag_input').tokenInput('add', {id:inputwrapper.find('.token-input-token').length, name:tag.text()}); - tag.addClass('token-suggestedtag-inactive'); - $('.token-input-input-token input').focus(); - }); - } - $('.token-input-list').on('keydown', 'input', function(e) { - if (e.which == 37) { - myself.updateSlidingTagList(); - } - }).on('keypress', 'input', function(e) { - if (e.which == 13) { - if (typeof changestamp == 'undefined' || (Date.now() - changestamp > 250)) { - e.preventDefault(); - myself.wrapper.find('.pkt_ext_btn').trigger('click'); - } - } - }).on('keyup', 'input', function(e) { - myself.checkValidTagSubmit(); - }); - myself.checkPlaceholderStatus(); - }, - onAdd: function() { - myself.checkValidTagSubmit(); - changestamp = Date.now(); - myself.hideInactiveTags(); - myself.checkPlaceholderStatus(); - }, - onDelete: function() { - myself.checkValidTagSubmit(); - changestamp = Date.now(); - myself.showActiveTags(); - myself.checkPlaceholderStatus(); - }, - onShowDropdown: function() { - thePKT_SAVED.sendMessage("expandSavePanel"); - }, - onHideDropdown: function() { - thePKT_SAVED.sendMessage("collapseSavePanel"); - } - }); - $('body').on('keydown', function(e) { - var key = e.keyCode || e.which; - if (key == 8) { - var selected = $('.token-input-selected-token'); - if (selected.length) { - e.preventDefault(); - e.stopImmediatePropagation(); - inputwrapper.find('.pkt_ext_tag_input').tokenInput('remove', {name:selected.find('p').text()}); - } - } - else if ($(e.target).parent().hasClass('token-input-input-token')) { - e.stopImmediatePropagation(); - } - }); - }; - this.disableInput = function() { - this.wrapper.find('.pkt_ext_item_actions').addClass('pkt_ext_item_actions_disabled'); - this.wrapper.find('.pkt_ext_btn').addClass('pkt_ext_btn_disabled'); - this.wrapper.find('.pkt_ext_tag_input_wrapper').addClass('pkt_ext_tag_input_wrapper_disabled'); - if (this.wrapper.find('.pkt_ext_suggestedtag_detail').length) { - this.wrapper.find('.pkt_ext_suggestedtag_detail').addClass('pkt_ext_suggestedtag_detail_disabled'); - } - }; - this.enableInput = function() { - this.wrapper.find('.pkt_ext_item_actions').removeClass('pkt_ext_item_actions_disabled'); - this.checkValidTagSubmit(); - this.wrapper.find('.pkt_ext_tag_input_wrapper').removeClass('pkt_ext_tag_input_wrapper_disabled'); - if (this.wrapper.find('.pkt_ext_suggestedtag_detail').length) { - this.wrapper.find('.pkt_ext_suggestedtag_detail').removeClass('pkt_ext_suggestedtag_detail_disabled'); - } - }; - this.initAddTagInput = function() { - $('.pkt_ext_btn').click(function(e) { - e.preventDefault(); - if ($(this).hasClass('pkt_ext_btn_disabled') || $('.pkt_ext_edit_msg_active').filter('.pkt_ext_edit_msg_error').length) - { - return; - } - myself.disableInput(); - $('.pkt_ext_containersaved').find('.pkt_ext_detail h2').text(myself.dictJSON.processingtags); - var originaltags = []; - $('.token-input-token').each(function() - { - var text = $.trim($(this).find('p').text()); - if (text.length) - { - originaltags.push(text); - } - }); - - thePKT_SAVED.sendMessage("addTags", - { - url: myself.savedUrl, - tags: originaltags - }, function(resp) - { - if (resp.status == 'success') - { - myself.showStateFinalMsg(myself.dictJSON.tagssaved); - } - else if (resp.status == 'error') - { - $('.pkt_ext_edit_msg').addClass('pkt_ext_edit_msg_error pkt_ext_edit_msg_active').text(resp.error.message); - } - }); - }); - }; - this.initRemovePageInput = function() { - $('.pkt_ext_removeitem').click(function(e) { - if ($(this).parents('.pkt_ext_item_actions_disabled').length) { - e.preventDefault(); - return; - } - if ($(this).hasClass('pkt_ext_removeitem')) { - e.preventDefault(); - myself.disableInput(); - $('.pkt_ext_containersaved').find('.pkt_ext_detail h2').text(myself.dictJSON.processingremove); - - thePKT_SAVED.sendMessage("deleteItem", - { - itemId: myself.savedItemId - }, function(resp) { - if (resp.status == 'success') { - myself.showStateFinalMsg(myself.dictJSON.pageremoved); - } - else if (resp.status == 'error') { - $('.pkt_ext_edit_msg').addClass('pkt_ext_edit_msg_error pkt_ext_edit_msg_active').text(resp.error.message); - } - }); - } - }); - }; - this.initOpenListInput = function() { - $('.pkt_ext_openpocket').click(function(e) - { - e.preventDefault(); - thePKT_SAVED.sendMessage("openTabWithUrl", - { - url: $(this).attr('href'), - activate: true - }); - myself.closePopup(); - }); - }; - this.showTagsError = function(msg) { - $('.pkt_ext_edit_msg').addClass('pkt_ext_edit_msg_error pkt_ext_edit_msg_active').text(msg); - $('.pkt_ext_tag_detail').addClass('pkt_ext_tag_error'); - }; - this.hideTagsError = function(msg) { - $('.pkt_ext_edit_msg').removeClass('pkt_ext_edit_msg_error pkt_ext_edit_msg_active').text(''); - $('.pkt_ext_tag_detail').removeClass('pkt_ext_tag_error'); - }; - this.showActiveTags = function() { - if (!$('.pkt_ext_suggestedtag_detail').length) { - return; - } - var activetokenstext = '|'; - $('.token-input-token').each(function(index, element) { - activetokenstext += $(element).find('p').text() + '|'; - }); - - var inactivetags = $('.pkt_ext_suggestedtag_detail').find('.token_tag_inactive'); - inactivetags.each(function(index, element) { - if (activetokenstext.indexOf('|' + $(element).text() + '|') == -1) { - $(element).removeClass('token_tag_inactive'); - } - }); - }; - this.hideInactiveTags = function() { - if (!$('.pkt_ext_suggestedtag_detail').length) { - return; - } - var activetokenstext = '|'; - $('.token-input-token').each(function(index, element) { - activetokenstext += $(element).find('p').text() + '|'; - }); - var activesuggestedtags = $('.token_tag').not('.token_tag_inactive'); - activesuggestedtags.each(function(index, element) { - if (activetokenstext.indexOf('|' + $(element).text() + '|') > -1) { - $(element).addClass('token_tag_inactive'); - } - }); - }; - this.showStateSaved = function(initobj) { - this.wrapper.find('.pkt_ext_detail h2').text(this.dictJSON.pagesaved); - this.wrapper.find('.pkt_ext_btn').addClass('pkt_ext_btn_disabled'); - if (typeof initobj.item == 'object') - { - this.savedItemId = initobj.item.item_id; - this.savedUrl = initobj.item.given_url; - } - $('.pkt_ext_containersaved').addClass('pkt_ext_container_detailactive').removeClass('pkt_ext_container_finalstate'); - - myself.fillUserTags(); - if (myself.suggestedTagsLoaded) { - myself.startCloseTimer(); - } - else { - myself.fillSuggestedTags(); - } - }; - this.sanitizeText = function(s) { - var sanitizeMap = { - "&": "&", - "<": "<", - ">": ">", - '"': '"', - "'": ''' - }; - if (typeof s !== 'string') - { - return ''; - } - return String(s).replace(/[&<>"']/g, function (str) { - return sanitizeMap[str]; - }); - }; - this.showStateFinalMsg = function(msg) { - this.wrapper.find('.pkt_ext_tag_detail').one('webkitTransitionEnd transitionend msTransitionEnd oTransitionEnd', function(e) - { - $(this).off('webkitTransitionEnd transitionend msTransitionEnd oTransitionEnd'); - myself.preventCloseTimerCancel = true; - myself.startCloseTimer(myself.autocloseTimingFinalState); - myself.wrapper.find('.pkt_ext_detail h2').text(msg); - }); - this.wrapper.addClass('pkt_ext_container_finalstate'); - }; - this.showStateError = function(headline, detail) { - this.wrapper.find('.pkt_ext_detail h2').text(headline); - this.wrapper.find('.pkt_ext_detail h3').text(detail); - this.wrapper.addClass('pkt_ext_container_detailactive pkt_ext_container_finalstate pkt_ext_container_finalerrorstate'); - this.preventCloseTimerCancel = true; - this.startCloseTimer(myself.autocloseTimingFinalState); - } - this.getTranslations = function() - { - this.dictJSON = window.pocketStrings; - }; -}; - -PKT_SAVED_OVERLAY.prototype = { - create : function() - { - if (this.active) - { - return; - } - this.active = true; - - // set translations - this.getTranslations(); - - // set host - this.dictJSON.pockethost = this.pockethost; - - // extra modifier class for collapsed state - if (this.inoverflowmenu) - { - $('body').addClass('pkt_ext_saved_overflow'); - } - - // extra modifier class for language - if (this.locale) - { - $('body').addClass('pkt_ext_saved_' + this.locale); - } - - // Create actual content - $('body').append(Handlebars.templates.saved_shell(this.dictJSON)); - - // Add in premium content (if applicable based on premium status) - this.createPremiumFunctionality(); - - // Initialize functionality for overlay - this.wrapper = $('.pkt_ext_containersaved'); - this.initTagInput(); - this.initAddTagInput(); - this.initRemovePageInput(); - this.initOpenListInput(); - this.initAutoCloseEvents(); - }, - createPremiumFunctionality: function() - { - if (this.premiumStatus && !$('.pkt_ext_suggestedtag_detail').length) - { - $('body').append(Handlebars.templates.saved_premiumshell(this.dictJSON)); - $('.pkt_ext_initload').append(Handlebars.templates.saved_premiumextras(this.dictJSON)); - } - } -}; - - -// Layer between Bookmarklet and Extensions -var PKT_SAVED = function () {}; - -PKT_SAVED.prototype = { - init: function () { - if (this.inited) { - return; - } - this.panelId = pktPanelMessaging.panelIdFromURL(window.location.href); - this.overlay = new PKT_SAVED_OVERLAY(); - - this.inited = true; - }, - - addMessageListener: function(messageId, callback) { - pktPanelMessaging.addMessageListener(this.panelId, messageId, callback); - }, - - sendMessage: function(messageId, payload, callback) { - pktPanelMessaging.sendMessage(this.panelId, messageId, payload, callback); - }, - - create: function() { - var myself = this; - var url = window.location.href.match(/premiumStatus=([\w|\d|\.]*)&?/); - if (url && url.length > 1) - { - myself.overlay.premiumStatus = (url[1] == '1'); - } - var host = window.location.href.match(/pockethost=([\w|\.]*)&?/); - if (host && host.length > 1) - { - myself.overlay.pockethost = host[1]; - } - var inoverflowmenu = window.location.href.match(/inoverflowmenu=([\w|\.]*)&?/); - if (inoverflowmenu && inoverflowmenu.length > 1) - { - myself.overlay.inoverflowmenu = (inoverflowmenu[1] == 'true'); - } - var locale = window.location.href.match(/locale=([\w|\.]*)&?/); - if (locale && locale.length > 1) - { - myself.overlay.locale = locale[1].toLowerCase(); - } - - myself.overlay.create(); - - // tell back end we're ready - thePKT_SAVED.sendMessage("show"); - - // wait confirmation of save before flipping to final saved state - thePKT_SAVED.addMessageListener("saveLink", function(resp) - { - if (resp.status == 'error') { - if (typeof resp.error == 'object') - { - if (resp.error.localizedKey) - { - myself.overlay.showStateError(myself.overlay.dictJSON.pagenotsaved, myself.overlay.dictJSON[resp.error.localizedKey]); - } - else - { - myself.overlay.showStateError(myself.overlay.dictJSON.pagenotsaved, resp.error.message); - } - } - else - { - myself.overlay.showStateError(myself.overlay.dictJSON.pagenotsaved, myself.overlay.dictJSON.errorgeneric); - } - return; - } - - myself.overlay.showStateSaved(resp); - }); - - } -} - -$(function() -{ - if (!window.thePKT_SAVED) { - var thePKT_SAVED = new PKT_SAVED(); - window.thePKT_SAVED = thePKT_SAVED; - thePKT_SAVED.init(); - } - - var pocketHost = thePKT_SAVED.overlay.pockethost; - // send an async message to get string data - thePKT_SAVED.sendMessage("initL10N", { - tos: [ - 'https://'+ pocketHost +'/tos?s=ffi&t=tos&tv=panel_tryit', - 'https://'+ pocketHost +'/privacy?s=ffi&t=privacypolicy&tv=panel_tryit' - ] - }, function(resp) { - window.pocketStrings = resp.strings; - window.thePKT_SAVED.create(); - }); -}); diff --git a/browser/extensions/pocket/content/panels/js/signup.js b/browser/extensions/pocket/content/panels/js/signup.js deleted file mode 100644 index af55cc2a7..000000000 --- a/browser/extensions/pocket/content/panels/js/signup.js +++ /dev/null @@ -1,193 +0,0 @@ -/* -PKT_SIGNUP_OVERLAY is the view itself and contains all of the methods to manipute the overlay and messaging. -It does not contain any logic for saving or communication with the extension or server. -*/ -var PKT_SIGNUP_OVERLAY = function (options) -{ - var myself = this; - this.inited = false; - this.active = false; - this.delayedStateSaved = false; - this.wrapper = null; - this.variant = window.___PKT__SIGNUP_VARIANT; - this.tagline = window.___PKT__SIGNUP_TAGLINE || ''; - this.preventCloseTimerCancel = false; - this.translations = {}; - this.closeValid = true; - this.mouseInside = false; - this.autocloseTimer = null; - this.variant = ""; - this.inoverflowmenu = false; - this.controlvariant; - this.pockethost = "getpocket.com"; - this.fxasignedin = false; - this.dictJSON = {}; - this.initCloseTabEvents = function() { - $('.btn,.pkt_ext_learnmore,.alreadyhave > a').click(function(e) - { - e.preventDefault(); - thePKT_SIGNUP.sendMessage("openTabWithUrl", - { - url: $(this).attr('href'), - activate: true - }); - myself.closePopup(); - }); - }; - this.closePopup = function() { - thePKT_SIGNUP.sendMessage("close"); - }; - this.sanitizeText = function(s) { - var sanitizeMap = { - "&": "&", - "<": "<", - ">": ">", - '"': '"', - "'": ''' - }; - if (typeof s !== 'string') - { - return ''; - } - return String(s).replace(/[&<>"']/g, function (str) { - return sanitizeMap[str]; - }); - }; - this.getTranslations = function() - { - this.dictJSON = window.pocketStrings; - }; - -}; - -PKT_SIGNUP_OVERLAY.prototype = { - create : function() - { - var controlvariant = window.location.href.match(/controlvariant=([\w|\.]*)&?/); - if (controlvariant && controlvariant.length > 1) - { - this.controlvariant = controlvariant[1]; - } - var variant = window.location.href.match(/variant=([\w|\.]*)&?/); - if (variant && variant.length > 1) - { - this.variant = variant[1]; - } - var fxasignedin = window.location.href.match(/fxasignedin=([\w|\d|\.]*)&?/); - if (fxasignedin && fxasignedin.length > 1) - { - this.fxasignedin = (fxasignedin[1] == '1'); - } - var host = window.location.href.match(/pockethost=([\w|\.]*)&?/); - if (host && host.length > 1) - { - this.pockethost = host[1]; - } - var inoverflowmenu = window.location.href.match(/inoverflowmenu=([\w|\.]*)&?/); - if (inoverflowmenu && inoverflowmenu.length > 1) - { - this.inoverflowmenu = (inoverflowmenu[1] == 'true'); - } - var locale = window.location.href.match(/locale=([\w|\.]*)&?/); - if (locale && locale.length > 1) - { - this.locale = locale[1].toLowerCase(); - } - - if (this.active) - { - return; - } - this.active = true; - - // set translations - this.getTranslations(); - this.dictJSON.fxasignedin = this.fxasignedin ? 1 : 0; - this.dictJSON.controlvariant = this.controlvariant == 'true' ? 1 : 0; - this.dictJSON.variant = (this.variant ? this.variant : 'undefined'); - this.dictJSON.variant += this.fxasignedin ? '_fxa' : '_nonfxa'; - this.dictJSON.pockethost = this.pockethost; - this.dictJSON.showlearnmore = true; - - // extra modifier class for collapsed state - if (this.inoverflowmenu) - { - $('body').addClass('pkt_ext_signup_overflow'); - } - - // extra modifier class for language - if (this.locale) - { - $('body').addClass('pkt_ext_signup_' + this.locale); - } - - // Create actual content - if (this.variant == 'overflow') - { - $('body').append(Handlebars.templates.signup_shell(this.dictJSON)); - } - else - { - $('body').append(Handlebars.templates.signupstoryboard_shell(this.dictJSON)); - } - - - // tell background we're ready - thePKT_SIGNUP.sendMessage("show"); - - // close events - this.initCloseTabEvents(); - } -}; - - -// Layer between Bookmarklet and Extensions -var PKT_SIGNUP = function () {}; - -PKT_SIGNUP.prototype = { - init: function () { - if (this.inited) { - return; - } - this.panelId = pktPanelMessaging.panelIdFromURL(window.location.href); - this.overlay = new PKT_SIGNUP_OVERLAY(); - - this.inited = true; - }, - - addMessageListener: function(messageId, callback) { - pktPanelMessaging.addMessageListener(this.panelId, messageId, callback); - }, - - sendMessage: function(messageId, payload, callback) { - pktPanelMessaging.sendMessage(this.panelId, messageId, payload, callback); - }, - - create: function() { - this.overlay.create(); - - // tell back end we're ready - thePKT_SIGNUP.sendMessage("show"); - } -} - -$(function() -{ - if (!window.thePKT_SIGNUP) { - var thePKT_SIGNUP = new PKT_SIGNUP(); - window.thePKT_SIGNUP = thePKT_SIGNUP; - thePKT_SIGNUP.init(); - } - - var pocketHost = thePKT_SIGNUP.overlay.pockethost; - // send an async message to get string data - thePKT_SIGNUP.sendMessage("initL10N", { - tos: [ - 'https://'+ pocketHost +'/tos?s=ffi&t=tos&tv=panel_tryit', - 'https://'+ pocketHost +'/privacy?s=ffi&t=privacypolicy&tv=panel_tryit' - ] - }, function(resp) { - window.pocketStrings = resp.strings; - window.thePKT_SIGNUP.create(); - }); -}); diff --git a/browser/extensions/pocket/content/panels/js/tmpl.js b/browser/extensions/pocket/content/panels/js/tmpl.js deleted file mode 100644 index a03ffda70..000000000 --- a/browser/extensions/pocket/content/panels/js/tmpl.js +++ /dev/null @@ -1,242 +0,0 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['saved_premiumextras'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - return "

    \r\n
    "; - },"useData":true}); -templates['saved_premiumshell'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "
    \n

    " - + escapeExpression(((helper = (helper = helpers.suggestedtags || (depth0 != null ? depth0.suggestedtags : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"suggestedtags","hash":{},"data":data}) : helper))) - + "

    \n
    \n
      \n
    \n
    "; -},"useData":true}); -templates['saved_shell'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "
    \n
    \n
    \n

    " - + escapeExpression(((helper = (helper = helpers.saving || (depth0 != null ? depth0.saving : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"saving","hash":{},"data":data}) : helper))) - + "

    \n
    \n
    \n
    \n"; -},"useData":true}); -templates['signup_shell'] = template({"1":function(depth0,helpers,partials,data) { - var stack1, buffer = ""; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.controlvariant : depth0), {"name":"if","hash":{},"fn":this.program(2, data),"inverse":this.program(4, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - return buffer; -},"2":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.learnmore || (depth0 != null ? depth0.learnmore : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"learnmore","hash":{},"data":data}) : helper))) - + "

    \n"; -},"4":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.learnmore || (depth0 != null ? depth0.learnmore : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"learnmore","hash":{},"data":data}) : helper))) - + "

    \n"; -},"6":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.learnmore || (depth0 != null ? depth0.learnmore : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"learnmore","hash":{},"data":data}) : helper))) - + "

    \n"; -},"8":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.signuptosave || (depth0 != null ? depth0.signuptosave : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signuptosave","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.signinfirefox || (depth0 != null ? depth0.signinfirefox : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signinfirefox","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.alreadyhaveacct || (depth0 != null ? depth0.alreadyhaveacct : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"alreadyhaveacct","hash":{},"data":data}) : helper))) - + " " - + escapeExpression(((helper = (helper = helpers.loginnow || (depth0 != null ? depth0.loginnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"loginnow","hash":{},"data":data}) : helper))) - + ".

    \n"; -},"10":function(depth0,helpers,partials,data) { - var stack1, buffer = ""; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.controlvariant : depth0), {"name":"if","hash":{},"fn":this.program(11, data),"inverse":this.program(13, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - return buffer; -},"11":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.signuptosave || (depth0 != null ? depth0.signuptosave : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signuptosave","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.signupfirefox || (depth0 != null ? depth0.signupfirefox : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signupfirefox","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.signupemail || (depth0 != null ? depth0.signupemail : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signupemail","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.alreadyhaveacct || (depth0 != null ? depth0.alreadyhaveacct : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"alreadyhaveacct","hash":{},"data":data}) : helper))) - + " " - + escapeExpression(((helper = (helper = helpers.loginnow || (depth0 != null ? depth0.loginnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"loginnow","hash":{},"data":data}) : helper))) - + ".

    \n"; -},"13":function(depth0,helpers,partials,data) { - var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "

    " - + escapeExpression(((helper = (helper = helpers.tryitnow || (depth0 != null ? depth0.tryitnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"tryitnow","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.alreadyhaveacct || (depth0 != null ? depth0.alreadyhaveacct : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"alreadyhaveacct","hash":{},"data":data}) : helper))) - + " " - + escapeExpression(((helper = (helper = helpers.loginnow || (depth0 != null ? depth0.loginnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"loginnow","hash":{},"data":data}) : helper))) - + ".

    \n

    "; - stack1 = ((helper = (helper = helpers.tos || (depth0 != null ? depth0.tos : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"tos","hash":{},"data":data}) : helper)); - if (stack1 != null) { buffer += stack1; } - return buffer + "

    \n"; -},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "
    \n

    Pocket

    \n

    " - + escapeExpression(((helper = (helper = helpers.tagline || (depth0 != null ? depth0.tagline : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"tagline","hash":{},"data":data}) : helper))) - + "

    \n"; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.showlearnmore : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.program(6, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - buffer += "
    \n
    \n
    \n"; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.fxasignedin : depth0), {"name":"if","hash":{},"fn":this.program(8, data),"inverse":this.program(10, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - return buffer + "
    \n"; -},"useData":true}); -templates['signupstoryboard_shell'] = template({"1":function(depth0,helpers,partials,data) { - var stack1, buffer = ""; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.controlvariant : depth0), {"name":"if","hash":{},"fn":this.program(2, data),"inverse":this.program(4, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - return buffer; -},"2":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.learnmore || (depth0 != null ? depth0.learnmore : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"learnmore","hash":{},"data":data}) : helper))) - + "

    \n"; -},"4":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.learnmore || (depth0 != null ? depth0.learnmore : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"learnmore","hash":{},"data":data}) : helper))) - + "

    \n"; -},"6":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.learnmore || (depth0 != null ? depth0.learnmore : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"learnmore","hash":{},"data":data}) : helper))) - + "

    \n"; -},"8":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.signuptosave || (depth0 != null ? depth0.signuptosave : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signuptosave","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.signinfirefox || (depth0 != null ? depth0.signinfirefox : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signinfirefox","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.alreadyhaveacct || (depth0 != null ? depth0.alreadyhaveacct : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"alreadyhaveacct","hash":{},"data":data}) : helper))) - + " " - + escapeExpression(((helper = (helper = helpers.loginnow || (depth0 != null ? depth0.loginnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"loginnow","hash":{},"data":data}) : helper))) - + ".

    \n"; -},"10":function(depth0,helpers,partials,data) { - var stack1, buffer = ""; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.controlvariant : depth0), {"name":"if","hash":{},"fn":this.program(11, data),"inverse":this.program(13, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - return buffer; -},"11":function(depth0,helpers,partials,data) { - var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; - return "

    " - + escapeExpression(((helper = (helper = helpers.signuptosave || (depth0 != null ? depth0.signuptosave : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signuptosave","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.signupfirefox || (depth0 != null ? depth0.signupfirefox : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signupfirefox","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.signupemail || (depth0 != null ? depth0.signupemail : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signupemail","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.alreadyhaveacct || (depth0 != null ? depth0.alreadyhaveacct : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"alreadyhaveacct","hash":{},"data":data}) : helper))) - + " " - + escapeExpression(((helper = (helper = helpers.loginnow || (depth0 != null ? depth0.loginnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"loginnow","hash":{},"data":data}) : helper))) - + ".

    \n"; -},"13":function(depth0,helpers,partials,data) { - var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "

    " - + escapeExpression(((helper = (helper = helpers.tryitnow || (depth0 != null ? depth0.tryitnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"tryitnow","hash":{},"data":data}) : helper))) - + "

    \n

    " - + escapeExpression(((helper = (helper = helpers.alreadyhaveacct || (depth0 != null ? depth0.alreadyhaveacct : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"alreadyhaveacct","hash":{},"data":data}) : helper))) - + " " - + escapeExpression(((helper = (helper = helpers.loginnow || (depth0 != null ? depth0.loginnow : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"loginnow","hash":{},"data":data}) : helper))) - + ".

    \n

    "; - stack1 = ((helper = (helper = helpers.tos || (depth0 != null ? depth0.tos : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"tos","hash":{},"data":data}) : helper)); - if (stack1 != null) { buffer += stack1; } - return buffer + "

    \n"; -},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "
    \n
    \n
    \n

    " - + escapeExpression(((helper = (helper = helpers.taglinestory_one || (depth0 != null ? depth0.taglinestory_one : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"taglinestory_one","hash":{},"data":data}) : helper))) - + "

    \n
    \n
    \n
    \n
    \n
    \n
    \n

    " - + escapeExpression(((helper = (helper = helpers.taglinestory_two || (depth0 != null ? depth0.taglinestory_two : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"taglinestory_two","hash":{},"data":data}) : helper))) - + "

    \n"; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.showlearnmore : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.program(6, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - buffer += "
    \n
    \n
    \n
    \n
    \n"; - stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.fxasignedin : depth0), {"name":"if","hash":{},"fn":this.program(8, data),"inverse":this.program(10, data),"data":data}); - if (stack1 != null) { buffer += stack1; } - return buffer + "\n
    \n"; -},"useData":true}); -})(); diff --git a/browser/extensions/pocket/content/panels/js/vendor/handlebars.runtime.js b/browser/extensions/pocket/content/panels/js/vendor/handlebars.runtime.js deleted file mode 100644 index c8bb1c452..000000000 --- a/browser/extensions/pocket/content/panels/js/vendor/handlebars.runtime.js +++ /dev/null @@ -1,660 +0,0 @@ -/* - - handlebars v2.0.0 - -Copyright (C) 2011-2014 by Yehuda Katz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -@license -*/ -/* exported Handlebars */ -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - define([], factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.Handlebars = root.Handlebars || factory(); - } -}(this, function () { -// handlebars/safe-string.js -var __module3__ = (function() { - "use strict"; - var __exports__; - // Build out our basic SafeString type - function SafeString(string) { - this.string = string; - } - - SafeString.prototype.toString = function() { - return "" + this.string; - }; - - __exports__ = SafeString; - return __exports__; -})(); - -// handlebars/utils.js -var __module2__ = (function(__dependency1__) { - "use strict"; - var __exports__ = {}; - /*jshint -W004 */ - var SafeString = __dependency1__; - - var escape = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - - var badChars = /[&<>"'`]/g; - var possible = /[&<>"'`]/; - - function escapeChar(chr) { - return escape[chr]; - } - - function extend(obj /* , ...source */) { - for (var i = 1; i < arguments.length; i++) { - for (var key in arguments[i]) { - if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { - obj[key] = arguments[i][key]; - } - } - } - - return obj; - } - - __exports__.extend = extend;var toString = Object.prototype.toString; - __exports__.toString = toString; - // Sourced from lodash - // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt - var isFunction = function(value) { - return typeof value === 'function'; - }; - // fallback for older versions of Chrome and Safari - /* istanbul ignore next */ - if (isFunction(/x/)) { - isFunction = function(value) { - return typeof value === 'function' && toString.call(value) === '[object Function]'; - }; - } - var isFunction; - __exports__.isFunction = isFunction; - /* istanbul ignore next */ - var isArray = Array.isArray || function(value) { - return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; - }; - __exports__.isArray = isArray; - - function escapeExpression(string) { - // don't escape SafeStrings, since they're already safe - if (string instanceof SafeString) { - return string.toString(); - } else if (string == null) { - return ""; - } else if (!string) { - return string + ''; - } - - // Force a string conversion as this will be done by the append regardless and - // the regex test will do this transparently behind the scenes, causing issues if - // an object's to string has escaped characters in it. - string = "" + string; - - if(!possible.test(string)) { return string; } - return string.replace(badChars, escapeChar); - } - - __exports__.escapeExpression = escapeExpression;function isEmpty(value) { - if (!value && value !== 0) { - return true; - } else if (isArray(value) && value.length === 0) { - return true; - } else { - return false; - } - } - - __exports__.isEmpty = isEmpty;function appendContextPath(contextPath, id) { - return (contextPath ? contextPath + '.' : '') + id; - } - - __exports__.appendContextPath = appendContextPath; - return __exports__; -})(__module3__); - -// handlebars/exception.js -var __module4__ = (function() { - "use strict"; - var __exports__; - - var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; - - function Exception(message, node) { - var line; - if (node && node.firstLine) { - line = node.firstLine; - - message += ' - ' + line + ':' + node.firstColumn; - } - - var tmp = Error.prototype.constructor.call(this, message); - - // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. - for (var idx = 0; idx < errorProps.length; idx++) { - this[errorProps[idx]] = tmp[errorProps[idx]]; - } - - if (line) { - this.lineNumber = line; - this.column = node.firstColumn; - } - } - - Exception.prototype = new Error(); - - __exports__ = Exception; - return __exports__; -})(); - -// handlebars/base.js -var __module1__ = (function(__dependency1__, __dependency2__) { - "use strict"; - var __exports__ = {}; - var Utils = __dependency1__; - var Exception = __dependency2__; - - var VERSION = "2.0.0"; - __exports__.VERSION = VERSION;var COMPILER_REVISION = 6; - __exports__.COMPILER_REVISION = COMPILER_REVISION; - var REVISION_CHANGES = { - 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it - 2: '== 1.0.0-rc.3', - 3: '== 1.0.0-rc.4', - 4: '== 1.x.x', - 5: '== 2.0.0-alpha.x', - 6: '>= 2.0.0-beta.1' - }; - __exports__.REVISION_CHANGES = REVISION_CHANGES; - var isArray = Utils.isArray, - isFunction = Utils.isFunction, - toString = Utils.toString, - objectType = '[object Object]'; - - function HandlebarsEnvironment(helpers, partials) { - this.helpers = helpers || {}; - this.partials = partials || {}; - - registerDefaultHelpers(this); - } - - __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = { - constructor: HandlebarsEnvironment, - - logger: logger, - log: log, - - registerHelper: function(name, fn) { - if (toString.call(name) === objectType) { - if (fn) { throw new Exception('Arg not supported with multiple helpers'); } - Utils.extend(this.helpers, name); - } else { - this.helpers[name] = fn; - } - }, - unregisterHelper: function(name) { - delete this.helpers[name]; - }, - - registerPartial: function(name, partial) { - if (toString.call(name) === objectType) { - Utils.extend(this.partials, name); - } else { - this.partials[name] = partial; - } - }, - unregisterPartial: function(name) { - delete this.partials[name]; - } - }; - - function registerDefaultHelpers(instance) { - instance.registerHelper('helperMissing', function(/* [args, ]options */) { - if(arguments.length === 1) { - // A missing field in a {{foo}} constuct. - return undefined; - } else { - // Someone is actually trying to call something, blow up. - throw new Exception("Missing helper: '" + arguments[arguments.length-1].name + "'"); - } - }); - - instance.registerHelper('blockHelperMissing', function(context, options) { - var inverse = options.inverse, - fn = options.fn; - - if(context === true) { - return fn(this); - } else if(context === false || context == null) { - return inverse(this); - } else if (isArray(context)) { - if(context.length > 0) { - if (options.ids) { - options.ids = [options.name]; - } - - return instance.helpers.each(context, options); - } else { - return inverse(this); - } - } else { - if (options.data && options.ids) { - var data = createFrame(options.data); - data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name); - options = {data: data}; - } - - return fn(context, options); - } - }); - - instance.registerHelper('each', function(context, options) { - if (!options) { - throw new Exception('Must pass iterator to #each'); - } - - var fn = options.fn, inverse = options.inverse; - var i = 0, ret = "", data; - - var contextPath; - if (options.data && options.ids) { - contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; - } - - if (isFunction(context)) { context = context.call(this); } - - if (options.data) { - data = createFrame(options.data); - } - - if(context && typeof context === 'object') { - if (isArray(context)) { - for(var j = context.length; ia?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
    ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+Math.random()}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b) -},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("