detect new browser window with WATIN - watin

is there a way to test wether a link was opened in a new browser-window (or browser-tab)?
Update:
So far I used the following code:
var newBrowserWindow = Browser.AttachTo<IE>(Find.ByTitle(browserTitle));
Assert.That(newBrowserWindow.hWnd, Is.Not.EqualTo(existingBrowserWindow.hWnd));
Where I used the existingBrowserWindow to open a page and to click on a link. But when the link opens a new tab in the existing browser (default behaviour for IE with targer=_blank) it has the same window-handle, since it's the same browser window. So how can I detect a new tab?

Some code of yours would help...,
Anyway, what I do when a link open a new browser window is
using (var newBrowser = WatiN.Core.Browser.AttachTo<IE>(Find.ByTitle("Analytics - Read conversation"))
{
}
Browser.AttachTo supports Find.ByUri(), Find.ByTitle() and Find.By("hwnd", windowHandle) according to documentation. I only tested Find.ByUri() and Find.ByTitle() methods.
if you want to detect if you action has opened a new window you could do
public bool TryGetNewBrowser(out IE browser, string title)
{
try
{
browser = WatiN.Core.Browser.AttachTo<IE>(Find.ByTitle(title));
return true;
}
catch(WatiN.Core.Exceptions.BrowserNotFoundException)
{
browser = null;
return false;
}
}
As far as I know, there is no support in WatiN for new tab. But the default behavior of internet explorer is to open new links in new window.

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);

Firefox crashes on element.remove()

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?

Could not get Alert dialog with Firefox when using final WatiN version

The code below works well with IE7, but when I switch to run with Firefox (from 3.0 to 3.6) I could not get the the Dialog. It raise error on line: DiaglogHandler.WaitUntilExists(10) "Dialog not available within 10 seconds." even though the dialog is there. I'm using the final WatiN release.
string url = "https://www.xxx.com"
Settings.AutoStartDialogWatcher = true;
Settings.AutoCloseDialogs = false;
//var browser = new IE();
var browser = new FireFox();
browser.GoTo(url);
Image theButton = browser.Image(Find.By("id", "button"));
AlertDialogHandler DiaglogHandler = new AlertDialogHandler();
DialogWatcher theDialogWatcher = new DialogWatcher(new WatiN.Core.Native.Windows.Window(browser.hWnd));
theDialogWatcher.Add(DiaglogHandler);
theDialogWatcher.CloseUnhandledDialogs = false;
theButton.ClickNoWait();
DiaglogHandler.WaitUntilExists(10);
Console.WriteLine(DiaglogHandler.Message);
Console.WriteLine("Done");
Console.ReadLine();
Afaik WatiN does not deal well with Dialogs yet, though it is on the horizon.
It is possible to get around them, say passing an Enter to the browser or other javascript interaction.
I've had similar issues with Authentication Required Dialogs in FireFox

Reusing a tab in Firefox, TabOpen event, and beyond

I followed a tutorial on reusing tabs inside Firefox, and right now my extension does it well. However, I also need to reuse tabs that are opened from outside (from some application, start menu etc.). How do I do this?
I tried adding an event listener for TabOpen event, but when I log the
event.target.linkedBrowser.currentURI.spec
it's value is "about:blank". I expected the actual address that I typed into the address bar (automatically opens in a new tab), or the address that I open from some other application, so I can close that tab immediately, and the focus the right one. What am I doing wrong?
Thanks in advance.
Just in case, here's the code that reuses the tab when a new tab is requested from an extension
function openAndReuseOneTabPerURL(url) {
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var browserEnumerator = wm.getEnumerator("navigator:browser");
// Check each browser instance for our URL
var found = false;
while (!found && browserEnumerator.hasMoreElements()) {
var browserWin = browserEnumerator.getNext();
var tabbrowser = browserWin.getBrowser();
// Check each tab of this browser instance
var numTabs = tabbrowser.browsers.length;
for(var index=0; index<numTabs; index++) {
var currentBrowser = tabbrowser.getBrowserAtIndex(index);
if (url == currentBrowser.currentURI.spec) {
// The URL is already opened. Select this tab.
tabbrowser.selectedTab = tabbrowser.mTabs[index];
// Focus *this* browser-window
browserWin.focus();
found = true;
break;
}
}
}
// Our URL isn't open. Open it now.
if (!found) {
var recentWindow = wm.getMostRecentWindow("navigator:browser");
if (recentWindow) {
// Use an existing browser window
recentWindow.delayedOpenTab(url, null, null, null, null);
}
else {
// No browser windows are open, so open a new one.
window.open(url);
}
}
}
When you receive the TabOpen event, it's too early for the page content to be loaded still. When you receive the TabOpen event, however, you should register for load or DOMContentLoaded. When you receive that event, you should be able to access the URI.
I guess you could extract the wanted behaviour from the implementation in the Tab Mix Plus extension

Resources