Browse Source

Refactor - move webrequest permission logic into the background

simov 7 years ago
parent
commit
58c6f99a6b
8 changed files with 108 additions and 93 deletions
  1. 0 52
      background/headers.js
  2. 3 3
      background/index.js
  3. 3 8
      background/messages.js
  4. 99 0
      background/webrequest.js
  5. 0 27
      content/options.js
  6. 1 1
      manifest.firefox.json
  7. 1 1
      manifest.json
  8. 1 1
      manifest.test.json

+ 0 - 52
background/headers.js

@@ -1,52 +0,0 @@
-
-md.headers = ({storage: {state}, detect}) => {
-
-  var callback = ({method, url, responseHeaders}) => {
-    if (method !== 'GET') {
-      return {responseHeaders}
-    }
-
-    var header = responseHeaders.find(({name}) => /^content-type/i.test(name)) || {}
-    var origin = detect.match(url)
-
-    if (!detect.header(header.value) && !origin) {
-      return {responseHeaders}
-    }
-
-    if (origin.csp) {
-      responseHeaders = responseHeaders
-        .filter(({name}) => !/content-security-policy/i.test(name))
-    }
-
-    // ff: markdown `content-type` is not allowed
-    if (/Firefox/.test(navigator.userAgent) && detect.header(header.value)) {
-      header.value = 'text/plain'
-    }
-
-    if (origin.encoding && header.name) {
-      var [media] = header.value.split(';')
-      header.value = `${media}; charset=${origin.encoding}`
-    }
-
-    return {responseHeaders}
-  }
-
-  var filter = {
-    urls: ['<all_urls>'],
-    types: ['main_frame', 'sub_frame']
-  }
-
-  var options = ['blocking', 'responseHeaders']
-
-  var add = () => {
-    if (!chrome.webRequest.onHeadersReceived.hasListener(callback)) {
-      chrome.webRequest.onHeadersReceived.addListener(callback, filter, options)
-    }
-  }
-
-  var remove = () => {
-    chrome.webRequest.onHeadersReceived.removeListener(callback, filter, options)
-  }
-
-  return {add, remove}
-}

+ 3 - 3
background/index.js

@@ -4,7 +4,7 @@
 
 
   var inject = md.inject({storage})
   var inject = md.inject({storage})
   var detect = md.detect({storage, inject})
   var detect = md.detect({storage, inject})
-  var headers = md.headers({storage, detect})
+  var webrequest = md.webrequest({storage, detect})
   var mathjax = md.mathjax()
   var mathjax = md.mathjax()
 
 
   var compilers = Object.keys(md.compilers)
   var compilers = Object.keys(md.compilers)
@@ -13,12 +13,12 @@
       all
       all
     ), {})
     ), {})
 
 
-  var messages = md.messages({storage, compilers, mathjax, headers})
+  var messages = md.messages({storage, compilers, mathjax, webrequest})
 
 
 
 
   chrome.tabs.onUpdated.addListener(detect.tab)
   chrome.tabs.onUpdated.addListener(detect.tab)
 
 
   chrome.runtime.onMessage.addListener(messages)
   chrome.runtime.onMessage.addListener(messages)
 
 
-  chrome.webRequest && headers.add()
+  setTimeout(webrequest, 0)
 })()
 })()

+ 3 - 8
background/messages.js

@@ -1,5 +1,5 @@
 
 
-md.messages = ({storage: {defaults, state, set}, compilers, mathjax, headers}) => {
+md.messages = ({storage: {defaults, state, set}, compilers, mathjax, webrequest}) => {
 
 
   return (req, sender, sendResponse) => {
   return (req, sender, sendResponse) => {
 
 
@@ -85,13 +85,6 @@ md.messages = ({storage: {defaults, state, set}, compilers, mathjax, headers}) =
       set({header: req.header})
       set({header: req.header})
       sendResponse()
       sendResponse()
     }
     }
-    else if (req.message === 'options.intercept') {
-      // ff: onHeadersReceived is enabled by default
-      if (!/Firefox/.test(navigator.userAgent)) {
-        headers[req.intercept ? 'add' : 'remove']()
-      }
-      sendResponse()
-    }
 
 
     // origins
     // origins
     else if (req.message === 'origin.add') {
     else if (req.message === 'origin.add') {
@@ -106,11 +99,13 @@ md.messages = ({storage: {defaults, state, set}, compilers, mathjax, headers}) =
     else if (req.message === 'origin.remove') {
     else if (req.message === 'origin.remove') {
       delete state.origins[req.origin]
       delete state.origins[req.origin]
       set({origins: state.origins})
       set({origins: state.origins})
+      webrequest()
       sendResponse()
       sendResponse()
     }
     }
     else if (req.message === 'origin.update') {
     else if (req.message === 'origin.update') {
       state.origins[req.origin] = req.options
       state.origins[req.origin] = req.options
       set({origins: state.origins})
       set({origins: state.origins})
+      webrequest()
       sendResponse()
       sendResponse()
     }
     }
   }
   }

+ 99 - 0
background/webrequest.js

@@ -0,0 +1,99 @@
+
+md.webrequest = ({storage: {state}, detect}) => {
+
+  var permissions = ['webRequest', 'webRequestBlocking']
+
+  var filter = {
+    urls: ['<all_urls>'],
+    types: ['main_frame', 'sub_frame']
+  }
+
+  var options = ['blocking', 'responseHeaders']
+
+  var onHeadersReceived = ({method, url, responseHeaders}) => {
+    if (method !== 'GET') {
+      return {responseHeaders}
+    }
+
+    var header = responseHeaders.find(({name}) => /^content-type/i.test(name)) || {}
+    var origin = detect.match(url)
+
+    if (!detect.header(header.value) && !origin) {
+      return {responseHeaders}
+    }
+
+    if (origin.csp) {
+      responseHeaders = responseHeaders
+        .filter(({name}) => !/content-security-policy/i.test(name))
+    }
+
+    // ff: markdown `content-type` is not allowed
+    if (/Firefox/.test(navigator.userAgent) && detect.header(header.value)) {
+      header.value = 'text/plain'
+    }
+
+    if (origin.encoding && header.name) {
+      var [media] = header.value.split(';')
+      header.value = `${media}; charset=${origin.encoding}`
+    }
+
+    return {responseHeaders}
+  }
+
+  var events = () => {
+    var headers = false
+    for (var key in state.origins) {
+      if (state.origins[key].csp || state.origins[key].encoding) {
+        headers = true
+        break
+      }
+    }
+
+    // ff: webRequest is required permission
+    if (/Firefox/.test(navigator.userAgent)) {
+      headers = true
+    }
+
+    return {headers}
+  }
+
+  var perm = (headers, done) => {
+    // ff: webRequest is required permission
+    if (/Firefox/.test(navigator.userAgent)) {
+      done()
+    }
+    // request permissions
+    else if (headers && !chrome.webRequest) {
+      chrome.permissions.request({permissions}, done)
+    }
+    // remove permissions
+    else if (!headers && chrome.webRequest) {
+      chrome.permissions.remove({permissions}, () => {
+        chrome.webRequest = null
+        done()
+      })
+    }
+    else {
+      done()
+    }
+  }
+
+  return () => {
+
+    var {headers} = events()
+
+    // remove listeners
+    if (chrome.webRequest) {
+      if (!headers && !/Firefox/.test(navigator.userAgent)) {
+        chrome.webRequest.onHeadersReceived.removeListener(onHeadersReceived)
+      }
+    }
+
+    perm(headers, () => {
+      // add listeners
+      if (headers && !chrome.webRequest.onHeadersReceived.hasListener(onHeadersReceived)) {
+        chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, filter, options)
+      }
+    })
+  }
+}

+ 0 - 27
content/options.js

@@ -98,7 +98,6 @@ var events = {
       chrome.permissions.remove({origins: [`${origin}/*`]}, (removed) => {
       chrome.permissions.remove({origins: [`${origin}/*`]}, (removed) => {
         if (removed) {
         if (removed) {
           chrome.runtime.sendMessage({message: 'origin.remove', origin})
           chrome.runtime.sendMessage({message: 'origin.remove', origin})
-          webRequest()
           delete state.origins[origin]
           delete state.origins[origin]
           m.redraw()
           m.redraw()
         }
         }
@@ -137,7 +136,6 @@ var events = {
         origin,
         origin,
         options: {match, csp, encoding},
         options: {match, csp, encoding},
       })
       })
-      webRequest()
     },
     },
 
 
     encoding: (origin) => (e) => {
     encoding: (origin) => (e) => {
@@ -148,35 +146,10 @@ var events = {
         origin,
         origin,
         options: {match, csp, encoding},
         options: {match, csp, encoding},
       })
       })
-      webRequest()
     },
     },
   },
   },
 }
 }
 
 
-var webRequest = () => {
-  // ff: webRequest is required permission
-  if (/Firefox/.test(navigator.userAgent)) {
-    return
-  }
-
-  var intercept = false
-  for (var key in state.origins) {
-    if (state.origins[key].csp || state.origins[key].encoding) {
-      intercept = true
-      break
-    }
-  }
-
-  chrome.permissions[intercept ? 'request' : 'remove']({
-    permissions: ['webRequest', 'webRequestBlocking']
-  }, () => {
-    chrome.runtime.sendMessage({
-      message: 'options.intercept',
-      intercept,
-    })
-  })
-}
-
 var oncreate = {
 var oncreate = {
   ripple: (vnode) => {
   ripple: (vnode) => {
     mdc.ripple.MDCRipple.attachTo(vnode.dom)
     mdc.ripple.MDCRipple.attachTo(vnode.dom)

+ 1 - 1
manifest.firefox.json

@@ -30,7 +30,7 @@
       "/background/compilers/remark.js",
       "/background/compilers/remark.js",
 
 
       "/background/storage.js",
       "/background/storage.js",
-      "/background/headers.js",
+      "/background/webrequest.js",
       "/background/detect.js",
       "/background/detect.js",
       "/background/inject.js",
       "/background/inject.js",
       "/background/messages.js",
       "/background/messages.js",

+ 1 - 1
manifest.json

@@ -27,7 +27,7 @@
       "/background/compilers/remark.js",
       "/background/compilers/remark.js",
 
 
       "/background/storage.js",
       "/background/storage.js",
-      "/background/headers.js",
+      "/background/webrequest.js",
       "/background/detect.js",
       "/background/detect.js",
       "/background/inject.js",
       "/background/inject.js",
       "/background/messages.js",
       "/background/messages.js",

+ 1 - 1
manifest.test.json

@@ -27,7 +27,7 @@
       "/background/compilers/remark.js",
       "/background/compilers/remark.js",
 
 
       "/background/storage.js",
       "/background/storage.js",
-      "/background/headers.js",
+      "/background/webrequest.js",
       "/background/detect.js",
       "/background/detect.js",
       "/background/inject.js",
       "/background/inject.js",
       "/background/messages.js",
       "/background/messages.js",