How to Disable Javascript in Chrome (-headless) using PHP Webdriver - javascript

I am using Chrome headlessly.
I tried setting the --disable-javascript command line argument.
I tried using the experimental options:
$options->setExperimentalOption('prefs', [
'profile.managed_default_content_settings.javascript' => 2//this does not work
//,'profile.default_content_setting_values.javascript' => 2//this does not work, too
]);
$capabilities = DesiredCapabilities::chrome();
$capabilities->setCapability(ChromeOptions::CAPABILITY, $options);
As of this point these two do not work.
How can I disable javascript in Chrome using the Facebook PHP Webdriver ?
Here is a test to check if JavaScript is enabled:
$this->driver->get('https://www.whatismybrowser.com/detect/is-javascript-enabled');
return [
$this->driver->getTitle(),
$this->driver->findElement(WebDriverBy::cssSelector('.detected_result'))->getText()
];

It is simply impossible. Read here http://yizeng.me/2014/01/08/disable-javascript-using-selenium-webdriver/
WARNING: Running without JavaScript is unsupported and will likely break a large portion of the ChromeDriver's functionality. I suspect you will be able to do little more than navigate to a page. This is NOT a supported use case, and we will not be supporting it.
Closing this as WontFix - the ChromeDriver (and every other WebDriver implementation I'm aware of) require JavaScript to function.

It's possible to disable the execution of Javascript by setting one of the these preferences :
"webkit.webprefs.javascript_enabled": false
"profile.content_settings.exceptions.javascript.*.setting": 2
"profile.default_content_setting_values.javascript": 2
"profile.managed_default_content_settings.javascript": 2
But it's currently not supported headlessly since this mode doesn't load the preferences and there's no command switch related to this feature.
Note that disabling JavaScript used to break Selenium since most of commands are atom scripts injected in the page. It's no longer the case. All the commands are able to run. However I noticed that the returned text doesn't include the text from a <noscript> element (text displayed only when JavaScript is disabled). One workaround is to read the innerText property with either execute_script or get_attribute.

As others have pointed, it is still NOT possible to disable JavaScript in Chrome when headless.
However, for future reference, this is how you do it (when you are NOT using the --headless argument):
$options = new ChromeOptions();
$options->setExperimentalOption('prefs', [
'profile.managed_default_content_settings.javascript' => 2,
]);
$result = DesiredCapabilities::chrome();
$result->setCapability(
ChromeOptions::CAPABILITY_W3C,
// There is a bug in php-webdriver, so ->toArray() is needed!
$options->toArray()
);

Although regular headless mode in Chrome prevents disabling JavaScript, there's a newer headless mode without restrictions.
The Chromium developers recently added a 2nd headless mode that functions the same way as normal Chrome.
The NEW way: --headless=chrome
The OLD way: --headless
There's more info on that here: https://bugs.chromium.org/p/chromium/issues/detail?id=706008#c36
This means that you can now disable JavaScript when using the newer headless mode.

Related

How to detect older versions of iOS and prevent a script from loading [duplicate]

This question already has answers here:
Detect iOS version less than 5 with JavaScript
(9 answers)
Closed 12 months ago.
Our company recently decided to stop support for iOS 12.3 and below. However a small fraction of users are still on older devices that do not support newer JavaScript operators or syntax.
In order to prevent our script from affecting these users we are looking for ways to stop our script from loading if iOS v12.3 or below is detected.
Our JS code is loaded onto client websites via script tags like so:
<script src="exampledomain.com/example.js"></script>
Our first idea was to detect the useragent like this post but there are some problems with this approach.
It is strongly advised against for several reasons outlined here
Detecting the user agent within our script means that it still loads and throws errors when iOS <12.3 encounters syntax it cannot handle.
Detecting the user agent using conditional javascript on our client websites before loading our script is a possibility but difficult to maintain and not ideal for our customers.
Another option is to point the src of our script element to a script that can detect the UA and serve different versions of our script. However our script is time sensitive and the additional time it takes to make 2 requests instead of 1 is something we would like to avoid.
Lastly it is also possible to detect iOS versions without using the useragent by specifically targetting features that are not supported. For example using the nullish coalescing operator (??) in a try catch statement could indicate that the device is below iOS 12.3. But this method also relies on running JavaScript directly on the client website or doing multiple requests.
I would like to know if there are alternative methods we have not considered. Thanks.
This code snipped detects iOS version, so you can manage the scripts from backend side:
function getIOSVersion() {
const ua = navigator.userAgent;
if (/(iPhone|iPod|iPad)/i.test(ua)) {
return ua.match(/OS [\d_]+/i)[0].substr(3).split('_').map(n => parseInt(n));
}
return [0];
}
If you do not want to use UserAgent you can use the information of the platform the browser is compiled:
function getIOSVersion() {
const ua = navigator.platform;
if (/(iPhone|iPod|iPad)/i.test(ua)) {
return ua.match(/OS [\d_]+/i)[0].substr(3).split('_').map(n => parseInt(n));
}
return [0];
}

How do I make WebStorm recognize the JavaScript "window" object for type-hinting and warnings?

I'm working in React, running WebStorm 2017.3.5
WebStorm is not recognizing the window object as anything special like it does in other JavaScript projects.
For instance, both of the following lines produce "Unresolved function or method" warnings:
window.addEventListener("resize", resizeHandler);
window.alert("foo");
These (and other standard window methods) also don't show up in the code completion section when I type window.
The behavior works as expected for document.
Anyone know what I need to enable to make Web Storm aware of window?
EDIT: invalidating cache did not help.
Possible fix:
Change language level from React to ECMA 6 (Settings --> Languages & Frameworks --> JavaScript --> JavaScript language version
Delete all code in the current file (cut to clipboard)
type window. on the now empty first line. Type hinting should pick up on window, make it a different color, and show methods for alert(), addEventListener(), etc
Paste original code
Return language level to React/JSX
I have no idea why the above worked when invalidating caches and restarting did not. I tried doing just 2 and 3 alone without success, and just 1 alone also without success.

Google Chrome - how can i programmatically enable chrome://flags some of the modules from disable mode to enabled mode?

How can I automate the setting of chrome flags to enable few modules?
I have application designed which requires on open the chrome://flags few modules enabled, otherwise the whole application does not work, for normal user its nightmare to do such small changes.
Is there any javascript or google app engine or other method to use from server side scripting or some plugin where i can say click this and it will automatically enable the modules inside chrome://flags?
Almost every Chrome flag can be set via the command line. Here is a quite exhaustive list of command line parameters, but also keep in mind that there would be even more in newer versions!
EDIT: Here is the Comprehensive, up-to-date list of Chrome command line switches
So basically you would launch chrome with these command line flags already set. That's the best way to go about it.
You cannot manually set this using Javascript or other behavior. The only way you can set this programmatically (other than command line flags) is to use Capybara (a tool that can open and control browsers, generally used for running automated tests), open Chrome and then manually navigate to "chrome://flags" and click the necessary combo boxes.
EDIT: Watir is also as good as Capybara
Watir is another browser automation framework (similar to Capybara) but is much easier to setup and start with. Here are examples on how you would open a web page and select a combo box, and here are instructions on using it with Chrome. You can write a single ruby file which looks like:
require 'watir-webdriver'
browser = Watir::Browser.new :chrome
browser.goto "chrome://flags"
browser.select_list(:id => <combo box id>).select("Enabled")
...
Persisting the Flags when using WebDriver
Chrome has the --user-data-dir switch which is where all the profile settings are saved. The default directories that Chrome uses (on Windows/Mac/Linux) [is documented here. Generally, WebDriver launches with a temporary --user-data-dir, and later deletes the temporary folder after use. So whatever flags you set will be lost when you run Chrome again! So set --user-data-dir to your user's default profile directory, and then whatever flags you set will be persisted.
Edit 2: Added comprehensive list of chrome command line flags
Edit 3: Added instructions for persisting the flags in Webdriver
Rooting about in the chrome://flags screen I found something interesting in an included JS file :
/**
* Invoked when the selection of a multi-value choice is changed to the
* specified index.
* #param {HTMLElement} node The node for the experiment being changed.
* #param {number} index The index of the option that was selected.
*/
function handleSelectChoiceExperiment(node, index) {
// Tell the C++ FlagsDOMHandler to enable the selected choice.
chrome.send('enableFlagsExperiment',
[String(node.internal_name) + '#' + index, 'true']);
requestFlagsExperimentsData();
}
chrome.send is indeed a valid method,
Here is another snippet form the same file (chrome://flags/flags.js)
/**
* Asks the C++ FlagsDOMHandler to restart the browser (restoring tabs).
*/
function restartBrowser() {
chrome.send('restartBrowser');
}
Manually calling chrome.send ('restartBroswer') did indeed restart the browser.
I think this provides all the facilities you need to automate the setting of the flags, you will need to trawl through the chrome://flags source to find the flags you need and then
set up the appropriate chrome.send calls.

Setting breakpoints dynamically at runtime in Javascript

Both firebug and the built in console in webkit browsers make it possible to set breakpoints in running Javascript code, so you can debug it as you would with any other language.
What I'm wondering is if there is any way that I can instruct firebug or webkit that I'd like to set a breakpoint on line X in file Y at runtime, and to be able to examine variables in the specific scope that I have paused in.
I need something that can work in both Chrome (or any other webkit browser) and Firefox. For the latter Firebug is an acceptable dependency. Supporting IE is not a requirement.
I've been building an in-browser IDE ( quick video for the interested: http://www.youtube.com/watch?v=c5lGwqi8L_g ) and want to give it a bit more meat.
One thing I did try was just adding debugger; as an extra line where users set them, but this isn't really an ideal solution.
I'd say you can definitely do this for webkit browsers using the remote debugging protocol. This is based on a websocket connection and a json message protocol that goes back and forth.
You can read the announcement and the whole protocol schema.
Chrome also offers more information about this inside its remote developer-tools docs.
For the debugger domain, for instance, you can see how you can use Debugger.setBreakpoint, Debugger.setBreakpointByUrl and Debugger.setBreakpointsActive to work with breakpoints.
On the other hand, Mozilla also seems to be working on this as you can see in https://developer.mozilla.org/en-US/docs/Tools/Debugger-API and https://wiki.mozilla.org/Remote_Debugging_Protocol though I don't know the completion status of it.
In this case, you can work with breakpoints using the Debugger.Script APIs setBreakPoint, getBreakPoint, getBreakpoints, clearBreakpoints and clearAllBreakpoints
I hope this helps you move forward.
There isn't such a thing, at least not using the public, scriptable side of JavaScript. It would be possible if you have a privileged browser extension that could do that for you. For example, Firebug has a debug method which you can call from its command line, but not from scripts inside a page.
So, you have two solutions:
Implement your own JavaScript interpreter, which you can control as you wish. Might be a bit too ambitious, though...
Rely on a browser extension that can set breakpoints anywhere in the code, expose some API to public code, and interact with it from your JavaScript. But that means that users will have to install some extra piece of software before they can use your "Web IDE".
Use _defineSetter__ to watch variables, and combine it with a call to debugger when an assignment happens.
__defineSetter__("name", function() { debugger; });
or defineProperty:
function setter () { debugger; }
Object.defineProperty(Math, 'name', { set: setter });
References
MDN: Object.defineProperty
A List Apart: Advanced Debugging With JavaScript
JavaScript Getters and Setters

Code Sign Javascript to use 'new ActiveXObject()' / 'GetObject()'

I've got a javascript file that uses
excel = GetObject("", "Excel.Application");
to hook a current running instance of excel, however it requires me to drop my security settings super low. How do I go about code-signing a javascript file to at least cause a security prompt instead of just failing? Google-ing keeps getting me results for signing custom activex controls, .dlls, and .exes but all I need is the built-in function approved.
On a related note
http://msdn.microsoft.com/en-us/library/7tf9xwsc%28v=vs.94%29.aspx
"The GetObject function is not supported in Internet Explorer 9 standards mode or later."
What is the proper method for accessing a currently running application in IE9 then?
There is no way to do that; there's no "code signing" mechanism for JavaScript.

Categories