Chrome Extension -- Running executeScript in multiple new tabs at the same time - google-chrome

I'm building a Chrome Extension that has a popup.html with a search form. Like Travelocity or Kayak, the form includes checkboxes so the user can select which sites they want to query.
On submit, popup.js launches multiple new tabs based on the selected checkboxes. In the tabs.create() callback for each new tab I use executeScript to:
- (A) inject the user's query into the search form on each of the new pages, and
- (B) submit the search form on those pages.
My code is working when one checkbox is selected (i.e. new tab is launched), but when multiple new tabs are created simultaneously it appears that the executeScript isn't running consistently. Sometimes it works, and sometimes it doesn't.
This leads me to believe that there's some sort of issue with the timing of the script execution, but I'm not sure.
If you have any idea what's going on I'd love to hear your advice.
Also, I'd appreciate any resources on how to debug this sort of issue in the future.
Here's my code on github...
whole repo: https://github.com/rossmorey/SongSearch
manifest.json
popup.html
popup.js (most relevant file)
Many thanks!

Seems like when you open multiple tabs - your popup.html loses the focus and closes, so on tabs.create callbacks which injects your code will not be executed.
Try to create tabs with "active:false" option, like this:
chrome.tabs.create({url: stringToObj[org], active:false} ...
I think it would help you.
And also...
It's a bug in your SeSac inject-code: if no search type defined in popup window, block
input[value="undefined"]
will not be found, so "checked" property will be called on "undefined" and this will stop you inject script execution.

Related

Modify DOM in content-script as a replacement for the non-ability to trigger pop-ups programmatically?

I'm working on an extension that's supposed to use the content of the page to determine whether to show an interface to the user.
The ways to show an interface, if I'm correct, are using a browser action or a page action.
And neither can be triggered programmatically. But content scripts could be written to inject an equivalent GUI into the webpage.
So, does it make sense to modify the DOM using content-scripts to display an interface as a substitute for page action? It seems like an obvious work around to me, and I'm sure there are good reasons to not let page actions be triggered programmatically.
Well, modifying DOM must be done by only Content Scripts, as that is the reason they exist.
Want to fetch any data from current page, alter anything in the page, add new UI in the page - whatever, content script will help you do that.
It has nothing to do with Page script Or Browser Script.
YES, you can not programatically trigger page/browser action. It has to be done by explicit clicking.
But if you want to open a UI by clicking a chrome extension, then there is a popup js for that.

Chrome - type=file drag and drop

I have a weird situation. One of my users is using functionality of Chrome (current version, 49, 50), that he drags and drops a file from his folder on local computer to normal input type=file button in a form on the webpage. Once again, let me stress it even more, its normal html input, no fancy javascript, no drag&drop events and handlers, nothing like this. It just takes the name of the dragged file and puts it into the input field, as like he selected it via "normal" way, opening the file select window, locating file on harddrive, selecting the file and confirming.
In some specific situation, this stops working (while doing some edits in the page via javascript / ajax), and I need to "reenable" it.
But, and that is my question, I haven't found any documentation of this "feature" in Google Chrome (or maybe some other browsers as well, I don't know). Why it works, how it works, how it should work and what to do if it stops working :) Does anyone has any experience with this ? The only way how to "fix" it now is to reload the page. I'd love to solve it ... :)
EDIT 1 : I just did a quick test, it works and bugs the same way in Firefox on Win. It doesn't show any error in dev console or any message, it just doesn't add the file as expected.
I've found it. The previous discussion with deceze pointed me to test the javascripts I have on the page, that do not "interfere" with the input type=file ... they weren't any such scripts, but I've found that after doubleclick on the table (that I'm using for editing) this script is being called
$(document).bind('drop dragover', function (e) {
e.preventDefault();
});
and there wasn't any unbind action when table is saved ... this caused the drag and drop everywhere on the page to stop working after the edit.

Duplicate a tab in Chrome without Reloading the Page?

Is there any way to completely duplicate the state of a current tab in Google Chrome? I want an exact copy of the current state of the page without having to reload the page in another tab.
An example use case:
While browsing a "slideshow" on a news website, I want to preserve the current slide that I'm on, but create a duplicate so that I can continue viewing the next slide. If I simply Right-Click and "Duplicate" the tab, the new page will completely Reload, reprocessing all of the Javascript and running the pre-slideshow advertisement again.
In short "NO" you can't.
I am not expert on this
but a similar behavior can be achieved in some ways i know :
Dump the whole DOM
Never tried this though. You can convert the DOM to a string, pass it to the new window and then parse it as a document. This will let you lose your DOM events and State manipulation javascript. (But that's good for your case)
var dtab = window.open('about:blank', 'duplicate_a_tab');
dtab.document.open();
dtab.document.write("... yout html string ..");
dtab.document.close();
Develop an extension
Let the users continue on the current tab with the current state, your extension should be able to capture the screenshot of that area and open that screenshot in new tab. There are plenty of screenshot taking extensions are available in the market.
If that website is your own
You can develop your services that uses state locally like progressive web apps. Give a link separately to 'duplicate' which will eventually open the same URL in different tab with the same local state and with the flag do-not-sync.
This will not work when the user uses browser inbuilt duplicate
feature.

Is there a way to uniquely identify tabs for the lifetime of the tab?

I was thinking of using the tabid to do this, but it seems to change quite often as I am browsing around within the tab. The API reference notes that the tabid is unique within a "browser session". I took this to mean within the lifetime of the browser process, but it seems more likely now that uniqueness is only guaranteed during a session with a specific website. Is there another way I could uniquely identify a tab for its entire life?
Due to prerendering and other factors, tabs can be 'replaced'. This means that tabId can change even if you keep the tab open. chrome.webNavigation.onTabReplaced can be used to capture such events. See https://developer.chrome.com/extensions/webNavigation.html#event-onTabReplaced for more information.
To demonstrate this, following these steps may help:
Make sure that you've requested "tabs" and "webNavigation" request for your extension and your extension doesn't use a non-persistent background page (without background.persistent = true in manifest.json). Also make sure Google is your default search engine and Instant Search is enabled.
Open some website (not Google search).
Execute chrome.tabs.query({}, function(tabs){console.log(tabs)}) in the developer tools of your extension's background page. Look at existing tabs and their ids.
Execute chrome.webNavigation.onTabReplaced.addListener(function(details){console.log(details); in the DevTools.
Type something in the omnibox of that tab to trigger Google Instant and click on the body of the page. You should see the onTabReplaced event fired and the old and new tab ids in the console of the DevTools.
Execute chrome.tabs.query({}, function(tabs){console.log(tabs)}) again and you'll find that tab id actually 'changed'.

How to get the changed content in the page?

I wrote a user script for the latest Chrome browser. It seems the script can't get the changed content of the page after loaded (for example, after the page loaded, I clicked ¿sth? and an embedded window popped up).
Even if I used window.setTimeout(), I still can't the get updated content in the timer callback through document.getElementById(). I inspected the page and found that the popup element existed in the DOM.
Is this a limitation of user script? Or some other methods could be used to get the update in user script?
Update:
I tried DOMSubtreemodified event as suggested. But the behavior is still strange.
I added only one one line of JavaScript to the userscript for my.safaribooksonline.com,
document.addEventListener("DOMSubtreeModified", function () {
alert(eval('typeof OpenSignInPopup')); });
But the alert box shows "undefined" as the evaluate result of OpenSignInPopup. But I can run the alert statement in the script console in the same page at the same time, and shows the result as "function".
This function was not loaded when the user script is running at first. So how can I use it in the user script?
You need to provide details, like the relevant code snippet(s) and the pages targeted.
In general, you can fire off the DOMSubtreeModified event in chrome. That should get you access to the changed DOM.
Also, are you sure the new content is not in an iframe?
Update for new OP info:
But the alert box shows "undefined" as the evaluate result of OpenSignInPopup.
In Chrome, Greasemonkey code cannot interact with the page's JS functions like that. You'll need to inject your code into the page. See this SO answer for more information.