diff --git a/proposals/extension_get_contexts.md b/proposals/extension_get_contexts.md
new file mode 100644
index 00000000..a4a331cc
--- /dev/null
+++ b/proposals/extension_get_contexts.md
@@ -0,0 +1,189 @@
+# New API: extension.getContexts()
+
+## Background / Summary
+
+Chromium currently has the
+[`extension.getViews()`](https://developer.chrome.com/docs/extensions/reference/extension/#method-getViews)
+API method which allows an extension to get information about the views the
+extension is running in. Common reasons for calling this method are: determining
+if a toolbar popup is open, reading and/or modifying a settings page, and etc.
+Chromium's implementation of Manifest V2 (MV2) allows for
+[background scripts (pages)](https://developer.chrome.com/docs/extensions/mv2/background_pages/)
+to call this API. This is possible because these scripts run on our main thread
+which allows them easy access to the JavaScript
+[`Window`](http://go/mdn/API/Window#instance_properties) objects provided by
+`extension.getViews()`.
+
+## Problem
+
+However, with Chromium’s migration to Manifest V3 (MV3), background pages
+[no longer exist](https://developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/);
+instead, an extension’s background context is
+[service worker](https://developer.chrome.com/docs/workbox/service-worker-overview/)-based.
+For technical reasons[1](#footnotes), service workers cannot access
+the [`Window`](http://go/mdn/API/Window#instance_properties) objects that
+`extension.getViews()` provides and it is not feasible to implement that with
+our browser design. Due to this we cannot provide access to the JavaScript
+context for these views, but we can allow an extension to query for them and
+potentially target them for messaging purposes.
+
+## Solution
+
+Considering the above situation, we’d like to propose a new `extension` API
+method to asynchronously provide metadata about the view that is still useful
+for an extension: `extension.getContexts()`. This will allow extension background scripts to identify the active contexts in the extension.
+For example, this can be used to target messages to send using
+[`runtime.sendMessage()`](https://developer.chrome.com/docs/extensions/reference/runtime/#method-sendMessage),
+etc.). Introducing this API will allow an easier migration from MV2.
+
+## API Proposal
+
+This new API would use a similar parameter signature as
+`extension.getViews()`but instead accept a new `contextProperties` object.
+
+```
+extension.getContexts()(
+ contextProperties?: object,
+)
+```
+
+`contextProperties` will have similar behavior to `extension.getViews()`’s
+[`fetchProperties`](https://developer.chrome.com/docs/extensions/reference/extension/#method-getViews)
+object in that it will limit the scope of the query to certain tabs, context
+types, and windows. It would be defined as:
+
+```
+extension.ContextProperties = {
+ tabId? = int, // Find context by tab id, omitted returns all tabs.
+ contextType? = ContextType, // Find context by type, omitted returns all types.
+ windowId? = int, // Find context by window id, omitted returns all
+ // windows.
+}
+```
+
+`ContextType` would serve a similar purpose of
+[`fetchProperties`](https://developer.chrome.com/docs/extensions/reference/extension/#method-getViews)’s
+[`ViewType`](https://developer.chrome.com/docs/extensions/reference/extension/#type-ViewType)
+in order to limit the type of extension contexts returned by the API. It would
+be defined as:
+
+```
+extension.ContextType = {
+ TAB: 'TAB', // Tabs the extension is running in.
+ POPUP: 'POPUP', // Popups created by the extension.
+ BACKGROUND: 'BACKGROUND', // Background script for the extension.
+ // (background pages for MV2, or service
+ // workers for MV2 + MV3).
+ OFFSCREEN_DOCUMENT: 'OFFSCREEN_DOCUMENT' // Offscreen documents for the extension.
+};
+```
+
+It would return an array of new `Context` objects for each frame the extension
+is running in:
+
+```
+extension.Context = {
+ tabId: int, // ID of the tab for this view.
+ windowId: int, // ID of the window this tab is located in.
+ documentId: int, // ID of the DOM document loaded in the tab.
+ frameId: int, // ID of the frame this context is running for.
+ contextType: ContextType, // Context type -- tab, popup, etc.
+ frameUrl: string, // The current URL of the frame. For background
+ // pages and service workers this value is empty.
+ origin: string, // The origin of the context. Mostly this is the
+ // extension origin.
+ incognito: boolean // Whether the context is for an incognito
+ // profile.
+}
+```
+
+`Context` objects will contain an `incognito` value indicating if the Context is
+running in an incognito profile. In this area, this brings up the case of an
+extension specifying
+[split incognito mode](https://developer.chrome.com/docs/extensions/mv3/manifest/incognito/#split).
+In this case we would not return the `Context`s from the related (but different)
+extension process running for the incognito profile. `spanning`mode would return
+any `Context`s running in an incognito profile (with `Context.incognito` being
+`true`) in the same shared process. More comments about this are in the Future
+Work](#future-work) section on this proposal.
+
+## Future Work
+
+### Multi Page Architecture Fields (`DocumentLifeCycle`, `FrameType`, and `parentDocumentId`, and `parentFrameId`)
+
+[Multi Page Architecture](https://docs.google.com//1NginQ8k0w3znuwTiJ5qjYmBKgZDekvEPC22q0I4swxQ#heading=h.w1qo2n6sr8wn)
+caused
+[multiple changes](https://developer.chrome.com/blog/extension-instantnav/) to
+Chromium's
+[tabs API](https://developer.chrome.com/docs/extensions/reference/tabs/),
+[scripting API](https://developer.chrome.com/docs/extensions/reference/scripting/),
+and
+[web navigation API](https://developer.chrome.com/docs/extensions/reference/webNavigation/).
+For the web navigation API it changed how outermost frames are exposed to
+extensions in Chromium. Considering this new architecture it is likely that
+extensions will want to know what navigation state (`DocumentLifeCycle`) a
+`Context` is in, whether the frame’s `FrameType` is an outermost frame, and
+other fields like `parentDocumentId`, and `parentFrameId`. These are fields we
+would like to include in a future iteration of this API.
+
+### Asynchronous and Synchronous Version
+
+A potential avenue is that, since this new API is asynchronous whereas
+`getViews()` is synchronous, we could explore a synchronous version of this new
+API if there’s significant demand for it. That demand would need to justify why
+the usage of `await` on the existing asynchronous API isn't sufficient. As
+mentioned previously[1](#footnotes), there are technical limitations
+that make it infeasible to synchronously fetch all `Context`s. We could provide
+two methods, one synchronous, and one asynchronous API methods:
+
+* `getContexts()`: as defined above and asynchronous. It fetches all
+ `Context`s available in the process running for the profile.
+* `getContextsSynchronous()` (name TBD): defined similarly to `getContexts()`,
+ but is synchronous. It returns the data for other `Context`s that are
+ available synchronously (running in the same process and on the same
+ thread). If called from a background script, it would likely only return the
+ background script `Context`.
+
+### Content Script Contexts
+
+[Content scripts](https://developer.chrome.com/docs/extensions/mv3/content_scripts/)
+run in a separate
+[Renderer](https://developer.chrome.com/blog/inside-browser-part3/) (and
+process) from the extension process. This proposal would not return those
+`Context`s since this adds significant complexity to the design in querying all
+Renderer processes in the browser to find content scripts. However, extensions
+could find it useful to have this `Context` metadata for places where the
+extension is executing JavaScript in a web page. It could be justified in the
+future if extension developers would have a significant need. If implemented the
+`frameUrl` field would be empty as providing a URL to the content script (within
+the extension) doesn't have a use case.
+
+### Messaging APIs Support `Context`s as Targets
+
+This new API now provides the ability to consider specifying targets via
+`Context`s to messaging APIs like `runtime.sendMessage()` or
+`tabs.sendMessage()`. With this support it would avoid
+[various workarounds](https://github.com/w3c/webextensions/pull/334#issuecomment-1343255899)
+needed to target specific pages with messages. `tabs.sendMessage()` accepting
+`Context`s would require work in retrieving content script `Context`s explained
+[above](#content-script-contexts).
+
+## Open Questions
+
+### Include `sandbox` Pages and Iframes as `Context`s?
+
+`sandbox` documents and iframes have an
+[opaque origin](https://html.spec.whatwg.org/multipage/browsers.html#concept-origin-opaque),
+should we return them? What if they come from within the extension (or outside
+in a Content Script)?
+
+## Footnotes
+
+1: Non-main threads in a
+[Renderer](https://developer.chrome.com/blog/inside-browser-part3/) (where
+service workers run in Chromium) cannot access DOM concepts directly (they are
+only accessible from the main browser thread). Service workers run in these
+threads therefore they do not have access to the JavaScript
+[`Window`](http://go/mdn/API/Window#instance_properties) objects provided by
+`extension.getViews()`. Supporting this access is likely years of software
+engineer work to implement.