1

I'm trying to retrieve the value of navigator.plugins from a Selenium driven ChromeDriver initiated Browsing Context.

Using I'm able to retrieve navigator.userAgent and navigator.plugins as follows:

navigator_userAgent_plugins

But using Selenium's execute_script() method I'm able to extract the navigator.userAgent but navigator.plugins raises the following circular reference error:

  • Code Block:

    from selenium import webdriver 
    
    options = webdriver.ChromeOptions() 
    options.add_argument("start-maximized")
    driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
    driver.get("https://www.google.com/")
    print("userAgent: "+driver.execute_script("return navigator.userAgent;"))
    print("plugins: "+driver.execute_script("return navigator.plugins;"))
    
  • Console Output:

    userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
    Traceback (most recent call last):
      File "C:\Users\Soma Bhattacharjee\Desktop\Debanjan\PyPrograms\navigator_properties.py", line 19, in <module>
        print("vendor: "+driver.execute_script("return navigator.plugins;"))
      File "C:\Python\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 636, in execute_script
        'args': converted_args})['value']
      File "C:\Python\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
        self.error_handler.check_response(response)
      File "C:\Python\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
        raise exception_class(message, screen, stacktrace)
    selenium.common.exceptions.JavascriptException: Message: javascript error: circular reference
      (Session info: chrome=83.0.4103.116)
    

I've been through the following discussions on circular reference and I understand the concept. But I am not sure how should I address the issue here.

Can someone help me to retrieve the navigator.plugins please?

3 Answers 3

3

There might be a serialization issue when you query a non-primitive data structure from a browser realm. By closely inspecting the hierarchy of a single plugin, we can see it has a recursive structure which is an issue for the serializer. enter image description here

If you need a list of plugins, try returning just a serialized, newline-separated string and then split it by a newline symbol in the Python realm.

For example:

plugins = driver.execute_script("return Array.from(navigator.plugins).map(({name}) => name).join('\n');").split('\n')
Sign up to request clarification or add additional context in comments.

12 Comments

With print("plugins->name: "+driver.execute_script("return Array.from(navigator.plugins).map(({name}) => name);")) I'm seeing TypeError: must be str, not list
Ok, then just return it as newline-separated string. For example: return Array.from(navigator.plugins).map(({name}) => name).join('\n'); Then just split it by \n in your Python code to get a list of stirngs.
With print("plugins->name: "+driver.execute_script("return Array.from(navigator.plugins).map(({name}) => name);")[0]) I get back Chrome PDF Plugin, Chrome PDF Viewer and so on.
That is not what I suggested above. In your case you just return the name of a first available plugin. What I suggested to do is to return a newline-separated string from your call to execute_script and then slit it by "\n" in your Python code to get a list of stirngs. For example: plugins = driver.execute_script("return Array.from(navigator.plugins).map(({name}) => name).join('\n')").split('\n') print('plugins->name: ' + plugins)
@ViacheslavMoskalenko All you need to add is .join() to the end and it will return a comma-delimited string of names, return Array.from(navigator.plugins).map(({name}) => name).join()
|
2

I'm assuming it has something to do with the fact that navigator.plugins returns a PluginArray.

The PluginArray page lists the methods and properties that are available and with that I wrote this code that returns the list of names. You can adapt it to whatever you need.

print("plugins: " + driver.execute_script("var list = [];for(var i = 0; i < navigator.plugins.length; i++) { list.push(navigator.plugins[i].name); }; return list.join();"))

5 Comments

Definitely this answer helps to move one step ahead. Somehow, I need to get the plugin values.
What plugin values are you looking for specfically?
I was looking to extract the values from 1) Chrome PDF Plugin 2) Chrome PDF Viewer 3) Native Client
Which values are you looking for? Have you looked at the PluginArray page I linked in my answer? It links to the Plugin page which has the different properties you can access: description, filename, and version. Is that what you're looking for or ?
So what's the overall goal here? You should probably update your question with that. Are you trying to locate a specific plugin, make sure a specific plugin is not installed, etc.? Once we have that, we can better create an answer.
1

Circular Reference

A circular reference occurs if two separate objects pass references to each other. Circular referencing implies that the 2 objects referencing each other are tightly coupled and changes to one object may need changes in other as well.


NavigatorPlugins.plugins

NavigatorPlugins.plugins returns a PluginArray object, listing the Plugin objects describing the plugins installed in the application. plugins is PluginArray object used to access Plugin objects either by name or as a list of items. The returned value has the length property and supports accessing individual items using bracket notation (e.g. plugins[2]), as well as via item(index) and namedItem("name") methods.


To extract the navigator.plugins properties you can use the following solutions:

  • To get the list of names of the plugins:

    print(driver.execute_script("return Array.from(navigator.plugins).map(({name}) => name);"))
    
    • Console Output:

      ['Chrome PDF Plugin', 'Chrome PDF Viewer', 'Native Client']
      
  • To get the list of filename of the plugins:

    print(driver.execute_script("return Array.from(navigator.plugins).map(({filename}) => filename);"))
    
    • Console Output:

      ['internal-pdf-viewer', 'mhjfbmdgcfjbbpaeojofohoefgiehjai', 'internal-nacl-plugin']
      
  • To get the list of description of the plugins:

    print(driver.execute_script("return Array.from(navigator.plugins).map(({description}) => description);"))
    
    • Console Output:

      ['Portable Document Format', '', '']
      

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.