In my Firefox extension I am using DOMContentLoaded to detect page load and insert my HTML. Is there an event which triggers before this and still the document is available at that time?
Note: This answer refers to XUL-based extensions. As of Firefox 57, this technology is obsolete. The functionality mentioned here is no longer available to extensions.
There is content-document-global-created notification that is sent out when a document is created, before any content is added to it (to be precise, it happens when the browser receives the HTTP headers of the response and knows that it isn't a redirect or such). That's the earliest point where you can get the document. The DOMContentLoaded event is fired once Gecko finishes downloading the contents of the document, that's the earlies point where you can access the complete DOM. In between there is a bunch of other events, e.g. lots of progress listener events - which one you use depends on what you are trying to do, there is no general answer.
Related
I am starting with chrome extension development and have a couple of questions regarding extension install/update flow and testing during the development :
What happens with the background script after extension update, does chrome perform background script reload ?
Are content scripts detached from background script after extension update ?
If there's an onInstalled event handler in background script, what happens with that event handler when chrome updates extension(is this event handler detached, and when update finishes, the new handler is attached and then executed or some other flow is exercised) ?
Is there a way to simulate update process during development in order to debug events that happen during the update process, for example to host extension on some local server and update from there ?
where to search for documentation on topics like this and similar, is the chromium source code the right place or at least the starting point ?
Thanks!
What happens with the background script after extension update, does Chrome perform background script reload?
The behavior depends on whether you have a handler to chrome.runtime.onUpdateAvailable event registered and whether your extension has a persistent background page or event page.
If you have a persistent background page:
If you handle this event and call chrome.runtime.reload(), the extension is unloaded and then updated before being loaded again.
If you handle this event and do not call chrome.runtime.reload(), then the update will only apply when the extension is next reloaded - likely the next full browser restart.
If you do not handle this event at all, the extension will be unloaded immediately to be updated.
If you have a non-persistent Event page:
If you handle this event and call chrome.runtime.reload(), the extension is updated before being loaded again.
If you do not call chrome.runtime.reload(), or do not handle the event at all, Chrome will update the extension when the Event page next gets unloaded.
There is no way to programmatically prevent the update once the background page gets unloaded for whatever reason.
Are content scripts detached from background script after extension update?
Yes, and it's not pretty. They enter an "orphaned" state when using Chrome API gives inconsistent errors (some do nothing, some trigger exceptions), but are still running — for example, any DOM event listeners will still trigger.
As such, if you want the content scripts to work immediately again, your job is to:
Inject scripts programmatically in existing tabs, without making an assumption that it did not execute before: cleanup first if necessary.
Make sure orphaned copies stop executing: either by noticing in the old copy that it's orphaned, or by broadcasting a DOM event from the new copy.
Important note about WebExtensions: Firefox, unlike Chrome, always reinjects content scripts on load into pages that match manifest entries. Make sure to take that into account.
There are a few question that cover this; for example:
Sending message from a background script to a content script, then to a injected script (See addendum to the answer)
How to properly handle chrome extension updates from content scripts
Chrome extension content script re-injection after upgrade or install
If there's an onInstalled event handler in background script, what happens with that event handler when chrome updates extension (is this event handler detached, and when update finishes, the new handler is attached and then executed or some other flow is exercised)?
Since an update can only happen while the background page is unloaded, there is no complex logic; it will simply fire on first load of the extension afterwards with details.reason == "update". Be sure to register the handler synchronously on script load (e.g. in top level code), or else you may miss the event — normally this only concerns Event pages, but I suspect it's also important here.
Is there a way to simulate update process during development in order to debug events that happen during the update process, for example to host extension on some local server and update from there?
Sadly, this is no longer possible to the best of my knowledge, unless you can use Enterprise Policy install. Your best bet is to have an extension in CWS that's published as Private.
To a certain extent, pressing "Reload" after making some changes to an unpacked extension simulates what happens during the update - with the exception of onInstalled event.
Where to search for documentation on topics like this and similar, is the chromium source code the right place or at least the starting point?
Well.. For detailed questions Chromium code is, of course, the authoritative source. You should search StackOverflow as well, as there's quite a body of knowledge amassed here already. Finally, the official docs provide a lot of information, even if it's not immediately evident - the chrome.runtime API docs, for example.
I am developing a custom translation extension for GMail in chrome and need to trigger the content script when the user clicks on an email in his inbox.
Since GMail uses AJAX, I decided to use the DOMSubTreeModified event. My extension works, but it seems via console logging that the function that sits the translate keeps getting executed constantly, even though the email text remains the same.
DOMContentLoaded does not trigger. Can anyone suggest any alternative I can use? I guess a timer or something in GMail constantly updates the page and makes minor adjustments. I had even narrowed the element on which the event is generated.
It appears that you should be using gmail-specific events to know when a new email is loaded, not generic DOM events. This add-on is not official Google code, but if you look at how it works, you could probably discover how to observe all sorts of gmail events or you could just use it to solve your problems.
there are two events related to web page load - ondomcontentloaded and onload.
At which point will the user will be able to see the web page?
That really depends on the browser. Chrome and Firefox progressively render the webpage as it loads, even if HTML hasn't been completely sent. This will be happening before either of those events are triggered.
onload will always fire after DOMContentLoaded, so if you want the earliest event, use DOMContentLoaded.
I am trying to write a JavaScript script that is "overlayed" on top of a Facebook page. It uses DOMContentLoaded to detect when content is loaded, then adds some extra stuff in. However, because Facebook doesn't actually "reload" the page when going to a new page (it just uses AJAX), the DOMContentLoaded handler doesn't run again, even though there is new stuff to look through.
Anyway, to detect the change, I thought about using onhashchange since Facebook used to change the page's hash, but in Firefox 4 (I need to support Firefox 3 and later with this, but no other browsers), Facebook doesn't change the hash anymore and in pre-Firefox 3.6 there is no onhashchange.
I thought about using DOMNodeInserted, but would that really slow down the page? (I really can't have any slowdowns in this script.)
you might want to monitor the windows.history object, see the following answer, on how facebook uses it to update pages:
"Redirect" page without refresh (Facebook photos style)
For lightweight pages it generally doesn't have noticable effect. However, on bulky pages (I tried this on gmail) it makes that really really slow that I cannot even compose a message smoothly. And that event was added to a very simple span element which just had a single link in that. The events like DOMNodeInserted and DOMSubTreeModified are real show stoppers.
UPDATE: For all those trying to find an answer to this, note that these methods DOMNodeInserted (or DOMSubtreeModified) really had performance problems, so according to new ECMA specs it is a much faster listener : MutationObserver for doing the same thing (and more).
https://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/
I haven't seen any mention of this is David Flanagan's "JavaScript - the Definitive Guide" book (I've asked this question on O'Reilly Answers too), or anywhere else for that matter, but I am finding that window.onunload is not invoked unless the document fully loaded, which is quite annoying! That's true for IE8 and Chrome 3 at least
I have a piece of Javascript I want to add to the bottom of web pages. If the user happens to click off the page before the page has loaded(^ see below), and before my Javascript has had a chance to run, I was hoping to trap that in the onunload. But that's not possible as the onunload event handler is only invoked when the document fully loads. If I can't use onunload, is there anything else I can use to achieve the same?
^ "Javascript - The Definitive Guide" suggests user interaction with the page cannot happen until the page is loaded. I believe this is wrong. Here is what the book says:
"Another grey area in the Javascript execution model is the question of whether event handlers can be invoked before the document is fully loaded. Our discussion of the Javascript execution model has so far concluded that all event handlers are always triggered after all scripts have been executed. While this typically happens, it is not required by any standard. If a document is very long or is being loaded over a slow network connection, the browser might partially render the document and allow the user to begin interacting with it (and triggering event handlers) before all scripts and onload handlers have run. If such an event handler invokes a function that is not yet defined, it will fail. (this is one reason to define all functions in scripts in the of a document.) And if such an event handler attempts to manipulate a part of the document that has not yet been parsed, it will fail. This scenario is uncommon in practice, and it is not usually worth the extra coding effort required to aggressively protect against it."
(5th Edition, Page 256)
I performed tests on IE8 that showed it was possible to interact with the page (and leave it via an anchor link) at any stage in the loading of the page.
Thanks for any help,
Paul
It makes sense to me that an onunload event could not fire until the document is parsed. Document parsing and script execution generally run on the same thread and if a user was to navigate away from the page then the thread would be cancelled after the onunload event is fired. Since the parsing is using the thread at the time the user navigates away from the page, the browser would have the following options:
Complete the parsing and fire the unload event - which would delay navigation to the next page, so this isn't really a feasible option.
Cancel parsing and fire the unload event - this is a more feasible option but you could probably see some UAs not bothering.
Just stop the thread and navigate to the next page - which seems to be what's happening for you in IE and Chrome
Maybe you could see if the onbeforeunload event is fired? I don't think it will make a difference though. I think the best thing to do would be to look at ways you can optimize the page to load faster.