A selenium driver instance has two properties characterizing its connection to a selenium webdriver - a connection url, and session id. By setting those to the values of an already running one, you effectively "hijack" it, and can use freely.
Disclaimer - the solution uses internal SE structures, so can break on newer versions. Also, as you are connecting to the running webdriver as to aRemote one, you cannot close it even if you want to - thus this can lead to resources leakage on the machine that it runs on; e.g. that webdriver has to be eventually terminated manually by a task manager.
So first things first - you have a running browser instance, and you need to get its properties for future connections. They are 2 - driver.command_executor._url, and driver.session_id where driver is the object name of the running instance. This python code will do just that:
from robot.libraries.BuiltIn import BuiltIn
def return_driver_props()
seLib = BuiltIn().get_library_instance('SeleniumLibrary')
# the driver is instantiated in the SeleniumLibrary, but not provided publicly, thus accessing it through this py code
remote_url = seLib.driver.command_executor._url # for local instance, this is a value in the form 'http://localhost:57856'
session_id = seLib.driver.session_id
return remote_url, session_id
Importing that file as a Library, by calling the function/method you'll have the 2 props:
${conn_url} ${session_id}= Return Driver Props
# and do whatever is needed to make them known - log, store in a file, DB, etc.
Now in the second run that needs to reattach, and with the 2 values in hand, you just use the keyword Open Browser and specify a remote connection:
Open Browser about:about remote_url=${that_known_url} browser=${the_used_browser_type} # the last args - chrome|firefox|edge - whatever you're connecting two
The tricky part - the moment you connect to a remote server, selenium automatically starts a new session - which is a second browser instance (this started somewhere around selenium3, though I'm not sure on the exact timing). E.g. if you start using it right now - that is not the browser you wanted, but a brand new. That's also the reason why I gave as target address "about:about" - so it loads a dummy page, very fast.
Two things must happen at this point - a) you have to get rid of the "dummy" SE session, and b) switch to the previous one:
def set_driver_session_id(sesion_id):
""" Sets the sessoin_id of the current driver insance to the provided one. """
seLib = BuiltIn().get_library_instance('SeleniumLibrary')
if seLib.driver.session_id != sesion_id: # this is pretty much guaranteed to be the case
seLib.driver.close() # this closes the session's window
seLib.driver.quit() # for remote connections (like ours), this deletes the session, but doesn't stop the SE
# set to the session that's already running
seLib.driver.session_id = sesion_id
This function/keyword is called with the known session id:
Set Driver Session ID ${session_id}
,and voilà, you are now in control of the previous browser, with its full state - the url it was at, cookies, localStorage, etc.
I'm leaving as an exercise to the reader how to automatically pass the url and the session id.
What I myself am doing is storing them in a file in a temp folder after running the first piece, and reading from there in the follow-up runs, with some error handling around it - missing or bad file, the connection cannot happen, and so on, with fallbacks to new instance creation.