Add kill switch mechanism

This code implements the kill switch mechanism in the extension. This is
explained in //src/killSwitch/README.md and in the design doc:
https://docs.google.com/document/d/1O5YV6_WcxwrUyz-lwHOSTfZ3oyIFWj2EQee0VuKkhaA/edit.

Bug: twpowertools:64

Change-Id: Ia993c78035bba7038aafd53d156f20954217e86f
diff --git a/src/common/optionsUtils.js b/src/common/optionsUtils.js
index 16294ab..bfcb92c 100644
--- a/src/common/optionsUtils.js
+++ b/src/common/optionsUtils.js
@@ -6,7 +6,7 @@
 // Adds missing options with their default value. If |dryRun| is set to false,
 // they are also saved to the sync storage area.
 export function cleanUpOptions(options, dryRun = false) {
-  console.log('[cleanUpOptions] Previous options', JSON.stringify(options));
+  console.debug('[cleanUpOptions] Previous options', JSON.stringify(options));
 
   if (typeof options !== 'object' || options === null) options = {};
 
@@ -18,7 +18,7 @@
     }
   }
 
-  console.log('[cleanUpOptions] New options', JSON.stringify(options));
+  console.debug('[cleanUpOptions] New options', JSON.stringify(options));
 
   if (!ok && !dryRun) {
     chrome.storage.sync.set(options);
@@ -31,12 +31,29 @@
 // stored in the sync storage area.
 export function getOptions(options) {
   // Once we only target MV3, this can be greatly simplified.
-  return new Promise(
-      (resolve, reject) => {chrome.storage.sync.get(options, items => {
-        if (chrome.runtime.lastError) return reject(chrome.runtime.lastError);
+  return new Promise((resolve, reject) => {
+    if (typeof options === 'string')
+      options = [options, '_forceDisabledFeatures'];
+    else if (typeof options === 'array')
+      options = [...options, '_forceDisabledFeatures'];
+    else if (options !== null)
+      console.error('Unexpected |options| parameter (expected: string, array, or null).');
 
-        resolve(items);
-      })});
+    chrome.storage.sync.get(options, items => {
+      if (chrome.runtime.lastError) return reject(chrome.runtime.lastError);
+
+      // Handle applicable kill switches which force disable features
+      if (items?._forceDisabledFeatures) {
+        for (let feature of items?._forceDisabledFeatures) {
+          items[feature] = false;
+        }
+
+        delete items._forceDisabledFeatures;
+      }
+
+      resolve(items);
+    });
+  });
 }
 
 // Returns a promise which returns whether the |option| option/feature is