Handling multiple windows

Talk about code development, features, specific bugs, enhancements, patches, and similar things.
Forum rules
Please keep everything here strictly on-topic.
This board is meant for Pale Moon source code development related subjects only like code snippets, patches, specific bugs, git, the repositories, etc.

This is not for tech support! Please do not post tech support questions in the "Development" board!
Please make sure not to use this board for support questions. Please post issues with specific websites, extensions, etc. in the relevant boards for those topics.

Please keep things on-topic as this forum will be used for reference for Pale Moon development. Expect topics that aren't relevant as such to be moved or deleted.
User avatar
moonbat
Knows the dark side
Knows the dark side
Posts: 4981
Joined: 2015-12-09, 15:45

Handling multiple windows

Unread post by moonbat » 2020-07-07, 09:26

All my extensions have one Kryptonite - using multiple windows. Most people use tabbed browsing rather than separate windows, but when they do, there are problems with the state of overlaid UI elements.
In all my extensions, I use namespaces, <extension name>.namespace.
A common javascript module for utility functions, and separate sub-namespaces for the overlay window, options dialog etc.
For example, my browser overlay script -

Code: Select all

if ("undefined" == typeof(PureURL)) {
	var PureURL = {};
}
const puPrefBranch = PureURL.Common.prefBranch;
PureURL.Launch={
// All browser window related stuff goes here.
}
window.addEventListener("load", function(){PureURL.Launch.init();},false);
window.addEventListener("unload", PureURL.Launch.cleanup,false);
Part of my code involves enabling/disabling toolbar buttons when they are not applicable (in PMPlayer, when the current page has no video on it, in PureURL when the current page isn't a webpage). If you now open a new window and close it, the button on the previous window stops responding to events. If I null the button in the cleanup function, then it throws errors in the previous window.

Why does this happen? Shouldn't there be a new copy of the PureURL.Launch namespace when a new window opens, and only that go out of scope when the window closes? Otherwise what is the difference between using a namespace like this and using a .jsm module (which is expected to remain loaded throughout the existence of the browser process and not dependent on individual windows?)
"One hosts to look them up, one DNS to find them and in the darkness BIND them."

Image
Linux Mint 21 Xfce x64 on HP i5-5200 laptop, 12 GB RAM.
AutoPageColor|PermissionsPlus|PMPlayer|Pure URL|RecordRewind|TextFX

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 35636
Joined: 2011-08-28, 17:27
Location: Motala, SE

Re: Handling multiple windows

Unread post by Moonchild » 2020-07-07, 09:57

You probably want an init safeguard; add a property on your prototype that you set when init is completed so you don't get multiple inits. (e.g. add an isInitialized boolean)
Alternatively don't attach the extension init globals to window loading but to browser startup instead and only set per-window changes in the onload handler?

I haven't looked at your code but there are common ways around this kind of duplicate scripting causing issues, depending on how exactly it's used.
"Sometimes, the best way to get what you want is to be a good person." -- Louis Rossmann
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

JustOff

Re: Handling multiple windows

Unread post by JustOff » 2020-07-07, 10:22

moonbat wrote:
2020-07-07, 09:26
Shouldn't there be a new copy of the PureURL.Launch namespace when a new window opens
The problem is that you are creating PureURL object from common.jsm, not from init.js, which makes PureURL shared across all windows.

The simplest way to fix this is to move import

Code: Select all

Components.utils.import("chrome://pureurl4pm/content/common.jsm");
below the PureURL init block

Code: Select all

if ("undefined" == typeof(PureURL)) {
	var PureURL = {};
}

User avatar
moonbat
Knows the dark side
Knows the dark side
Posts: 4981
Joined: 2015-12-09, 15:45

Re: Handling multiple windows

Unread post by moonbat » 2020-07-07, 11:36

Moonchild wrote:
2020-07-07, 09:57
don't attach the extension init globals to window loading but to browser startup instead
How does one event-handle that?
JustOff wrote:
2020-07-07, 10:22
The simplest way to fix this is to move import
Didn't help :(
I tested it by setting PureURL.Launch (namespace for all functions in the window) to null in the close window handler, and it got applied to the one in the existing window as well.
"One hosts to look them up, one DNS to find them and in the darkness BIND them."

Image
Linux Mint 21 Xfce x64 on HP i5-5200 laptop, 12 GB RAM.
AutoPageColor|PermissionsPlus|PMPlayer|Pure URL|RecordRewind|TextFX

JustOff

Re: Handling multiple windows

Unread post by JustOff » 2020-07-07, 14:32

Well, I looked a little more carefully and looks like you are a bit confused with namespaces.

How about this:

Code: Select all

diff --git a/src/content/common.jsm b/src/content/common.jsm
index e5b3117..f2f94db 100644
--- a/src/content/common.jsm
+++ b/src/content/common.jsm
@@ -1,10 +1,7 @@
-var EXPORTED_SYMBOLS = ["PureURL","Cc","Ci","Cu","PureURLPrefListener"]
+var EXPORTED_SYMBOLS = ["Common", "PureURLPrefListener"]
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 Cu.import("resource://gre/modules/Services.jsm");
-if ("undefined" == typeof(PureURL)) {
-	var PureURL = {};
-}
-PureURL.Common={
+Common={
 		pureURLObserver : null,
 		logoutput : false,
 		linkcount : 0,
@@ -16,13 +13,13 @@ PureURL.Common={
 		 * Toggle console logging.
 		 */
 		setLogging:function(flag){
-			PureURL.Common.logoutput = flag;
+			Common.logoutput = flag;
 		},
 		/**
 		 * Log output to toolkit error console if enabled.
 		 */ 
 		printlog:function(item) {
-			if(PureURL.Common.logoutput==true) {
+			if(Common.logoutput==true) {
 				Services.console.logStringMessage("[PureURL:]"+item);
 			}
 		},
@@ -171,9 +168,9 @@ PureURL.Common={
 				var response = url.getResponseHeader('Location');
 				if(Math.round(url.responseStatus/100) == 3 && response){
 					if(el != response) {
-						PureURL.Common.printlog("Resolved "+el+" to "+response);
+						Common.printlog("Resolved "+el+" to "+response);
 					}
-					return el==response ? response : PureURL.Common.unshortenLink(response);
+					return el==response ? response : Common.unshortenLink(response);
 				}
 			}catch(e){
 				return el;
@@ -197,21 +194,21 @@ PureURL.Common={
 				if(!host)
 					continue;
 				var qpos = href.indexOf('?');
-				if(qpos===-1||PureURL.Common.checkedLinks.hasOwnProperty(href)){
-					if(PureURL.Common.prefBranch.getBoolPref("expandlinks") 
-							&& PureURL.Common.shorteners.has(host)){
-						el.href = PureURL.Common.unshortenLink(el);
+				if(qpos===-1||Common.checkedLinks.hasOwnProperty(href)){
+					if(Common.prefBranch.getBoolPref("expandlinks") 
+							&& Common.shorteners.has(host)){
+						el.href = Common.unshortenLink(el);
 						if(orig != el.href){
-							PureURL.Common.printlog("Original link: "+orig
+							Common.printlog("Original link: "+orig
 							                        +"\nExpanded link: "+el.href);
 							el.title=el.href;
-							PureURL.Common.expandcount++;
+							Common.expandcount++;
 						}
 					}
 					continue;
 				}
 				var args = href.substring(qpos+1, href.length);
-				var regexp = PureURL.Common.gfields.getRegExp(host);
+				var regexp = Common.gfields.getRegExp(host);
 				if(regexp) {
 					var cleaned = args.replace(regexp, '').replace(/^[&]+/i, '');
 					if(args!==cleaned) {
@@ -219,11 +216,11 @@ PureURL.Common={
 						if(cleaned)
 							href += '?'+cleaned;
 						el.href = href;
-						PureURL.Common.linkcount++;
-						PureURL.Common.printlog("Original link: "+orig+"\nCleaned link:"+href);
+						Common.linkcount++;
+						Common.printlog("Original link: "+orig+"\nCleaned link:"+href);
 					}
 				}
-				PureURL.Common.checkedLinks[el.href] = true;
+				Common.checkedLinks[el.href] = true;
 			}
 			return root;
 		}
@@ -233,12 +230,12 @@ function pureURLHttpObserver() {
 pureURLHttpObserver.prototype = {
 		observe : function(aSubject,aTopic,aData){
 			if ("http-on-modify-request" == aTopic && 
-					PureURL.Common.prefBranch.getBoolPref("request_hook_enabled",true)) {
+					Common.prefBranch.getBoolPref("request_hook_enabled",true)) {
 				aSubject.QueryInterface(Ci.nsIHttpChannel);
 				url = aSubject.URI.spec;
 				path = aSubject.URI.path;
 				qpos = path.indexOf('?');
-				regexp = PureURL.Common.gfields.getRegExp(aSubject.URI.host);
+				regexp = Common.gfields.getRegExp(aSubject.URI.host);
 				if (regexp !== null && qpos > -1) {
 					var args = path.substring(qpos + 1, path.length);
 					var cleaned = args.replace(regexp, '').replace(/^[&]+/i, '');
@@ -247,7 +244,7 @@ pureURLHttpObserver.prototype = {
 						if (cleaned) path += '?' + cleaned;
 						try {
 							aSubject.URI.path = path;
-							PureURL.Common.printlog("Original request: "+url+"\nCleaned request:"+aSubject.URI.spec);
+							Common.printlog("Original request: "+url+"\nCleaned request:"+aSubject.URI.spec);
 						} catch (e) {
 							Cu.reportError("[PureURL error:] URI= "+aSubject.URI.spec+"\nmodified path="+path+"\n"+e);
 						}
@@ -256,7 +253,7 @@ pureURLHttpObserver.prototype = {
 			}
 		}
 }
-PureURL.Common.pureURLObserver = new pureURLHttpObserver();
+Common.pureURLObserver = new pureURLHttpObserver();
 function PureURLPrefListener(branch_name, callback) {
 	// Keeping a reference to the observed preference branch or it will get
 	// garbage collected.
diff --git a/src/content/init.js b/src/content/init.js
index 14dd206..3daa441 100644
--- a/src/content/init.js
+++ b/src/content/init.js
@@ -1,9 +1,9 @@
-Components.utils.import("chrome://pureurl4pm/content/common.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 if ("undefined" == typeof(PureURL)) {
 	var PureURL = {};
 }
+Components.utils.import("chrome://pureurl4pm/content/common.jsm", PureURL);
 const puPrefBranch = PureURL.Common.prefBranch;
 PureURL.Launch={
 		btnchkIntercept:null,
@@ -70,7 +70,7 @@ PureURL.Launch={
 		/**
 		 * Listens for preference changes and applies them to the UI.
 		 */
-		prefListener : new PureURLPrefListener("extensions.pure-url@palemoon.",function(branch,name){
+		prefListener : new PureURL.PureURLPrefListener("extensions.pure-url@palemoon.",function(branch,name){
 			switch(name){
 			case("request_hook_enabled"):
 				var intercept = puPrefBranch.getBoolPref("request_hook_enabled",true);

User avatar
moonbat
Knows the dark side
Knows the dark side
Posts: 4981
Joined: 2015-12-09, 15:45

Re: Handling multiple windows

Unread post by moonbat » 2020-07-07, 15:32

I'll try this out. I wanted to keep everything under a sub namespace of PureURL so that Common doesn't conflict with any other extension having a similar name. Or maybe I should name it PureURLCommon or something.
"One hosts to look them up, one DNS to find them and in the darkness BIND them."

Image
Linux Mint 21 Xfce x64 on HP i5-5200 laptop, 12 GB RAM.
AutoPageColor|PermissionsPlus|PMPlayer|Pure URL|RecordRewind|TextFX

JustOff

Re: Handling multiple windows

Unread post by JustOff » 2020-07-07, 15:39

moonbat wrote:
2020-07-07, 15:32
I wanted to keep everything under a sub namespace of PureURL so that Common doesn't conflict with any other extension having a similar name.
And it will be right there because of:

Code: Select all

-Components.utils.import("chrome://pureurl4pm/content/common.jsm");
+Components.utils.import("chrome://pureurl4pm/content/common.jsm", PureURL);

User avatar
moonbat
Knows the dark side
Knows the dark side
Posts: 4981
Joined: 2015-12-09, 15:45

Re: Handling multiple windows

Unread post by moonbat » 2020-07-07, 15:43

Thanks JustOff!
"One hosts to look them up, one DNS to find them and in the darkness BIND them."

Image
Linux Mint 21 Xfce x64 on HP i5-5200 laptop, 12 GB RAM.
AutoPageColor|PermissionsPlus|PMPlayer|Pure URL|RecordRewind|TextFX