Chris Parks

I'm a technical problem-solver who specializes in planning, organizing, and facilitating technical projects between systems. I have led successful integrations projects between platforms such as Shopify, Amazon, NetSuite, and more, on top of providing technical consultation and guidance for clients looking to build custom integrations via API.

Chrome Function Monitor Extension Architecture Deep Dive

In a previous post, I introduced an extension I created for the Chrome Web Browser called the Function Monitor. The extension allows you to monitor a webpage for calls of a specified function, and records and lists those function calls in a tab in the inspector. I have recorded a video demo of how the extension works when installed, which you can see in the original post linked below, but I also want to show how the code in the app works internally.

At a high level, there are three main domains that the extension is broken down into: the React UI app (found in the /src folder), the Extension app (found in the /chrome-pages folder, and the DOM of the page that is currently being inspected.

LucidChart Diagram

Here’s an illustration of the architecture of the app that I created using LucidChart:


Extension Code Elements Breakdown

Here’s a breakdown of the main elements of the code structure, which you can view in full on GitHub: https://github.com/richparks92/react-function-monitor-chrome/

/public/chrome-pages Extension Logic

background.js
  • Serves as the central messaging hub of the extension
  • Receives messages from the DOM and either handles the logic or forwards the message to the Client
  • Receives messages from the App UI and Client
  • Notifies the Client when the page is about to navigate and when page navigation has been completed
  • Injects scripts into DOM when requested by App UI or Client
devtools.js
  • This small file simply adds the extension UI as a new panel in the inspector

[/js/content-scripts]

addDomListeners.js
  • This script is injected into the DOM in an isolated context
  • It adds event listeners to the DOM that are able to receive messages that are sent from other scripts that are injected into the DOM
  • Received messages are forwarded to background.js
  • The two messages that this script listens for are:
    • FUNCTION_CALL_EVENT: the wrapped function in the window context has been called (includes details of the function invocation)
    • FN_ARRAY_READY_EVENT: the list of available window functions has been created by getFunctionList.js
getFunctionList.js
  • Injects a script into the window context to read the names and paths of the available functions in the window
  • Once the functions list has been compiled, it is communicated by sending a FN_ARRAY_READY_EVENT message from the window’s injected script that is received by the addDomListeners.js script.
    • That message is then forwarded to the Client via the FN_ARRAY_RESULT message

/src React App

Most of the functional logic is contained in this folder.

App.js
  • Entry point for app
  • Creates DevToolsDebugClient Client
  • Loads themes and icons
  • Requests two scripts to be injected
    • addDomListeners
    • getFunctionList
  • Creates the AppContainer

[src/scripts]

devToolsDebugClient
  • Stores main information on app data state
  • Javascript class that handles the logic of wrapping and unwrapping the selected function
    • Functions are wrapped by copying the function to a string, and creating a new function that intercepts invocation details and triggers original function
  • Initiates message to background.js to request to background to inject addDomListeners and getFunctionList scripts into the inspected page’s DOM
  • Receives and handles messages from background.js
  • Receives and handles messages from the inspected page’s DOM
  • Imports helper functions from util/helpers.js and debuggerMethods.js, and requestScriptInjection.js

[src/components]

appContainer
  • Creates app UI state
    • button state
    • function state
    • function suggestion list state
    • function call (invocation) history
  • Sets up child UI components
functionForm
  • Represents the form within the pane where the user enters the path of the function they want to wrap, and the button that triggers the wrapping and unwrapping by the Client
    • The input box is loaded with autocomplete suggestions when the extension loads and on page refreshed
functionInfoPanel
  • Displays the status of the function wrapper, including the selected function (if any) and whether it has been wrapped
invocationsList
  • Displays the history and details of each recorded invocation of the currently wrapped function

[src/util]

helpers.js
  • Contains helpful utility functions
    • Extracts arguments from function invocation string
    • Converts arguments into a tree node object for UI display

Here’s the link to the original post and demo video.