I am testing the BroadcastChannel functionality and I'am having trouble. I open two Chrome windows and the dev tools for each. On the console I write:
const z = new BroadcastChannel('blarg')
z.onmessage = function (ev) {console.log(ev)}
I can examine z and it has the function saved to the onmessage prop so it all looks good. However, when I test:
z.postMessage('sweet')
in one of the consoles, nothing shows in the other. I would expect since both Chrome windows are subscribed to the broadcast channel blarg and have a function to console log the message that is posted, I would see the message sweet to be shown in the other console but nothing happens.
So two questions:
Can't I test BroadcastChannel interface in the devtools console like this?
If so, what am I missing about how BroadcastChannel works?
It works if:
the communication happens on the same origin
the channel name is the same on both ends (blarg in your case, but it could also be "")
you don't expect to receive the message if you are the sender
When you say
I open two chrome windows and the dev tools for each.
call them A and B. In nomenclature A and B are defined as "browsing contexts", and they could also be tabs, frames or iframes.
The following code is an example that satisfies conditions 1. and 2.
devtools A:
location.href = 'https://example.com'
z = new BroadcastChannel('blarg')
z.onmessage = (ev) => { console.log(ev) }
devtools B:
location.href = 'https://example.com'
z = new BroadcastChannel('blarg')
z.onmessage = (ev) => { console.log(ev) }
Condition 1 is also satisfied when browser contexts (windows, tabs, frames or iframes) don't "point" to any regular url (for example when you press CTRL+T to open a new tab). In this case the origin has the special value of chrome://new-tab-page.
Said that, if you post from A to B, B will receive the message and console.log it. The same applies vice versa.
Related
Edge claims to support webkitSpeechRecognition, but it doesn't work (discussion here, doesn't work on websites meant for testing, like this mozilla one, with the error "Error occurred in recognition: language-not-supported" despite my US english UI).
How can I detect if webkitSpeechRecognition is actually supported? I tried to filter out Edge by looking at the user agent, but it shows up as Chrome, and I'd prefer to just use feature detection rather than looking at the user agent anyway. I'd like to check this without requesting microphone permission (if I did request microphone permission, I'd have to wait for them to accept, and then see the language-not-supported error). Is there a simple way to check this, similar to just checking the value of window["webkitSpeechRecognition"] (which is defined in Edge, despite not working)?
If you want to check the support for webkitSpeechRecognition then you can refer to the JS code example below.
if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)
{
console.log("speech recognition API supported");
}
else
{
console.log("speech recognition API not supported")
}
Output in MS Edge 88.0.705.56:
However, if you directly try to make a test using webkitSpeechRecognition then it will not work.
It looks like this feature is currently under development and to use it we need to enable it by passing the command line arguments.
I suggest you refer to the steps below.
Create a shortcut of the Edge chromium-browser.
Right-click the shortcut file and go to Properties.
Under Shortcut tab, in the Target textbox, add --enable-features=msSpeechRecognition after the msedge.exe path. Make sure to add 1 space between the path and command-line argument.
It should look like below.
Click on the OK button to close the properties window.
Launch the Edge browser via shortcut and visit any sample code example for SpeechRecognition. Here I am making a test with this example.
Output in MS Edge 88.0.705.56:
In addition, it's useful to check for errors (as shown in the above example source code, see below, https://www.google.com/intl/en/chrome/demos/speech.html): for instance audio might be disabled if not on a https website.
recognition.onerror = function(event) {
if (event.error == 'no-speech') {
start_img.src = '/intl/en/chrome/assets/common/images/content/mic.gif';
showInfo('info_no_speech');
ignore_onend = true;
}
if (event.error == 'audio-capture') {
start_img.src = '/intl/en/chrome/assets/common/images/content/mic.gif';
showInfo('info_no_microphone');
ignore_onend = true;
}
if (event.error == 'not-allowed') {
if (event.timeStamp - start_timestamp < 100) {
showInfo('info_blocked');
} else {
showInfo('info_denied');
}
ignore_onend = true;
}
};
I need to capture the console logs (category: info) of a browser using Ruby & Capybara. Until now I have tried using driver.manage.logs.get(:browser) or (:client) but, using this, the result is not what I want. It gives out the interaction results between selenium and browser where I can see my javascript statements sent for execution, but the resulting output fails to get captured.
Whether or not logs are available when using selenium depends on what browser you are using with Selenium. If you were using Firefox you'd be out of luck since it doesn't support the log retrieval API, however since you're using Chrome they are accessible. The issue you're having is that, by default, only WARN or ERROR level logs are captured. You can change this in the driver registration through the loggingPrefs capability
Selenium 3
Capybara.register_driver :logging_selenium_chrome do |app|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs:{browser: 'ALL'})
browser_options = ::Selenium::WebDriver::Chrome::Options.new()
# browser_options.args << '--some_option' # add whatever browser args and other options you need (--headless, etc)
Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options, desired_capabilities: caps)
end
Selenium 4
Capybara.register_driver :logging_selenium_chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_option("goog:loggingPrefs", {browser: 'ALL'})
browser_options = ::Selenium::WebDriver::Chrome::Options.new()
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(app,
capabilities: options,
browser: :chrome)
end
end
and then specify to use :logging_selenium_chrome as your driver
Capybara.javascript_driver = :logging_selenium_chrome # or however else you're specifying which driver to use
which should then allow you to get the logs in your tests with
page.driver.browser.manage.logs.get(:browser)
Thomas Walpole answer is correct but it seems that nowadays if you are using chrome as your driver you should use
Selenium::WebDriver::Remote::Capabilities.chrome( "goog:loggingPrefs": { browser: 'ALL' } )
Notice goog:loggingPrefs instead of loggingPrefs only with this solution i was able to get console.log printed in the log.
Took me a while and got it from here https://intellipaat.com/community/5478/getting-console-log-output-from-chrome-with-selenium-python-api-bindings after several frustrating attempts.
November 2022 update, use:
page.driver.browser.logs.get(:browser)
Not sure that this is what you want, but take a look at https://github.com/dbalatero/capybara-chromedriver-logger.
It helps me identify the problem with dynamic modules import(''). Works both locally and in Github Actions / Circle CI by displaying failed loads of assets (which i believe outputs as console.error).
I have one situation,where i need to pass some json from one window to new window in the same domain.I have first window lets say it window1 and second window,let say it window2.
I have following code in window1:
var params = [
'height=750',
'width=720',
'scrollbars=yes',
'left=0',
'top=0',
'fullscreen=no', // only works in IE, but here for completeness
'location=no'
].join(',');
var port = location.port;
var url = "http://" + hostName + ':' + port + "/isecalreport" + location.search;
var newWindow = window.open(url,'photocal_report',params);
while(true){
if(newWindow! == undefined) {
newWindow.location.state={payloadFromIseCalWeekly : payloadFromIseCalWeekly,instrumentIdObj : instrumentIdObj};
break;
}
}
Code in window2:
var payloadFromIseCalWeekly = location.state.payloadFromIseCalWeekly ? location.state.payloadFromIseCalWeekly : {};
I want to make use of the json set in window.location.state.
So the problem is ,It works fine in chrome ,mozilla,but fails in IE 11(when debugger is not open.)
When i open debugger in IE11 ,it works fine.
I debugged it and found out that after the instruction which is opening the new window ,the next instruction get run and it doesnot find the new window object.
Its strange as it works when developer console is open.
It would be good if i can get insights about how to resolve the issue.
My aim is to open a new window ,to which i need to pass some data and using that data i want to do an API call.
With few exceptions, you cannot tell one window, tab or frame to talk to another directly. This is to prevent malicious scripts in one of these contexts from hijacking another across pages.
To cope with this, you have two options, you can use postMessage() or simply pass your data via the URL that you open in the new window. There are technically more options if you're on the same domain, but I recommend against going down that rabbit hole.
Sending data via the URL is a one-way affair. You can send query string variables in the URL that the new window can read, but it can't send anything back to the window that created it.
postMessage(), on the other hand, can be used to communicate between multiple contexts and across domains. It is considered secure because it requires that all participants be listening for messages, rather than allowing direct code access.
Your various pages can listen for messages with a simple event listener.
// listen for incoming messages on this page
window.addEventListener('message', function(e) {
// this is the handler function
// do we trust where this was sent from?
if (event.origin !== "http://example.com") {
// if so, print the resulting event object
console.log('message received', e);
}
}, false);
You can then send a message from another page to your window.
// the * is the targetOrigin, read the docs!
newWindow.postMessage("some message data", "*");
After a new install of Firefox 45 Developer Edition, I saw this page. It has a button ("Let's do it") that when clicked, somehow opens up the Choose default apps settings page in Windows 10.
https://www.mozilla.org/en-US/firefox/windows-10/welcome/?utm_source=firefox-browser&utm_medium=firefox-browser
How is this done? I couldn't find anything through the Developer Console in the labyrinthine code on that page. Besides, I would have thought browsers don't allow JavaScript to open something as sensitive as the Settings app.
The page fires a custom event of type mozUITour on the document. This event is handled in the browser by content-UITour.js, which shovels out most of the actual processing to UITour.jsm. The unobfuscated client-side code can be viewed in UITour-lib.js.
Cutting through all the client-side abstraction, this is what’s happening:
document.dispatchEvent(new CustomEvent('mozUITour', {
bubbles: true,
detail: {
action: 'setConfiguration',
data: {
configuration: 'defaultBrowser'
}
}
}));
Then in the browser, it handles the event, dispatches the event in another internal event queue, where it will be processed by calling into nsIShellService::setDefaultBrowser, implemented by nsWindowsShellService.cpp. On what’s currently line 943, we have:
if (IsWin10OrLater()) {
rv = LaunchModernSettingsDialogDefaultApps();
} else {
rv = LaunchControlPanelDefaultsSelectionUI();
}
And LaunchModernSettingsDialogDefaultApps, I think, is a pretty descriptive function name.
Now, from your comment, “in a way that one could use it on their own page, for example”? Not so likely. content-UITour.js checks that the page has the uitour permission. From browser/app/permissions, we have:
# UITour
origin uitour 1 https://www.mozilla.org
origin uitour 1 https://self-repair.mozilla.org
origin uitour 1 https://support.mozilla.org
origin uitour 1 about:home
So unless you’re www.mozilla.org, self-repair.mozilla.org, support.mozilla.org, or about:home, you can’t do it, at least not by default. Before Firefox 15 (17 with a manual settings change, see this bug for more information), you might be able to use netscape.security.PrivilegeManager.enablePrivilege to request extra permissions from the browser, but that’s not around any more, and I’m not sure that even touches the same permission mechanism.
My add-on creates a FireFox File menu command that triggers callback function 'launchApp'.
function launchApp() {
var ww = Cc["#mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
var appUrl='chrome://mrT2/mrT00.xul'; // production (fails)
var appUrl='file:///C:/mpa/##mrT-2.0/mrT00.xul'; // testing (works)
var win = ww.openWindow(null, appUrl, "mrT2-window", "chrome,resizable", null);
// Summary of results of ww.openWindow() for various appUrl values:
// 'chrome:///mrT2/mrT00.xul' 'No chrome package registered for ...' (true)
// 'chrome://mrT00.xul' 'Invalid chrome URI: /' (true)
// 'chrome:///mrT00.xul' and 'chrome://mrT2/mrT00.xul' seem valid yet both give:
//Error: NS_ERROR_ILLEGAL_VALUE: Component returned failure code: 0x80070057 ...
// ... (NS_ERROR_ILLEGAL_VALUE) [nsIWindowWatcher.openWindow] (unexplained)
return true;
The above code works nicely and is great for testing mrT00.xul (because it collects the file directly from where I am editing it).
However when I interchange the two appUrl vars to try and open the exact same file as shipped via the xpi (and now internal to firefox) I get the dreaded 'illegal value' 0x80070057.
After 2 long days of research and study I cannot fault my code. Can you?
Otherwise, how may I begin tracing nsiWindowWatcher to pinpoint the error?
Bad things can happen when an extension attempts to open a xul file outside the /content directory or inside it when the chrome.manifest file in the .xpi root is not in order. Firefox handling of both these situations is not above reproach, warnings being offered in neither case.