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 theClient
- 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 orClient
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 theDOM
- 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
- That message is then forwarded to the
/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 injectaddDomListeners
andgetFunctionList
scripts into the inspected page’sDOM
- Receives and handles messages from
background
.js
- Receives and handles messages from the inspected page’s
DOM
- Imports helper functions from
util/helpers.js
anddebuggerMethods.js
, andrequestScriptInjection.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.