Firefox crashes on element.remove() - firefox

When tinyMCE is used with Firefox and the user drags an image into the editor,image.remove (); window FF converts the image to a base64 string and embeds the image as text--not optimal DB strategy. This question addresses the issue. I've added a simple handler to the editor that handles it simply:
if (tinymce.isGecko) {
editor.getDoc().addEventListener('DOMNodeInserted', function(event) {
var image = event.target;
if ((image.nodeName === 'IMG') && (image.src.substring(0, 30).match(/.*?data.*?;base64/g))) {
image.remove ();
alert('Using drag-and-drop for images with Firefox has been disabled for technical reasons. Please use the "Add Media" button.')
}
},
false);
}
But image.remove (); crashes Firefox every time. Can anyone verify this, and is there a workaround?

Related

tabs onUpdated event not detected on Safari extension?

I am trying to develop a simple web extension/addon under Safari, which is using the tabs onUpdated event. I used the Safari XCRUN converter: https://developer.apple.com/documentation/safariservices/safari_web_extensions/converting_a_web_extension_for_safari
What I am trying to do is :
Open new tab on Google Scholar with set prefs params, from "options.js" script (Options page code below)
Listen for this tab to be updated and ready (e.g. tab status is complete)
Then, inject a content script that will simulate the user click on save button (i.e. on GScholar page)
Then remove the listener, and wait 1,5s (for GS tab to reload and finish saving) in order to finally close this tab.
// Detect browser language
const gsUrl = currentBrowser.i18n.getUILanguage().includes("fr")
? GSCHOLAR_SET_PREFS_FR_URL
: GSCHOLAR_SET_PREFS_COM_URL;
// Listener to detect when the GS tab has finished loading
const gsTabListener = (tabId, changeInfo, tabInfo) => {
if (changeInfo.url && changeInfo.url.startsWith(GSCHOLAR_HOST)) {
currentBrowser.tabs.executeScript(
tabId,
{
code: `document.getElementsByName("save")[0].click();`,
},
() => {
currentBrowser.tabs.onUpdated.removeListener(gsTabListener);
setTimeout(() => currentBrowser.tabs.remove(tabId), 1500);
}
);
}
};
currentBrowser.tabs.onUpdated.addListener(gsTabListener); // Add tab listener
currentBrowser.tabs.create({
url: `${gsUrl}?inst=${gScholarInstIdList.join("&inst=")}&save=#2`,
active: false,
}); // Open GS tab according to browser language
The problem is that it works well on Chrome/Edge/Firefox (on MacOS), but not on Safari : the GS tab is opended but isn't closed and nothing happens :-/
PS:
It seems tabs onUpdated event is well supported on Safari according to MDN.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated
I have also tried webNavigation onCompleted event, but same !
Developing on : MacBookAir under MacOS Monterey 12.4, Safari 15.4 (17613.2.7.18), XCode 13.3.1 (13E500a), extension is bundled with Webpack 5.68.0 (e.g. building all assets files).
I really don't see what I am doing wrong and why wouldn't this tab event be intercepted ?
Thanks for your feedback.
After debugging I finally sloved this by noticing that in fact the events were triggered, but missed because of the availability and values of parameters passed into callabck (changeInfo, details) depending on the browser we're on.
So I switched from onUpdated to webNavigation.onCompleted API, which is better suited to our need (tab page fully loaded) and whose parameter is simple and consistent across browsers :-)
const uiLanguage = currentBrowser.i18n.getUILanguage().includes("fr")
? "fr"
: "com"; // Detect browser language
const gsUrl = `${GSCHOLAR_SETTINGS_HOST}.${uiLanguage}`;
// Listener to detect when the GS tab has finished loading
const gsTabListener = (details) => {
if (details && details.url && details.tabId) {
if (details.url.startsWith(`${gsUrl}/scholar_settings?`)) {
currentBrowser.tabs.executeScript(details.tabId, {
code: `document.getElementsByName("save")[0].click();`,
});
} else if (details.url.startsWith(`${gsUrl}/scholar?`)) {
currentBrowser.webNavigation.onCompleted.removeListener(
gsTabListener
);
currentBrowser.tabs.remove(details.tabId);
}
}
};
currentBrowser.webNavigation.onCompleted.addListener(gsTabListener); // Add GS tab listener
currentBrowser.tabs.create({
url: `${gsUrl}/scholar_settings?inst=${gScholarInstIdList.join(
"&inst="
)}&save=#2`,
active: false,
}); // Open GS tab according to browser language

Firefox add-on triggers code in each open window

I have a Firefox add on that displays a pop-up when it sees a certain response header. This works fine when I have a single window. However, when I have multiple windows open, and one of the tabs in a window triggers the pop-up code in my add-on (due to the presence of said header) I get a pop-up in each of my open windows. For example, if I have 3 windows open, I get 3 different pop ups, one for each windows. Is this the default behavior, and is there an easy in-built way to fix this using their SDK.
Edit:
I have the following code:
Util.requestBlock(httpChannel) {
/*load response headers here*/
if (responseHeaders.includes("header_xyz"))
alert("show popup");
}
Util.monitor = function(w) {
this.obsService = Components.classes['#mozilla.org/observer-service;1'].getService(Components.interfaces.nsIObserverService);
this.obsService.addObserver(this, 'http-on-examine-response', false);
}
Util.monitor.prototype = {
'observe': function(subject, topic, data). {
if (topic == 'http-on-examine-response'). {
var channel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
var block_response = new Util.RequestBlock(channel);
}
},
};
The Util.monitor adds an observer. Whenever a response is received, the "Observe" function is called.
var windows = require("window-utils");
for (window in windows.browserWindowIterator)
doToWindow(window);

Detect tab URL change inside a Firefox add-on

I have an extension, functional on Chrome, that monitors the active Tab for URL changes.
Specifically, I need to detect when the URL changes, but there is no new page load or navigation. Some sites do this (e.g. when you click to view another video on YouTube).
On Chrome, I accomplished this with:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo && changeInfo.status == "complete") {
//do stuff here
}
});
How do I detect such changes in a Firefox add-on?
I've been told to use: Listening to events on all tabs, but I couldn't put it together. One of the problems was that gBrowser was not defined in the extension.
What am I doing wrong?
Is there a simpler way?
Use ProgressListener to be notified about location changes.
To install a listener, convert SDK tab to its raw (old) representation using viewFor.
Backward conversion is possible with modelFor and getTabForContentWindow.
const tabs = require("sdk/tabs");
const {viewFor} = require('sdk/view/core');
const {modelFor} = require('sdk/model/core');
const {getBrowserForTab, getTabForContentWindow} = require("sdk/tabs/utils");
const {Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
var progressListener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
onLocationChange: function(aProgress, aRequest, aURI) {
var highLevel= modelFor(getTabForContentWindow(aProgress.DOMWindow));
console.log("onLocationChange ", highLevel.url);
}
};
tabs.on('open', function(newTab) {
var lowLevel = viewFor(newTab);
var browser = getBrowserForTab(lowLevel);
browser.addProgressListener(progressListener);
});
Don't forget to remove listeners on extension unload. Tab listeners are removed automagically, but ProgressListeners won't be.
Inspired by
Converting to chrome windows
If you're using the add-on SDK, you're looking at the wrong docs. Here are the tab docs.
As stated there, you create a listener like so:
var tabs = require("sdk/tabs");
// Listen for tab openings.
tabs.on('open', function onOpen(tab) {
myOpenTabs.push(tab);
});
// Listen for tab content loads.
tabs.on('ready', function(tab) {
console.log('tab is loaded', tab.title, tab.url);
});
All the docs you look at should be a subset of developer.mozilla.org/en-US/Add-ons/SDK.
I find that the activate and pageshow events, between the two of them, cover all changes in URL that I can conjure up between switching tabs, opening pages in a new tab, closing tabs, refreshing pages, and typing in new URL's.
var updateURL = function (tab) {
var oldURL = url;
var url = tab.url;
console.log(url);
};
tabs.on("activate", updateURL);
tabs.on("pageshow", updateURL);

Force context menu to appear for form inputs

I'm trying to develop a ff addon that allows a user to right-click on a form element and perform a task associated with it.
Unfortunately somebody decided that the context menu shouldn't appear for form inputs in ff and despite long discussions https://bugzilla.mozilla.org/show_bug.cgi?id=433168, they still don't appear for checkboxes, radios or selects.
I did find this: https://developer.mozilla.org/en-US/docs/Offering_a_context_menu_for_form_controls but I cannot think how to translate the code to work with the new add-on SDK.
I tried dumping the javascript shown into a content script and also via the observer-service but to no avail.
I also cannot find the source for the recommended extension https://addons.mozilla.org/en-US/firefox/addon/form-control-context-menu/ which considering it was 'created specifically to demonstrate how to do this' is pretty frustrating.
This seems like very basic addon functionality, any help or links to easier documentation would be greatly appreciated.
** UPDATE **
I have added the following code in a file, required from main, that seems to do the trick.
var {WindowTracker} = require("window-utils");
var tracker = WindowTracker({
onTrack: function(window){
if (window.location.href == "chrome://browser/content/browser.xul") {
// This is a browser window, replace
// window.nsContextMenu.prototype.setTarget function
window.setTargetOriginal = window.nsContextMenu.prototype.setTarget;
window.nsContextMenu.prototype.setTarget = function(aNode, aRangeParent, aRangeOffset) {
window.setTargetOriginal.apply(this, arguments);
this.shouldDisplay = true;
};
};
}
, onUntrack: function(window) {
if (window.location.href == "chrome://browser/content/browser.xul") {
// In case we were called because the extension is uninstalled - restore
// original window.nsContextMenu.prototype.setTarget function
window.nsContextMenu.prototype.setTarget = window.setTargetOriginal;
};
}
});
Unfortunately this still does not bring up a context menu for disabled inputs, but this is not a show-stopper for me.
Many Thanks
The important piece of code in this extension can be seen here. It is very simple - it replaces nsContextMenu.prototype.setTarget function in each browser window and makes sure that it sets shouldDisplay flag for form controls.
The only problem translating this to Add-on SDK is that the high-level modules don't give you direct access to browser windows. You have to use the deprecated window-utils module. Something like this should work:
var {WindowTracker} = require("sdk/deprecated/window-utils");
var tracker = WindowTracker({
onTrack: function(window)
{
if (window.location.href == "chrome://browser/content/browser.xul")
{
// This is a browser window, replace
// window.nsContextMenu.prototype.setTarget function
}
},
onUntrack: function(window)
{
if (window.location.href == "chrome://browser/content/browser.xul")
{
// In case we were called because the extension is uninstalled - restore
// original window.nsContextMenu.prototype.setTarget function
}
}
});
Note that WindowTracker is supposed to be replaced in some future SDK version. Also, for reference: nsContextMenu implementation

Drupal Node Forms - Image field: How to directly upload an image after choosing a file (no need to click upload button)

I'm trying to change the default behavior of Drupal when adding an image through image field on a content type.
When you choose an image to assign to a node, it's not directly uploaded. You also need to click "upload" to display the preview of your image, and this is not really user friendly.
How can I change this (programmatically) to make Drupal start uploading directly the image after choosing the file.
Thank you for help
You can do it this way:
(function ($) {
Drupal.behaviors.autoUpload = {
attach: function(context, settings) {
$('.form-item input.form-submit[value=Upload]', context).hide();
$('.form-item input.form-file', context).change(function() {
$parent = $(this).closest('.form-item');
setTimeout(function() {
if(!$('.error', $parent).length) {
$('input.form-submit[value=Upload]', $parent).mousedown();
}
}, 100);
});
$('.form-item input.form-submit[value=Transférer]', context).hide();
$('.form-item input.form-file', context).change(function() {
$parent = $(this).closest('.form-item');
setTimeout(function() {
if(!$('.error', $parent).length) {
$('input.form-submit[value=Transférer]', $parent).mousedown();
}
}, 100);
});
}
};
})(jQuery);
This solution works with either english and french browsers. Unlike AutoUpload module, which only works on browsers configured in english. Note the [value=Upload] / [value=Upload] attribute
I found a similar post:
https://drupal.stackexchange.com/questions/31121/how-can-i-automatically-upload-images-on-file-selection-rather-than-pressing-the
It's exactly what I need..
You should be able to use http://drupal.org/project/imce for your needs.
I am not sure about the Image field but when I encountered this issue I decided letting users add images in body since it is a much easier option for durpal - When inserting images in text They will show immediately .
IMCE + filefield seems like a viable option for your direct needs,They do mention AJAX support.

Resources