File indexing completed on 2024-04-28 05:32:49

0001 /*
0002     Copyright (C) 2020 Kai Uwe Broulik <kde@broulik.de>
0003 
0004     This program is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU General Public License as
0006     published by the Free Software Foundation; either version 3 of
0007     the License, or (at your option) any later version.
0008 
0009     This program is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012     GNU General Public License for more details.
0013 
0014     You should have received a copy of the GNU General Public License
0015     along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 let defaultFaviconData = "";
0019 
0020 function getFavicon(url) {
0021     return new Promise((resolve) => {
0022         let xhr = new XMLHttpRequest();
0023         xhr.onreadystatechange = function() {
0024             if (xhr.readyState !== XMLHttpRequest.DONE) {
0025                 return;
0026             }
0027 
0028             if (!xhr.response) {
0029                 return resolve();
0030             }
0031 
0032             let reader = new FileReader();
0033             reader.onloadend = () => {
0034                 resolve(reader.result);
0035             }
0036             reader.readAsDataURL(xhr.response);
0037         }
0038         const favIconUrl = "chrome://favicon/size/16@" + window.devicePixelRatio + "x/" + url;
0039         xhr.open("GET", favIconUrl);
0040         xhr.responseType = "blob";
0041         xhr.send();
0042     });
0043 }
0044 
0045 addCallback("historyrunner", "find", (message) => {
0046     const query = message.query;
0047 
0048     chrome.permissions.contains({
0049         permissions: ["history"]
0050     }, (granted) => {
0051         if (!granted) {
0052             sendPortMessage("historyrunner", "found", {
0053                 query,
0054                 error: "NO_PERMISSION"
0055             });
0056             return;
0057         }
0058 
0059         chrome.history.search({
0060             text: query,
0061             maxResults: 15,
0062             // By default searches only the past 24 hours but we want everything
0063             startTime: 0
0064         }, (results) => {
0065             let promises = [];
0066 
0067             // Collect open tabs for each history item URL to filter them out below
0068             results.forEach((result) => {
0069                 promises.push(new Promise((resolve) => {
0070                     chrome.tabs.query({
0071                         url: result.url
0072                     }, (tabs) => {
0073                         if (chrome.runtime.lastError || !tabs) {
0074                             return resolve([]);
0075                         }
0076 
0077                         resolve(tabs);
0078                     });
0079                 }));
0080             });
0081 
0082             Promise.all(promises).then((tabs) => {
0083                 // Now filter out the entries with corresponding tabs we found earlier
0084                 results = results.filter((result, index) => {
0085                     return tabs[index].length === 0;
0086                 });
0087 
0088                 // Now fetch all favicons from special favicon provider URL
0089                 // There's no public API for this.
0090                 // chrome://favicon/ works on Chrome "by accident", and for
0091                 // Firefox' page-icon: scheme there is https://bugzilla.mozilla.org/show_bug.cgi?id=1315616
0092                 if (IS_FIREFOX) {
0093                     return;
0094                 }
0095 
0096                 promises = [];
0097                 results.forEach((result) => {
0098                     promises.push(getFavicon(result.url));
0099                 });
0100 
0101                 return Promise.all(promises);
0102             }).then((favicons) => {
0103                 if (favicons) {
0104                     favicons.forEach((favicon, index) => {
0105                         if (favicon) {
0106                             results[index].favIconUrl = favicon;
0107                         }
0108                     });
0109 
0110                     // Now get the default favicon if we don't have it already...
0111                     if (!defaultFaviconData) {
0112                         return getFavicon("");
0113                     }
0114                 }
0115             }).then((faviconData) => {
0116                 if (faviconData) {
0117                     defaultFaviconData = faviconData;
0118                 }
0119 
0120                 if (defaultFaviconData) {
0121                     // ...and remove icon from all results that have the default one
0122                     results.forEach((result) => {
0123                         if (result.favIconUrl === defaultFaviconData) {
0124                             result.favIconUrl = "";
0125                         }
0126                     });
0127                 }
0128 
0129                 sendPortMessage("historyrunner", "found", {
0130                     query,
0131                     results
0132                 });
0133             });
0134 
0135         });
0136     });
0137 });
0138 
0139 addCallback("historyrunner", "run", (message) => {
0140     const url = message.url;
0141 
0142     chrome.tabs.create({
0143         url
0144     });
0145 });
0146 
0147 addCallback("historyrunner", "requestPermission", () => {
0148     chrome.tabs.create({
0149         url: chrome.runtime.getURL("permission_request.html") + "?permission=history"
0150     });
0151 });