threadListAvatars: dynamic unauthorized forums

This is an implementation of point 3 in the "Idea" section of the
following doc: go/eu7T9m (public link available in the linked bug).

Paraphrasing the previous document:
This change adds code to maintain a list of forums from which the
extension couldn't load any thread, which probably correspond to private
forums. When a forum is in this list, avatars are no longer retrieved
from threads in that forum until the entry expires.

Bug: 2
Change-Id: I05e7b02818181f410855948e1af6ec75fc7c792b
diff --git a/src/common/api.js b/src/common/api.js
index 065d84c..b2075c3 100644
--- a/src/common/api.js
+++ b/src/common/api.js
@@ -2,7 +2,9 @@
 
 // Function to wrap calls to the Community Console API with intelligent error
 // handling.
-export function CCApi(method, data, authenticated, authuser = 0) {
+export function CCApi(
+    method, data, authenticated, authuser = 0,
+    returnUnauthorizedStatus = false) {
   var authuserPart =
       authuser == '0' ? '' : '?authuser=' + encodeURIComponent(authuser);
 
@@ -29,12 +31,24 @@
       })
       .then(res => {
         if (res.status == 400) {
+          // If the canonicalCode is PERMISSION_DENIED:
+          if (returnUnauthorizedStatus && res.body?.[2] == 7)
+            return {
+              unauthorized: true,
+            };
+
           throw new Error(
               res.body[4] ||
               ('Response status 400 for method ' + method + '. ' +
                'Error code: ' + (res.body[2] ?? 'unknown')));
         }
 
+        if (returnUnauthorizedStatus)
+          return {
+            unauthorized: false,
+            body: res.body,
+          };
+
         return res.body;
       });
 }