Skip to content

Instantly share code, notes, and snippets.

@olejorgenb
Last active February 20, 2024 19:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olejorgenb/a6c0a81e52a98a894f7f98a385ebd78b to your computer and use it in GitHub Desktop.
Save olejorgenb/a6c0a81e52a98a894f7f98a385ebd78b to your computer and use it in GitHub Desktop.
Compares the published firefox port of Tab Modifier with the github source code
#!/bin/bash
# set -x
# The URLs for the extension and the Git repo
EXTENSION_URL="https://addons.mozilla.org/firefox/downloads/file/4099496/tab_modifier-0.21.0.xpi"
GIT_REPO_URL="https://github.com/furybee/chrome-tab-modifier.git"
# The names of the extension and Git repo directories
EXTENSION_DIR="tab_modifier_extension"
GIT_REPO_DIR="chrome-tab-modifier"
# Download the extension and the Git repo
wget -O extension.xpi "$EXTENSION_URL"
git clone "$GIT_REPO_URL" "$GIT_REPO_DIR"
# Extract the extension files
mkdir "$EXTENSION_DIR"
unzip extension.xpi -d "$EXTENSION_DIR"
# Move the extension files into the Git repo
cp -r "$EXTENSION_DIR"/* "$GIT_REPO_DIR/dist"
# Go into the Git repo
cd "$GIT_REPO_DIR"
# Stage and commit the changes
git add dist
git commit -m "Firefox port (dist only)"
echo "Created a new commit with the extension files. Please use 'git diff' to see the changes."
git show HEAD
commit 2ff024e24af664af1d38051e7958107b05b61684
Author: Ole Jørgen Brønner <olejorgenb@yahoo.no>
Date: Sun Jul 9 10:32:24 2023 +0200
firefox-port-dist
diff --git a/dist/html/options.html b/dist/html/options.html
index f22e134..3ff5489 100644
--- a/dist/html/options.html
+++ b/dist/html/options.html
@@ -6,6 +6,7 @@
<title>Tab Modifier</title>
+ <link rel="shortcut icon" href="/img/icon_48.png">
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.1/angular-material.min.css">
<link rel="stylesheet" href="/css/options.css">
@@ -81,7 +82,7 @@
<!-- Donate link -->
<md-menu-item>
- <md-button class="md-button" href="https://www.paypal.me/sylvainvalienne/5" target="_blank" aria-label="Donate" ga-track-event="['resources', 'donate-click']">
+ <md-button class="md-button" href="https://www.paypal.me/svalienne/5" target="_blank" aria-label="Donate" ga-track-event="['resources', 'donate-click']">
<md-icon md-svg-icon="credit-card"></md-icon>
Donate
</md-button>
diff --git a/dist/html/settings.html b/dist/html/settings.html
index 1aa94ef..5a29242 100644
--- a/dist/html/settings.html
+++ b/dist/html/settings.html
@@ -58,10 +58,13 @@
</div>
<div class="md-secondary">
- <md-button class="md-primary md-raised" ng-click="showImportDialog($event)" ga-track-event="['tab-rules', 'import']">
- <md-icon md-svg-icon="file-import"></md-icon>
- Import tab rules
- </md-button>
+ <input-file-button>
+ <md-button class="md-primary md-raised" aria-label="Upload a file" ga-track-event="['tab-rules', 'import']">
+ <md-icon md-svg-icon="file-import"></md-icon>
+ Import tab rules
+ </md-button>
+ <input id="settings" type="file" on-read-file="import($fileContent)" accept="application/json">
+ </input-file-button>
</div>
</md-list-item>
diff --git a/dist/js/background.js b/dist/js/background.js
index 6d388fb..0a974d6 100644
--- a/dist/js/background.js
+++ b/dist/js/background.js
@@ -7,12 +7,17 @@ let options_url = chrome.extension.getURL('html/options.html'), openOptionsPage,
openOptionsPage = function (hash) {
chrome.tabs.query({ url: options_url }, function (tabs) {
+ let tabOptions = {
+ url: (hash !== undefined) ? options_url + '#' + hash : options_url
+ };
if (tabs.length > 0) {
- chrome.tabs.update(tabs[0].id, { active: true, highlighted: true }, function (current_tab) {
+ tabOptions.active = true;
+ // if(isChrome || isOpera) tabOptions.highighted = true;
+ chrome.tabs.update(tabs[0].id, tabOptions, function (current_tab) {
chrome.windows.update(current_tab.windowId, { focused: true });
});
} else {
- chrome.tabs.create({ url: (hash !== undefined) ? options_url + '#' + hash : options_url });
+ chrome.tabs.create(tabOptions);
}
});
};
@@ -33,25 +38,27 @@ chrome.runtime.onMessage.addListener(function (message, sender) {
if (current_tab === undefined) {
return;
}
-
+
let tab, tab_id;
-
+
chrome.tabs.query({}, function (tabs) {
for (let i = 0; i < tabs.length; i++) {
tab = tabs[i];
-
+
if (tab.url.indexOf(message.url_fragment) !== -1 && tab.id !== current_tab.id) {
tab_id = tab.id;
-
+
chrome.tabs.executeScript(current_tab.id, {
code: 'window.onbeforeunload = null;'
}, function () {
- chrome.tabs.remove(current_tab.id);
-
chrome.tabs.update(tab_id, {
url: current_tab.url,
- highlighted: true
+ active: true
+ //if(isChrome || isOpera) highlighted: true
});
+ chrome.windows.update(tab_id, { focused: true });
+
+ chrome.tabs.remove(current_tab.id);
});
}
}
@@ -85,7 +92,7 @@ chrome.runtime.onInstalled.addListener(function (details) {
if (tab_modifier === undefined || tab_modifier.settings === undefined) {
return;
}
-
+
if (tab_modifier.settings !== undefined && tab_modifier.settings.enable_new_version_notification === true && details.previousVersion !== chrome.runtime.getManifest().version) {
openOptionsPage('update/' + chrome.runtime.getManifest().version);
}
@@ -96,14 +103,12 @@ chrome.runtime.onInstalled.addListener(function (details) {
chrome.contextMenus.create({
id: 'rename-tab',
- title: 'Rename Tab',
+ title: 'Create new rule',
contexts: ['all']
});
chrome.contextMenus.onClicked.addListener(function (info, tab) {
if (info.menuItemId === 'rename-tab') {
- let title = prompt('Enter the new title, a Tab rule will be automatically created for you based on current URL');
-
getStorage(function (tab_modifier) {
if (tab_modifier === undefined) {
tab_modifier = {
@@ -113,13 +118,13 @@ chrome.contextMenus.onClicked.addListener(function (info, tab) {
rules: []
};
}
-
+
let rule = {
name: 'Rule created from right-click (' + tab.url.replace(/(^\w+:|^)\/\//, '').substring(0, 15) + '...)',
detection: 'CONTAINS',
url_fragment: tab.url,
tab: {
- title: title,
+ title: tab.title,
icon: null,
pinned: false,
protected: false,
@@ -129,12 +134,12 @@ chrome.contextMenus.onClicked.addListener(function (info, tab) {
url_matcher: null
}
};
-
+
tab_modifier.rules.push(rule);
-
+
chrome.storage.local.set({ tab_modifier: tab_modifier });
-
- chrome.tabs.reload(tab.id);
+
+ openOptionsPage('edit-rule/' + tab_modifier.rules.indexOf(rule));
});
}
});
diff --git a/dist/js/content.js b/dist/js/content.js
index 1fb0649..2c45f97 100644
--- a/dist/js/content.js
+++ b/dist/js/content.js
@@ -5,7 +5,7 @@ chrome.storage.local.get('tab_modifier', function (items) {
return;
}
- var tab_modifier = items.tab_modifier, rule = null, processPage;
+ var tab_modifier = items.tab_modifier, rule = null, processPage, MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
processPage = function () {
// Check if a rule is available
@@ -154,7 +154,7 @@ chrome.storage.local.get('tab_modifier', function (items) {
var el, icon, link;
el = document.querySelectorAll('head link[rel*="icon"]');
-
+
// Remove existing favicons
Array.prototype.forEach.call(el, function (node) {
node.parentNode.removeChild(node);
@@ -182,9 +182,9 @@ chrome.storage.local.get('tab_modifier', function (items) {
}
var title_changed_by_me = false, observer_title;
-
+
// Set up a new observer
- observer_title = new window.WebKitMutationObserver(function (mutations) {
+ observer_title = new MutationObserver(function (mutations) {
if (title_changed_by_me === true) {
title_changed_by_me = false;
} else {
@@ -219,7 +219,7 @@ chrome.storage.local.get('tab_modifier', function (items) {
var icon_changed_by_me = false, observer_icon;
// Set up a new observer
- observer_icon = new window.WebKitMutationObserver(function (mutations) {
+ observer_icon = new MutationObserver(function (mutations) {
if (icon_changed_by_me === true) {
icon_changed_by_me = false;
} else {
@@ -268,7 +268,16 @@ chrome.storage.local.get('tab_modifier', function (items) {
// Protect the tab
if (rule.tab.protected === true) {
- w.onbeforeunload = function () {
+ //FF, IE, Safari
+ w.onbeforeunload = function (e) {
+ e = e || window.event;
+
+ // For IE and Firefox
+ if (e) {
+ e.returnValue = '';
+ }
+
+ // For Safari
return '';
};
}
diff --git a/dist/js/options.js b/dist/js/options.js
index ea3e017..075237a 100644
--- a/dist/js/options.js
+++ b/dist/js/options.js
@@ -2,9 +2,9 @@ var app = angular.module('TabModifier', ['ngRoute', 'ngAnimate', 'ngAria', 'ngMa
app.config(['$routeProvider', '$compileProvider', '$mdIconProvider', '$mdThemingProvider', 'AnalyticsProvider', function ($routeProvider, $compileProvider, $mdIconProvider, $mdThemingProvider, AnalyticsProvider) {
- // Allow "chrome-extension" protocol
- $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|chrome-extension|file|blob):/);
- $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|chrome-extension|file|blob):|data:image\//);
+ // Allow "chrome-extension" and "moz-extension" protocol
+ $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|chrome-extension|moz-extension|file|blob):/);
+ $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|chrome-extension|moz-extension|file|blob):|data:image\//);
// Load icons list by name
$mdIconProvider
@@ -12,7 +12,6 @@ app.config(['$routeProvider', '$compileProvider', '$mdIconProvider', '$mdTheming
.icon('backup-restore', '/icons/backup-restore.svg')
.icon('information-outline', '/icons/information-outline.svg')
.icon('alert', '/icons/alert.svg')
- .icon('file-add', '/icons/file-add.svg')
.icon('file-import', '/icons/file-import.svg')
.icon('file-export', '/icons/file-export.svg')
.icon('file-outline', '/icons/file-outline.svg')
@@ -107,77 +106,58 @@ app.controller('MainController', ['$scope', '$mdSidenav', '$q', 'Analytics', fun
}]);
app.controller('SettingsController', ['$scope', '$mdDialog', '$mdToast', '$location', 'TabModifier', 'Analytics', function ($scope, $mdDialog, $mdToast, $location, TabModifier, Analytics) {
-
+
var tab_modifier = new TabModifier();
-
+
chrome.storage.local.get('tab_modifier', function (items) {
if (items.tab_modifier === undefined) {
tab_modifier.build(new TabModifier());
} else {
tab_modifier.build(items.tab_modifier);
}
-
+
$scope.tab_modifier = tab_modifier;
-
+
// Generate JSON url
$scope.json_url = tab_modifier.export();
-
+
$scope.$apply();
});
-
- // Import tab rules action
- $scope.showImportDialog = function (evt) {
- $mdDialog.show({
- controller: 'SettingsController',
- templateUrl: '../html/import_dialog.html',
- parent: angular.element(document.body),
- targetEvent: evt,
- clickOutsideToClose: true
- });
- };
-
- $scope.cancelDialog = function () {
- $mdDialog.cancel();
- };
-
+
// Import tab rules action
- $scope.import = function (content, replace_existing_rules) {
- replace_existing_rules = typeof replace_existing_rules !== 'undefined' ? replace_existing_rules : true;
+ $scope.import = function (content) {
var result = tab_modifier.checkFileBeforeImport(content);
-
+
if (result === true) {
- var inputId = replace_existing_rules ? 'importReplace' : 'importAdd';
- document.getElementById(inputId).value = '';
-
- tab_modifier.import(content, replace_existing_rules).sync();
-
- $mdDialog.hide();
-
+ document.getElementById('settings').value = '';
+
+ tab_modifier.import(content).sync();
+
$location.path('/');
-
+
$mdToast.show(
$mdToast.simple()
.textContent('Your tab rules have been successfully imported')
.position('top right')
);
-
+
Analytics.trackEvent('tab-rules', 'import-success');
} else {
var message;
-
+
switch (result) {
case 'INVALID_JSON_FORMAT':
message = 'Invalid JSON file. Please check it on jsonlint.com.';
-
+
Analytics.trackEvent('tab-rules', 'import-error-json');
break;
case 'INVALID_SETTINGS':
message = 'Invalid settings file. Is this file comes from Tab Modifier?';
-
+
Analytics.trackEvent('tab-rules', 'import-error-format');
break;
}
- $mdDialog.hide();
+
$mdDialog.show(
$mdDialog.alert()
.clickOutsideToClose(true)
@@ -188,7 +168,7 @@ app.controller('SettingsController', ['$scope', '$mdDialog', '$mdToast', '$locat
);
}
};
-
+
// Delete all tab rules action
$scope.deleteRules = function (evt) {
var confirm = $mdDialog
@@ -200,20 +180,20 @@ app.controller('SettingsController', ['$scope', '$mdDialog', '$mdToast', '$locat
.targetEvent(evt)
.ok('Delete all')
.cancel('Cancel');
-
+
$mdDialog.show(confirm).then(function () {
tab_modifier.deleteRules().sync();
-
+
$mdToast.show(
$mdToast.simple()
.textContent('Your tab rules have been successfully deleted')
.position('top right')
);
-
+
Analytics.trackEvent('tab-rules', 'delete-all');
});
};
-
+
}]);
app.controller('TabRulesController', ['$scope', '$routeParams', '$http', '$mdDialog', '$mdMedia', '$mdToast', 'Rule', 'TabModifier', 'Analytics', function ($scope, $routeParams, $http, $mdDialog, $mdMedia, $mdToast, Rule, TabModifier, Analytics) {
@@ -227,7 +207,7 @@ app.controller('TabRulesController', ['$scope', '$routeParams', '$http', '$mdDia
// Avoid BC break
chrome.storage.sync.get('tab_modifier', function (items) {
- if (items.tab_modifier !== undefined && items.tab_modifier !== null) {
+ if (items !== undefined && items.tab_modifier !== undefined && items.tab_modifier !== null) {
tab_modifier.build(items.tab_modifier);
tab_modifier.sync();
}
@@ -241,15 +221,21 @@ app.controller('TabRulesController', ['$scope', '$routeParams', '$http', '$mdDia
tab_modifier.sync();
}
};
-
+
+ $scope.$routeParams = $routeParams;
+
chrome.storage.local.get('tab_modifier', function (items) {
- if (items.tab_modifier !== undefined) {
+ if (items !== undefined && items.tab_modifier !== undefined) {
tab_modifier.build(items.tab_modifier);
}
$scope.tab_modifier = tab_modifier;
$scope.$apply();
+
+ if ($scope.$routeParams.event === 'edit-rule') {
+ $scope.showForm(new Event('EditRule'), tab_modifier.rules[$scope.$routeParams.version]);
+ }
});
// Show modal form
@@ -529,19 +515,16 @@ app.factory('TabModifier', ['Rule', function (Rule) {
this.rules[index] = rule;
}
};
-
- TabModifier.prototype.build = function (data, replace_existing_rules) {
- replace_existing_rules = typeof replace_existing_rules !== 'undefined' ? replace_existing_rules : true;
+
+ TabModifier.prototype.build = function (data) {
var self = this;
if (data.settings !== undefined) {
this.settings = data.settings;
}
-
- if (replace_existing_rules === true) {
- this.deleteRules();
- }
-
+
+ this.deleteRules();
+
angular.forEach(data.rules, function (rule) {
self.addRule(new Rule(rule));
});
@@ -568,11 +551,9 @@ app.factory('TabModifier', ['Rule', function (Rule) {
return false;
}
};
-
- TabModifier.prototype.import = function (json, replace_existing_rules) {
- replace_existing_rules = typeof replace_existing_rules !== 'undefined' ? replace_existing_rules : true;
-
- this.build(JSON.parse(json), replace_existing_rules);
+
+ TabModifier.prototype.import = function (json) {
+ this.build(JSON.parse(json));
return this;
};
diff --git a/dist/manifest.json b/dist/manifest.json
index fd5a57b..9ebd483 100644
--- a/dist/manifest.json
+++ b/dist/manifest.json
@@ -1,46 +1,52 @@
-{
- "manifest_version": 2,
- "name": "Tab Modifier",
- "version": "0.22.0",
- "description": "Take control of your tabs",
- "homepage_url": "https://github.com/sylouuu/chrome-tab-modifier",
-
- "icons": {
- "16": "img/icon_16.png",
- "32": "img/icon_32.png",
- "48": "img/icon_48.png",
- "128": "img/icon_128.png"
- },
-
- "browser_action": {
- "default_icon": "img/icon_48.png"
- },
-
- "content_security_policy": "script-src 'self' https://ajax.googleapis.com https://www.google-analytics.com; object-src 'self'",
-
- "options_page": "html/options.html",
-
- "background": {
- "scripts": ["js/background.js"],
- "persistent": false
- },
-
- "content_scripts": [{
- "matches": ["<all_urls>"],
- "js": [
- "js/content.js"
- ]
- }],
-
- "web_accessible_resources": [
- "img/*"
+{
+ "manifest_version": 2,
+ "name": "Tab Modifier",
+ "version": "0.21.0",
+ "description": "Take control of your tabs",
+ "homepage_url": "https://github.com/sylouuu/chrome-tab-modifier",
+ "icons": {
+ "16": "img/icon_16.png",
+ "32": "img/icon_32.png",
+ "48": "img/icon_48.png",
+ "128": "img/icon_128.png"
+ },
+ "browser_action": {
+ "default_icon": "img/icon_48.png"
+ },
+ "content_security_policy": "script-src 'self' https://ajax.googleapis.com https://www.google-analytics.com; object-src 'self'",
+ "options_ui": {
+ "page": "html/options.html",
+ "open_in_tab": true
+ },
+ "background": {
+ "scripts": [
+ "js/background.js"
],
-
- "permissions": [
- "http://*/*",
- "https://*/*",
- "tabs",
- "storage",
- "contextMenus"
- ]
-}
+ "persistent": false
+ },
+ "content_scripts": [
+ {
+ "matches": [
+ "<all_urls>"
+ ],
+ "js": [
+ "js/content.js"
+ ]
+ }
+ ],
+ "web_accessible_resources": [
+ "img/*"
+ ],
+ "permissions": [
+ "http://*/*",
+ "https://*/*",
+ "tabs",
+ "storage",
+ "contextMenus"
+ ],
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "{72e1e117-c3cf-4190-a67c-639fcb08eb76}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dist/web-ext-artifacts/tab_modifier-0.21.0.xpi b/dist/web-ext-artifacts/tab_modifier-0.21.0.xpi
new file mode 100644
index 0000000..10d06d4
Binary files /dev/null and b/dist/web-ext-artifacts/tab_modifier-0.21.0.xpi differ
@olejorgenb
Copy link
Author

Note: the diff from above exclude boring changes to the manifest folder: git show HEAD -- . ':(exclude)dist/META-INF/*'

@AJolly
Copy link

AJolly commented Feb 20, 2024

Does the modified version work both in ff/chrome? I've got a tabmodifier fork I've added some features to, may caonsider backporting it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment