diff --git a/specification/index.bs b/specification/index.bs
index 4ab0a0a0..7fcb8941 100644
--- a/specification/index.bs
+++ b/specification/index.bs
@@ -7,6 +7,7 @@ Group: WECG
URL: https://w3c.github.io/webextensions/specification/index.html
Editor: Mukul Purohit, Microsoft Corporation https://www.microsoft.com, mpurohit@microsoft.com
Editor: Tomislav Jovanovic, Mozilla https://www.mozilla.org/, tjovanovic@mozilla.com
+Editor: Oliver Dunk, Google https://www.google.com, oliverdunk@chromium.org
Abstract: [Placeholder] Abstract.
Markup Shorthands: markdown yes
@@ -27,11 +28,11 @@ An optional directory containing strings as defined in l
## Other files
-An extension may also contain other files, such as those referenced in the content_scripts and background part of the Manifest.
+An extension may also contain other files, such as those referenced in the [[#key-content_scripts]] and [[#key-background]] parts of the [=manifest=].
# Manifest
-A WebExtension must have a manifest file at its root directory.
+A WebExtension must have a manifest file at its root directory.
## Manifest file
@@ -112,7 +113,7 @@ This key may be present.
### Key `content_scripts`
-This key may be present.
+The `content_scripts` key is a [=list=] of items representing [=content scripts=] that should be registered.
### Key `content_security_policy`
@@ -154,6 +155,8 @@ Filenames beginning with an underscore (`_`) are reserved for use by user agent.
# Isolated worlds
+Worlds are isolated JavaScript contexts with access to the same underlying DOM tree but their own set of wrappers around those DOM objects.
+
# Unavailable APIs
# The `browser` global
@@ -172,6 +175,12 @@ Issue(62): Specify localization handling.
# Match patterns
+A match pattern is a pattern used to match URLs. They are case-insensitive.
+
+# Globs
+
+A glob can be any [=string=]. It can contain any number of wildcards where * can match zero or more characters and ? matches exactly one character.
+
# Concepts
## Uniqueness of extension IDs
@@ -190,7 +199,57 @@ Issue(62): Specify localization handling.
## Content scripts
-### Isolated worlds
+Content scripts represent a set of JS and CSS files that should be injected into matching pages loaded by the user agent. They are injected using the steps in [[#inject-a-content-script]].
+
+### Key `matches`
+
+A [=list=] of [=match patterns=] that are used to decide which pages the user agent injects the content script into. This key is required.
+
+### Key `exclude_matches`
+
+A [=list=] of [=match patterns=] that should be used to exclude URLs from where the content script runs.
+
+### Key `js`
+
+A [=list=] of file paths, relative to the extension's package, that should be injected as scripts.
+
+### Key `css`
+
+A [=list=] of file paths, relative to the extension's package, that should be injected as stylesheets.
+
+### Key `all_frames`
+
+If `all_frames` is true, the content script must be injected into any subframes that match the other matching criteria for the content script. If false, content scripts will only be injected into top-level documents. Defaults to false.
+
+### Key `match_about_blank`
+
+If this is true, use the URL of the parent frame when matching a child frame whose document URL has the `about` [=scheme=]. See also [[#determine-the-url-for-content-script-matching]]. Defaults to `false`.
+
+Note: In Firefox, setting `match_about_blank` to `true` also allows injection into top-level `about:blank` pages.
+
+### Key `match_origin_as_fallback`
+
+If this is true, use fallbacks as described in [[#determine-the-url-for-content-script-matching]].
+
+No path is available when the URL to match against falls back to an origin. Therefore, when set, the user agent may treat a [[#key-matches]] with a path other than `/*` as an error.
+
+Defaults to `false`.
+
+### Key `run_at`
+
+Specifies when the content script should be injected. Valid values are `document_start`, `document_end` and `document_idle`.
+
+### Key `include_globs`
+
+A list of [=globs=] that a page should match. A page matches if the URL matches both the [[#key-matches]] field and the [[#key-include_globs]] field.
+
+### Key `exclude_globs`
+
+A list of [=globs=] that should be used to exclude URLs from where the content script runs.
+
+### Key `world`
+
+The [=world=] any JavaScript scripts should be injected into. Defaults to `ISOLATED`. Valid values are `MAIN` and `ISOLATED`.
## Extension pages
@@ -203,3 +262,33 @@ Issue(62): Specify localization handling.
## Current behavior of cookie partitioning
# Version number handling
+
+# Algorithms
+
+## Determine the URL for content script matching
+
+To determine the URL to use for a document when injecting a content script:
+
+1. Let |url| be the document's URL.
+1. If the document is within a child frame:
+ 1. If the [=scheme=] of the document's URL is `about`, and `match_about_blank` or `match_origin_as_fallback` is set to true:
+ 1. Set |url| to a URL based on the origin of the parent frame.
+ 1. If the [=scheme=] of the document's URL is `data` and `match_origin_as_fallback` is set to true:
+ 1. Set |url| to be a URL based on the origin of the parent frame.
+ 1. If the [=scheme=] of the document's URL is `filesystem` or `blob` and `match_origin_as_fallback` is set to true:
+ 1. Set |url| to be a URL based on the origin of the frame which created the URL.
+1. Return |url|.
+
+## Inject a content script
+
+Issue: If the same extension specifies the same script twice, what should happen? ([bug](https://crbug.com/324096753))
+
+To determine if a content script should be injected in a document:
+
+1. Let |url| be the result of running [[#determine-the-url-for-content-script-matching]].
+1. If the extension does not have access to the origin, return.
+1. If |url| is not matched by a match pattern in `matches`, return.
+1. If `include_globs` is present and |url| is not matched by any pattern, return.
+1. If |url| matches an entry in `exclude_matches` or `exclude_globs`, return.
+1. If this is a child frame, and `all_frames` is not `true`, return.
+1. Otherwise, inject the content script. This should be done based on the `run_at` setting.