Dynamically changing proxy in Firefox with Selenium webdriver - firefox

Is there any way to dynamically change the proxy being used by Firefox when using selenium webdriver?
Currently I have proxy support using a proxy profile but is there a way to change the proxy when the browser is alive and running?
My current code:
proxy = Proxy({
'proxyType': 'MANUAL',
'httpProxy': proxy_ip,
'ftpProxy': proxy_ip,
'sslProxy': proxy_ip,
'noProxy': '' # set this value as desired
})
browser = webdriver.Firefox(proxy=proxy)
Thanks in advance.

This is a slightly old question.
But it is actually possible to change the proxies dynamically thru a "hacky way"
I am going to use Selenium JS with Firefox but you can follow thru in the language you want.
Step 1: Visiting "about:config"
driver.get("about:config");
Step 2 : Run script that changes proxy
var setupScript=`var prefs = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.setIntPref("network.proxy.type", 1);
prefs.setCharPref("network.proxy.http", "${proxyUsed.host}");
prefs.setIntPref("network.proxy.http_port", "${proxyUsed.port}");
prefs.setCharPref("network.proxy.ssl", "${proxyUsed.host}");
prefs.setIntPref("network.proxy.ssl_port", "${proxyUsed.port}");
prefs.setCharPref("network.proxy.ftp", "${proxyUsed.host}");
prefs.setIntPref("network.proxy.ftp_port", "${proxyUsed.port}");
`;
//running script below
driver.executeScript(setupScript);
//sleep for 1 sec
driver.sleep(1000);
Where use ${abcd} is where you put your variables, in the above example I am using ES6 which handles concatenation as shown, you can use other concatenation methods of your choice , depending on your language.
Step 3: : Visit your site
driver.get("http://whatismyip.com");
Explanation:the above code takes advantage of Firefox's API to change the preferences using JavaScript code.

As far as I know there are only two ways to change the proxy setting, one via a profile (which you are using) and the other using the capabilities of a driver when you instantiate it as per here. Sadly neither of these methods do what you want as they both happen before as you create your driver.
I have to ask, why is it you want to change your proxy settings? The only solution I can easily think of is to point firefox to a proxy that you can change at runtime. I am not sure but that might be possible with browsermob-proxy.

One possible solution is to close the webdriver instance and create it again after each operation by passing a new configuration in the browser profile

Have a try selenium-wire, It can even override header field
from seleniumwire import webdriver
options = {
'proxy': {
"http": "http://" + IP_PORT,
"https": "http://" + IP_PORT,
'custom_authorization':AUTH
},
'connection_keep_alive': True,
'connection_timeout': 30,
'verify_ssl': False
}
# Create a new instance of the Firefox driver
driver = webdriver.Firefox(seleniumwire_options=options)
driver.header_overrides = {
'Proxy-Authorization': AUTH
}
# Go to the Google home page
driver.get("http://whatismyip.com")
driver.close()

Related

Selenium w/ Firefox not accepting HTTP Proxy IP with user authentication

I'm looking to use Selenium with a username/password authenticated proxy in Ruby. I realize that most people use ProxyChain when doing this in Chrome, but I'd like to use a solution without any additional gems since it doesn't play well on Heroku, plus I'm using Firefox so there seems to be a possible other option judging by THIS question though it's written in Python.
I used the selenium docs to translate that code to Ruby, but Selenium is still not using my proxy when navigating to a webpage. Oddly enough when I refresh the page manually it prompts me for the username/password but it doesn't do that on the initial page load.
profile = Selenium::WebDriver::Firefox::Profile.new
profile["network.proxy.type"] = 1
# proxy ip and port are fake for this example
profile["network.proxy.http"] = "182.192.157.60"
profile["network.proxy.http_port"] = 12345
# set the username and password
profile["network.proxy.socks_username"] = "my_username"
profile["network.proxy.socks_password"] = "my_password"
options = Selenium::WebDriver::Firefox::Options.new(profile: profile)
driver = Selenium::WebDriver.for :firefox, options: options
If anyone has any ideas I would certainly appreciate the help. Thank you.

Not possible to test WebAssembly page locally with Firefox - SharedArrayBuffer not defined

I am using a WebAssembly based software that uses multi-threading that requires SharedArrayBuffer. It runs fine both in Chromium local/deployed, and Firefox 89 deployed, but since the best performance is under Firefox, I want to test and tune it on my machine, so I run python -m SimpleHTTPServer. In this situation, when I open 127.0.0.1:8000 or 0.0.0.0:8000 in Firefox, SharedArrayBuffer is undefined. Perhaps this is a security setting, but when using localhost, I'm really not interested in Firefox's interpretation of the situation -- this should just run. How can I make it work? Do I need a different web server, different settings?
As you guessed correctly, it has to do with security restrictions. There have been changes in regards to the use of SharedArrayBuffer that have already been implemented in Firefox 79 and will land in Chrome shortly as well (starting with Chrome 92). (Time of writing this: July 13, 2021.)
The main purpose is to restrict the use of SharedArrayBuffers in postMessage. Any such attempt will throw an error unless certain restrictive COOP/COEP headers are set to prevent cross-origin attacks:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Unfortunately, without these headers, there is also no global SharedArrayBuffer constructor. Apparently, this restriction may be lifted in the future. The objects themselves still work though (only passing them through postMessage would throw), but you need a different way to instantiate them. You can use WebAssembly.Memory instead:
const memory = new WebAssembly.Memory({ initial: 10, maximum: 100, shared: true })
// memory.buffer is instanceof SharedMemoryBuffer
You could now go one step further and recover the constructor from that. Therefore, with the following code as "shim", your existing code should work as long as it doesn't try to pass the buffer through postMessage:
if (typeof SharedArrayBuffer === 'undefined') {
const dummyMemory = new WebAssembly.Memory({ initial: 0, maximum: 0, shared: true })
globalThis.SharedArrayBuffer = dummyMemory.buffer.constructor
}
// Now, `new SharedArrayBuffer(1024)` works again
Further reading:
Article about this change on MDN
Google blog post about the upcoming change
WebAssembly.Memory documentation
As #CherryDT pointed out in the comment, the problem is missing headers for the local server. Searching the net, there is a blog that walks through the process of developing WebAssembly in Firefox with a python web server. Instead of python -m SimpleHTTPServer, one has to add a file ./wasm-server.py with this contents (for Python 2):
# Python 2
import SimpleHTTPServer
import SocketServer
class WasmHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header("Cross-Origin-Opener-Policy", "same-origin")
self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self)
# Python 3.7.5 adds in the WebAssembly Media Type. Version 2.x doesn't
# have this so add it in.
WasmHandler.extensions_map['.wasm'] = 'application/wasm'
if __name__ == '__main__':
PORT = 8080
httpd = SocketServer.TCPServer(("", PORT), WasmHandler)
print("Listening on port {}. Press Ctrl+C to stop.".format(PORT))
httpd.serve_forever()
then it is possible to test the application at 127.0.0.1:8080

Best way to control firefox via webdriver

I need to control Firefox browser via webdriver. Note, I'm not trying to control page elements (i.e. find element, click, get text, etc); rather I need access to Firefox's profiler and force gc (i.e. I need firefox's Chrome Authority and sdk). For context, I'm creating a micro benchmark framework, not running a normal webdriver test.
Obviously raw webdriver won't work, so what I've been trying to do is
1) Create a firefox extension/add-on that does what I need: i.e.
var customActions = function() {
console.log('calling customActions.')
// I need to access chrome authority:
var {Cc,Ci,Cu} = require("chrome");
Cc["#mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
Cu.forceGC();
var file = require('sdk/io/file');
// And do some writes:
var textWriter = file.open('a/local/path.txt', 'w');
textWriter.write('sample data');
textWriter.close();
console.log('called customActions.')
};
2) Expose my customActions function to a page:
var mod = require("sdk/page-mod");
var data = require("sdk/self").data;
mod.PageMod({
include: ['*'],
contentScriptFile: data.url("myscript.js"),
onAttach: function(worker) {
worker.port.on('callCustomActions', function() {
customActions();
});
}
});
and in myscript.js:
exportFunction(function() {
self.port.emit('callCustomActions');
}, unsafeWindow, {defineAs: "callCustomActions"});
3) Load the xpi during my webdriver test, and call out to global function callCustomActions
So two questions about this process.
1) This entire process is very roundabout. Is there a better practice for talking to a firefox extension via webdriver?
2) My current solution isn't working well. If I run my extension via cfx run directly (without webdriver) it works as expected. However, neither the sdk nor chrome authority do anything when running via webdriver.
By the way, I know my function is being called because the log line "calling customActions." and "called customActions." both do print.
Maybe there are some firefox preferences that I need to set but haven't?
It may be that you do not need the add-on at all. Mozilla uses Marionette for test automation of Firefox OS amongst other things:
Marionette is an automation driver for Mozilla's Gecko engine. It can
remotely control either the UI or the internal JavaScript of a Gecko
platform, such as Firefox or Firefox OS. It can control both the
chrome (i.e. menus and functions) or the content (the webpage loaded
inside the browsing context), giving a high level of control and
ability to replicate user actions. In addition to performing actions
on the browser, Marionette can also read the properties and attributes
of the DOM.
If this sounds similar to Selenium/WebDriver then you're correct!
Marionette shares much of the same ethos and API as
Selenium/WebDriver, with additional commands to interact with Gecko's
chrome interface. Its goal is to replicate what Selenium does for web
content: to enable the tester to have the ability to send commands to
remotely control a user agent.

How to edit the url in current browser using Watin

I need to navigate to new url from the current opened browser using Wating Code, Let me know if any one tried the same scenario. Also I need to get the url in the current opened browser.
using (IE browser = new IE())
{
browser.GoTo("www.google.co.uk");
string curentUrl = browser.Url;
}
If the browser is already open, you use the AttachTo static method
http://watinandmore.blogspot.com/2010/01/browserattachto-and-iattachto.html
HTH!

Register an application to a URL protocol (all browsers) via installer

I know this is possible via a simple registry change to accomplish this as long as IE/firefox is being used. However, I am wondering if there is a reliable way to do so for other browsers,
I am specifically looking for a way to do this via an installer, so editing a preference inside a specific browser will not cut it.
Here is the best I can come up with:
IE: http://msdn.microsoft.com/en-us/library/aa767914(VS.85).aspx
FireFox: http://kb.mozillazine.org/Register_protocol
Chrome: Since every other browser in seems to support the same convention, I created a bug for chrome.
Opera: I can't find any documentation, but it appears to follow the same method as IE/Firefox (see above links)
Safari: Same thing as opera, it works, but I can't find any documentation on it
Yes. Here is how to do it with FireFox:
http://kb.mozillazine.org/Register_protocol
and Opera:
http://www.opera.com/support/kb/view/535/
If someone looks like a solution for an intranet web site (for all browsers, not only IE), that contains hyperlinks to a shared server folders (like in my case) this is a possible solution:
register protocol (URI scheme) via registry (this can be done for all corporative users i suppose). For example, "myfile:" scheme. (thanks to Greg Dean's answer)
The hyperlink href attribute will then should look like
<a href='myfile:\\mysharedserver\sharedfolder\' target='_self'>Shared server</a>
Write a console application that redirects argument to windows explorer (see step 1 for example of such application)
This is piece of mine test app:
const string prefix = "myfile:";
static string ProcessInput(string s)
{
// TODO Verify and validate the input
// string as appropriate for your application.
if (s.StartsWith(prefix))
s = s.Substring(prefix.Length);
s = System.Net.WebUtility.UrlDecode(s);
Process.Start("explorer", s);
return s;
}
I think this app can be easily installed by your admins for all intranet users :)
I couldn't set up scheme setting to open such links in explorer without this separate app.

Resources