☠☠ backed out by 23e791edc97f ☠ ☠ | |
author | Jim Porter <jporter@mozilla.com> |
Tue, 17 Dec 2019 07:06:59 +0000 | |
changeset 507436 | 6636e1cd0c4163a145fbd92a2223b417cf840fa1 |
parent 507435 | 2afe2627f2574479a04dda8007420d801dccacbd |
child 507437 | 53e61aa34907c2df9392319bd612c6327848ba7d |
push id | 103434 |
push user | jporter@mozilla.com |
push date | Tue, 17 Dec 2019 17:59:01 +0000 |
treeherder | autoland@6636e1cd0c41 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | adw, Mardak |
bugs | 1529969 |
milestone | 73.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/browser/base/content/contentSearchHandoffUI.js @@ -0,0 +1,79 @@ +/* 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"; + +function ContentSearchHandoffUIController() { + this._isPrivateWindow = false; + this._engineIcon = null; + + window.addEventListener("ContentSearchService", this); + this._sendMsg("GetEngine"); +} + +ContentSearchHandoffUIController.prototype = { + handleEvent(event) { + let methodName = "_onMsg" + event.detail.type; + if (methodName in this) { + this[methodName](event.detail.data); + } + }, + + _onMsgEngine({ isPrivateWindow, engine }) { + this._isPrivateWindow = isPrivateWindow; + this._updateEngineIcon(engine); + }, + + _onMsgCurrentEngine(engine) { + if (!this._isPrivateWindow) { + this._updateEngineIcon(engine); + } + }, + + _onMsgCurrentPrivateEngine(engine) { + if (this._isPrivateWindow) { + this._updateEngineIcon(engine); + } + }, + + _updateEngineIcon(engine) { + if (this._engineIcon) { + URL.revokeObjectURL(this._engineIcon); + } + + if (engine.iconData) { + this._engineIcon = this._getFaviconURIFromIconData(engine.iconData); + } else { + this._engineIcon = "chrome://mozapps/skin/places/defaultFavicon.svg"; + } + + document.body.style.setProperty( + "--newtab-search-icon", + "url(" + this._engineIcon + ")" + ); + }, + + // If the favicon is an array buffer, convert it into a Blob URI. + // Otherwise just return the plain URI. + _getFaviconURIFromIconData(data) { + if (typeof data === "string") { + return data; + } + + // If typeof(data) != "string", we assume it's an ArrayBuffer + let blob = new Blob([data]); + return URL.createObjectURL(blob); + }, + + _sendMsg(type, data = null) { + dispatchEvent( + new CustomEvent("ContentSearchClient", { + detail: { + type, + data, + }, + }) + ); + }, +};
--- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -89,16 +89,17 @@ browser.jar: content/browser/static-robot.png (content/static-robot.png) content/browser/safeMode.css (content/safeMode.css) content/browser/safeMode.js (content/safeMode.js) content/browser/safeMode.xhtml (content/safeMode.xhtml) content/browser/sanitize.xhtml (content/sanitize.xhtml) content/browser/sanitizeDialog.js (content/sanitizeDialog.js) content/browser/sanitizeDialog.css (content/sanitizeDialog.css) content/browser/contentSearchUI.js (content/contentSearchUI.js) + content/browser/contentSearchHandoffUI.js (content/contentSearchHandoffUI.js) content/browser/contentSearchUI.css (content/contentSearchUI.css) content/browser/tabbrowser.css (content/tabbrowser.css) content/browser/tabbrowser.js (content/tabbrowser.js) content/browser/tabbrowser-tab.js (content/tabbrowser-tab.js) content/browser/tabbrowser-tabs.js (content/tabbrowser-tabs.js) content/browser/utilityOverlay.js (content/utilityOverlay.js) content/browser/webext-panels.js (content/webext-panels.js) * content/browser/webext-panels.xhtml (content/webext-panels.xhtml)
--- a/browser/components/newtab/bin/render-activity-stream-html.js +++ b/browser/components/newtab/bin/render-activity-stream-html.js @@ -23,16 +23,17 @@ const DEFAULT_OPTIONS = { * {bool} options.debug Should we use dev versions of JS libraries? * {bool} options.noscripts Should we include scripts in the prerendered files? * @return {str} An HTML document as a string */ function templateHTML(options) { const debugString = options.debug ? "-dev" : ""; const scripts = [ "chrome://browser/content/contentSearchUI.js", + "chrome://browser/content/contentSearchHandoffUI.js", "chrome://browser/content/contentTheme.js", `${options.baseUrl}vendor/react${debugString}.js`, `${options.baseUrl}vendor/react-dom${debugString}.js`, `${options.baseUrl}vendor/prop-types.js`, `${options.baseUrl}vendor/redux.js`, `${options.baseUrl}vendor/react-redux.js`, `${options.baseUrl}vendor/react-transition-group.js`, `${options.baseUrl}data/content/activity-stream.bundle.js`,
--- a/browser/components/newtab/content-src/components/Search/Search.jsx +++ b/browser/components/newtab/content-src/components/Search/Search.jsx @@ -1,28 +1,29 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* globals ContentSearchUIController */ +/* globals ContentSearchUIController, ContentSearchHandoffUIController */ "use strict"; import { actionCreators as ac, actionTypes as at } from "common/Actions.jsm"; import { connect } from "react-redux"; import { IS_NEWTAB } from "content-src/lib/constants"; import React from "react"; export class _Search extends React.PureComponent { constructor(props) { super(props); this.onSearchClick = this.onSearchClick.bind(this); this.onSearchHandoffClick = this.onSearchHandoffClick.bind(this); this.onSearchHandoffPaste = this.onSearchHandoffPaste.bind(this); this.onSearchHandoffDrop = this.onSearchHandoffDrop.bind(this); this.onInputMount = this.onInputMount.bind(this); + this.onInputMountHandoff = this.onInputMountHandoff.bind(this); this.onSearchHandoffButtonMount = this.onSearchHandoffButtonMount.bind( this ); } handleEvent(event) { // Also track search events with our own telemetry if (event.detail.type === "Search") { @@ -98,16 +99,24 @@ export class _Search extends React.PureC ); addEventListener("ContentSearchClient", this); } else { window.gContentSearchController = null; removeEventListener("ContentSearchClient", this); } } + onInputMountHandoff(input) { + if (input) { + // The handoff UI controller helps usset the search icon and reacts to + // changes to default engine to keep everything in sync. + this._handoffSearchController = new ContentSearchHandoffUIController(); + } + } + onSearchHandoffButtonMount(button) { // Keep a reference to the button for use during "paste" event handling. this._searchHandoffButton = button; } /* * Do not change the ID on the input field, as legacy newtab code * specifically looks for the id 'newtab-search-text' on input fields @@ -162,28 +171,20 @@ export class _Search extends React.PureC /> <input type="search" className="fake-editable" tabIndex="-1" aria-hidden="true" onDrop={this.onSearchHandoffDrop} onPaste={this.onSearchHandoffPaste} + ref={this.onInputMountHandoff} /> <div className="fake-caret" /> </button> - {/* - This dummy and hidden input below is so we can load ContentSearchUIController. - Why? It sets --newtab-search-icon for us and it isn't trivial to port over. - */} - <input - type="search" - style={{ display: "none" }} - ref={this.onInputMount} - /> </div> )} </div> ); } } export const Search = connect()(_Search);
--- a/browser/components/newtab/data/content/activity-stream.bundle.js +++ b/browser/components/newtab/data/content/activity-stream.bundle.js @@ -10281,31 +10281,32 @@ const TopSites = Object(react_redux__WEB /* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var content_src_lib_constants__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_3__); /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* globals ContentSearchUIController */ +/* globals ContentSearchUIController, ContentSearchHandoffUIController */ class _Search extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureComponent { constructor(props) { super(props); this.onSearchClick = this.onSearchClick.bind(this); this.onSearchHandoffClick = this.onSearchHandoffClick.bind(this); this.onSearchHandoffPaste = this.onSearchHandoffPaste.bind(this); this.onSearchHandoffDrop = this.onSearchHandoffDrop.bind(this); this.onInputMount = this.onInputMount.bind(this); + this.onInputMountHandoff = this.onInputMountHandoff.bind(this); this.onSearchHandoffButtonMount = this.onSearchHandoffButtonMount.bind(this); } handleEvent(event) { // Also track search events with our own telemetry if (event.detail.type === "Search") { this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({ event: "SEARCH" @@ -10385,16 +10386,24 @@ class _Search extends react__WEBPACK_IMP window.gContentSearchController = new ContentSearchUIController(input, input.parentNode, healthReportKey, searchSource); addEventListener("ContentSearchClient", this); } else { window.gContentSearchController = null; removeEventListener("ContentSearchClient", this); } } + onInputMountHandoff(input) { + if (input) { + // The handoff UI controller helps usset the search icon and reacts to + // changes to default engine to keep everything in sync. + this._handoffSearchController = new ContentSearchHandoffUIController(); + } + } + onSearchHandoffButtonMount(button) { // Keep a reference to the button for use during "paste" event handling. this._searchHandoffButton = button; } /* * Do not change the ID on the input field, as legacy newtab code * specifically looks for the id 'newtab-search-text' on input fields * in order to execute searches in various tests @@ -10436,26 +10445,21 @@ class _Search extends react__WEBPACK_IMP className: "fake-textbox", "data-l10n-id": "newtab-search-box-search-the-web-text" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { type: "search", className: "fake-editable", tabIndex: "-1", "aria-hidden": "true", onDrop: this.onSearchHandoffDrop, - onPaste: this.onSearchHandoffPaste + onPaste: this.onSearchHandoffPaste, + ref: this.onInputMountHandoff }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("div", { className: "fake-caret" - })), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { - type: "search", - style: { - display: "none" - }, - ref: this.onInputMount - }))); + })))); } } const Search = Object(react_redux__WEBPACK_IMPORTED_MODULE_1__["connect"])()(_Search); /***/ }), /* 77 */ /***/ (function(module, __webpack_exports__, __webpack_require__) {
--- a/browser/components/newtab/prerendered/activity-stream-debug.html +++ b/browser/components/newtab/prerendered/activity-stream-debug.html @@ -15,16 +15,17 @@ <link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" /> <link rel="stylesheet" href="resource://activity-stream/css/activity-stream.css" /> </head> <body class="activity-stream"> <div id="header-asrouter-container" role="presentation"></div> <div id="root"></div> <div id="footer-asrouter-container" role="presentation"></div> <script src="chrome://browser/content/contentSearchUI.js"></script> + <script src="chrome://browser/content/contentSearchHandoffUI.js"></script> <script src="chrome://browser/content/contentTheme.js"></script> <script src="resource://activity-stream/vendor/react-dev.js"></script> <script src="resource://activity-stream/vendor/react-dom-dev.js"></script> <script src="resource://activity-stream/vendor/prop-types.js"></script> <script src="resource://activity-stream/vendor/redux.js"></script> <script src="resource://activity-stream/vendor/react-redux.js"></script> <script src="resource://activity-stream/vendor/react-transition-group.js"></script> <script src="resource://activity-stream/data/content/activity-stream.bundle.js"></script>
--- a/browser/components/newtab/prerendered/activity-stream.html +++ b/browser/components/newtab/prerendered/activity-stream.html @@ -15,16 +15,17 @@ <link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" /> <link rel="stylesheet" href="resource://activity-stream/css/activity-stream.css" /> </head> <body class="activity-stream"> <div id="header-asrouter-container" role="presentation"></div> <div id="root"></div> <div id="footer-asrouter-container" role="presentation"></div> <script src="chrome://browser/content/contentSearchUI.js"></script> + <script src="chrome://browser/content/contentSearchHandoffUI.js"></script> <script src="chrome://browser/content/contentTheme.js"></script> <script src="resource://activity-stream/vendor/react.js"></script> <script src="resource://activity-stream/vendor/react-dom.js"></script> <script src="resource://activity-stream/vendor/prop-types.js"></script> <script src="resource://activity-stream/vendor/redux.js"></script> <script src="resource://activity-stream/vendor/react-redux.js"></script> <script src="resource://activity-stream/vendor/react-transition-group.js"></script> <script src="resource://activity-stream/data/content/activity-stream.bundle.js"></script>
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js +++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js @@ -113,19 +113,10 @@ document.addEventListener("DOMContentLoa } }); editable.addEventListener("paste", function(ev) { ev.preventDefault(); handoffSearch(ev.clipboardData.getData("Text")); }); // Load contentSearchUI so it sets the search engine icon for us. - // TODO: FIXME. We should eventually refector contentSearchUI to do only what - // we need and have it do the common search handoff work for - // about:newtab and about:privatebrowsing. - let input = document.getElementById("dummy-input"); - new window.ContentSearchUIController( - input, - input.parentNode, - "aboutprivatebrowsing", - "aboutprivatebrowsing" - ); + new window.ContentSearchHandoffUIController(); });
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml +++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml @@ -10,17 +10,17 @@ <head> <meta http-equiv="Content-Security-Policy" content="default-src chrome: blob:; object-src 'none'"/> <link rel="icon" type="image/png" href="chrome://browser/skin/privatebrowsing/favicon.svg"/> <link rel="stylesheet" href="chrome://browser/content/aboutPrivateBrowsing.css" type="text/css" media="all"/> <link rel="stylesheet" href="chrome://browser/skin/privatebrowsing/aboutPrivateBrowsing.css" type="text/css" media="all"/> <link rel="localization" href="branding/brand.ftl"/> <link rel="localization" href="browser/aboutPrivateBrowsing.ftl"/> <script src="chrome://browser/content/aboutPrivateBrowsing.js"></script> - <script src="chrome://browser/content/contentSearchUI.js"></script> + <script src="chrome://browser/content/contentSearchHandoffUI.js"></script> </head> <body> <p class="showNormal" data-l10n-id="about-private-browsing-not-private"></p> <button id="startPrivateBrowsing" class="showNormal" data-l10n-id="privatebrowsingpage-open-private-window-label"></button> <div id="search-banner" class="search-banner" hidden="true"> @@ -45,17 +45,16 @@ <div class="wordmark" /> </div> <div class="search-inner-wrapper"> <button id="search-handoff-button" class="search-handoff-button" tabindex="-1" data-l10n-id="about-private-browsing"> <div class="fake-textbox" data-l10n-id="about-private-browsing-search-placeholder"></div> <input id="fake-editable" class="fake-editable" tabindex="-1" aria-hidden="true" /> <div class="fake-caret" /> </button> - <input id="dummy-input" class="dummy-input" type="search" /> </div> <div class="info"> <h1 data-l10n-id="about-private-browsing-info-title"></h1> <p data-l10n-id="about-private-browsing-info-description"></p> <a id="private-browsing-myths" data-l10n-id="about-private-browsing-info-myths"></a> </div> </div> </body>
--- a/browser/modules/ContentSearch.jsm +++ b/browser/modules/ContentSearch.jsm @@ -448,16 +448,27 @@ var ContentSearch = { }, _onMessageGetState(msg, data) { return this.currentStateObj(msg.target.ownerGlobal).then(state => { this._reply(msg, "State", state); }); }, + _onMessageGetEngine(msg, data) { + return this.currentStateObj(msg.target.ownerGlobal).then(state => { + this._reply(msg, "Engine", { + isPrivateWindow: state.isPrivateWindow, + engine: state.isPrivateWindow + ? state.currentPrivateEngine + : state.currentEngine, + }); + }); + }, + _onMessageGetStrings(msg, data) { this._reply(msg, "Strings", this.searchSuggestionUIStrings); }, _onMessageSearch(msg, data) { this.performSearch(msg, data); },
--- a/browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css +++ b/browser/themes/shared/privatebrowsing/aboutPrivateBrowsing.css @@ -158,20 +158,16 @@ p { display: none; inset-inline-start: 47px; height: 17px; position: absolute; top: 16px; width: 1px; } -.dummy-input { - display: none; -} - .search-banner { width: 100%; background-color: var(--in-content-banner-background); color: var(--in-content-banner-text-color); } .banner-body { margin: auto;