My web application started firing off a ton of events while idle and I've been trying to hunt down who has been firing them.
I received a Chrome performance profile from a client and discovered that the events are being fired from the root of execution. This makes me believe that the events are coming from the user. But the odd thing is, is that the events are being fired so quickly that it's impossible for a user to perform them.
I also doubt that these are being executed through the script or a timer because then the stack trace would be prepended with a timer fired or another function.
So now I'm at square one where I have reasons to doubt that a script is firing them and I have reasons to doubt that a user is firing them.
I'm going to reach out to my client and monitorEvents (https://developers.google.com/web/tools/chrome-devtools/console/events) on the element and then check to see if the event being fired isTrusted (https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted). If it is Trusted, then I have no idea what could be happening external to Chrome that's causing so many events. And if it isn't Trusted then I have no idea how to track the code that's firing so many events.
Zoomed in profile execution stack
Zoomed out profile execution stack
Related
I'm currently working on developing a Chrome extension and have noticed that my extension works fine for several days or longer, but eventually reaches a state where various event listeners seem to stop working. For instance, my extension listens for storage updates coming from its popup and also for an alarm which is triggered every minute, but at some point both these seem to stop working simultaneously. My event listeners are registered synchronously as far as I can tell, and they continue to work for far longer than I would expect if this were not the case.
Further, when the extension reaches this state, I find that when I add test event listeners in the service worker console, these listeners don't appear to trigger properly either.
I have not been able to identify the precise circumstances under which this issue occurs, or replicate it successfully, except by waiting several days with my extension running. The issue does not appear to be associated with any runtime exceptions. If anyone has experienced a similar issue or has any debugging advice I'd greatly appreciate it. At this point, I'm not sure how to continue investigating this issue.
Related to this question, the workaround to launching a custom protocol after starting a websocket (so as to keep the socket open and polling) is to use an iframe element and set the src to be the custom protocol. But, if a user clicks the button that sets the src too quickly (i.e. they trigger the custom protocol too frequently), FF logs this warning:
"Iframe with external protocol was blocked due to lack of user activation, or because not enough time has passed since the last such iframe was loaded."
I can't seem to find any documentation on:
What constitutes user activation
How much time "enough time has passed" actually is
Does anyone know what exactly that warning means or what either of those bullet points are and how we can get around the limitation to allow launching a custom protocol (without refreshing the page or causing a popup) from within FF?
I've tried both having the iframe exist on the page beforehand and dynamically setting the src, as well as, dynamically creating the iframe with the src at the same time, but both end with the same warning being logged.
User activation means an event triggered by the user, such as mouse or keyboard events. This is similar to the way popup blockers work.
I doubt you'll find the "enough time" limit documented -- the programmers don't want to tell malware writers how to work around the restriction.
You say you're doing this when the user clicks on a button, so that should fit the "user activation" requirement. Are you doing it in a callback function that runs asynchronously from the event listener? That disconnects it from the user interaction -- it has to be directly in the listener function.
So, I wrote a few extensions, most disposable and one hopefully viable.
I'm still a bit confused about the "agenda", of "schedule" or whatchacallit, i.e. the order in which things happen, and the places where they live.
For example, I am writing a new one that shall do the following :
a browser action presents the user with a menu of 3 items
two of those items trigger actions to be executed immediately, while the third lauches a process that is to run undercover for an extended period (namely polling a certain web page at an interval, said web page needing not to be loaded in any visible tab or window).
Naturally I'd be tempted to assume that the long-term is to live in the background.js.
Now, I understand that the pop-up menu is an HTML document in its own right, living its life in its own bubble. It shall disappear right after the user cliked on an item, thereby taking its context with it to its grave. Right now I'm at a bit of a loss trying to figure out how it can trigger a background process.
Notwithstanding, I don't quite grasp what brings the background.js to life, even less so when it is specified as non persistent as is recommended.
Naturally, I'll RTFM again, but if you fellows could dumb this down to my poor level of understanding, I'd be so happy ...
Maybe as you said, you would need to RTFM again..
Background Page runs in the extension process and exists for the lifetime of your extension, until your extension is removed or the browser process terminates.
While Event Page, what chrome has recommended to use, is loaded only when they are needed. Take a look at Lifetime part, the following are some example that will cause the event page to load:
The app or extension is first installed or is updated to a new version (in order to register for events).
The event page was listening for an event, and the event is dispatched.
A content script or other extension sends a message.
Another view in the extension (for example, a popup) calls runtime.getBackgroundPage.
As for your question, 'how it can trigger a background process', if there are no events to catch or message to pass, you can just call runtime.getBackgroundPage to load the event page.
I would like to know what the browser does about events that happen while scripts are currently running. Does the browser just ignore these events or does it store them and execute them after any scripts stop running? Is this dependent on the event? I am specifically interested in mousemove and drag events.
Thanks
What do you mean? Events that trigger javascripts?
If so then yes, the triggered script is remembered and put on the call stack.
Javascript is single threaded -- so an event that triggers a new script will have to wait until all other scripts on the stack are completed before it fires.
So if your drag or mousemove trigger a script then that trigger will be remembered.
I have ~ 100-200 javascript functions loaded on a web-site.
I want to determine what javascript function is executed when i click one item or another in Google Chrome.
How can i do it with Chrome Web Developer Tools?
Thanks!
One simple approach is to start Chrome Developer Tools, switch to the Sources panel and hit F8 (Pause Execution). This will break on the first executed JavaScript statement.
Another approach is to set an event listener breakpoint for mousedown or click: in the same Sources panel, expand the "Event Listener Breakpoints" in the righthand sidebar. Expand the "Mouse" item and check the events you want to break on (e.g. "click", "mousedown"). Then go click in your page and see the JS execution break in the DevTools. Enjoy!
An alternative to pausing execution(which usually works great, but doesn't work well on pages which frequently execute periodic code)
You can use chrome's profiler to record for a short period of time. After you finish recording, it will show you a summary of cpu time spent in any of the functions which were executed during recording. We don't really care about the cpu time, were just using this tool because it will show us which functions were executed.
Basically just start recording:
Note: in Chrome 58 and above, the "Profiles" tab is renamed to "Memory". In Chrome 88+, the tab name is "Performance".
Then do your action(eg, click a button on the webpage, or do whatever will cause the interesting code to execute). Then stop the recording and view the result:
Notice I'm using "top down" viewing mode - which shows you the call stack, and you can drill down to see which functions eventually got called. For example, some anonymous function was called first(likely as a result of setTimeout or maybe some click event handler), and then it called some method identified by s.track.s.t which then called s_doPlugins and so on...The important thing is that in top down mode, the entries at the top of the tree form the start of a call stack, and so they're usually a function registered by some timer function(setTimeout, setInterval, requestAnimationFrame, etc...) or some event handler(click, mousemove, load, etc...).
You can also use the "chart" viewing mode, which shows you which function was called at which time, plotted on a chart from left to right. This helps you identify which function you're really looking for because you probably have a sense of what time the code executed within your recording(eg, right in the middle).
btw - I believe most other modern browsers have similar capability.
Chrome has updated many times since I wrote this answer, so the screenshots are a bit outdated, but the concept of using the cpu profiler remains the same. I'll update the screenshots another day.
I want to determine what javascript function is executed when i click one item or another in Google Chrome.
Now there's a great extension called Visual Event that does exactly that. It only recognizes event handlers set via popular js libraries (jQuery, YUI, MooTools, Prototype, Glow) and DOM Level 0 events.