Bug 1577035 - Cache Monitor data to reduce the load on Monitor API. r=johannh a=lizzard
authorErica Wright <ewright@mozilla.com>
Fri, 06 Sep 2019 17:57:58 +0000
changeset 554977 47ced6e49cfccfda6b0c369ddaf3eab0dba13ad3
parent 554976 dff98f24b46ba24955d8f3ec9fbc3e21a21189ac
child 554978 e7f3f12d59e3b95b63bef535fa022ac9646afc9f
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohannh, lizzard
bugs1577035
milestone70.0
Bug 1577035 - Cache Monitor data to reduce the load on Monitor API. r=johannh a=lizzard Differential Revision: https://phabricator.services.mozilla.com/D43865
browser/components/about/AboutProtectionsHandler.jsm
browser/components/protections/content/monitor-card.js
--- a/browser/components/about/AboutProtectionsHandler.jsm
+++ b/browser/components/about/AboutProtectionsHandler.jsm
@@ -54,17 +54,19 @@ const SERVICE_UNAVAILABLE = "Service una
 const UNEXPECTED_RESPONSE = "Unexpected response";
 const UNKNOWN_ERROR = "Unknown error";
 
 // Valid response info for successful Monitor data
 const MONITOR_RESPONSE_PROPS = ["monitoredEmails", "numBreaches", "passwords"];
 
 var AboutProtectionsHandler = {
   _inited: false,
+  monitorResponse: null,
   _topics: [
+    "ClearMonitorCache",
     // Opening about:* pages
     "OpenAboutLogins",
     "OpenContentBlockingPreferences",
     "OpenSyncPreferences",
     // Fetching data
     "FetchContentBlockingEvents",
     "FetchMonitorData",
     "FetchUserLoginsData",
@@ -95,17 +97,25 @@ var AboutProtectionsHandler = {
 
   /**
    * Fetches and validates data from the Monitor endpoint. If successful, then return
    * expected data. Otherwise, throw the appropriate error depending on the status code.
    *
    * @return valid data from endpoint.
    */
   async fetchUserBreachStats(token) {
-    let monitorResponse = null;
+    if (this.monitorResponse && this.monitorResponse.timestamp) {
+      var timeDiff = Date.now() - this.monitorResponse.timestamp;
+      let oneDayInMS = 24 * 60 * 60 * 1000;
+      if (timeDiff >= oneDayInMS) {
+        this.monitorResponse = null;
+      } else {
+        return this.monitorResponse;
+      }
+    }
 
     // Make the request
     const headers = new Headers();
     headers.append("Authorization", `Bearer ${token}`);
     const request = new Request(MONITOR_API_ENDPOINT, { headers });
     const response = await fetch(request);
 
     if (response.ok) {
@@ -117,41 +127,43 @@ var AboutProtectionsHandler = {
       for (let prop in json) {
         isValid = MONITOR_RESPONSE_PROPS.includes(prop);
 
         if (!isValid) {
           break;
         }
       }
 
-      monitorResponse = isValid ? json : new Error(UNEXPECTED_RESPONSE);
+      this.monitorResponse = isValid ? json : new Error(UNEXPECTED_RESPONSE);
+      if (isValid) {
+        this.monitorResponse.timestamp = Date.now();
+      }
     } else {
       // Check the reason for the error
       switch (response.status) {
         case 400:
         case 401:
-          monitorResponse = new Error(INVALID_OAUTH_TOKEN);
+          this.monitorResponse = new Error(INVALID_OAUTH_TOKEN);
           break;
         case 404:
-          monitorResponse = new Error(USER_UNSUBSCRIBED_TO_MONITOR);
+          this.monitorResponse = new Error(USER_UNSUBSCRIBED_TO_MONITOR);
           break;
         case 503:
-          monitorResponse = new Error(SERVICE_UNAVAILABLE);
+          this.monitorResponse = new Error(SERVICE_UNAVAILABLE);
           break;
         default:
-          monitorResponse = new Error(UNKNOWN_ERROR);
+          this.monitorResponse = new Error(UNKNOWN_ERROR);
           break;
       }
     }
 
-    if (monitorResponse instanceof Error) {
-      throw monitorResponse;
+    if (this.monitorResponse instanceof Error) {
+      throw this.monitorResponse;
     }
-
-    return monitorResponse;
+    return this.monitorResponse;
   },
 
   /**
    * Retrieves login data for the user.
    *
    * @return {{ hasFxa: Boolean,
    *            numLogins: Number,
    *            numSyncedDevices: Number }}
@@ -355,11 +367,14 @@ var AboutProtectionsHandler = {
         break;
       case "FetchUserLoginsData":
         this.sendMessage(
           aMessage.target,
           "SendUserLoginsData",
           await this.getLoginData()
         );
         break;
+      case "ClearMonitorCache":
+        this.monitorResponse = null;
+        break;
     }
   },
 };
--- a/browser/components/protections/content/monitor-card.js
+++ b/browser/components/protections/content/monitor-card.js
@@ -29,16 +29,17 @@ export default class MonitorClass {
       // Wait for monitor data and display the card.
       this.getMonitorData(data);
       RPMSendAsyncMessage("FetchMonitorData");
     });
 
     let monitorReportLink = this.doc.getElementById("full-report-link");
     monitorReportLink.addEventListener("click", () => {
       this.doc.sendTelemetryEvent("click", "mtr_report_link");
+      RPMSendAsyncMessage("ClearMonitorCache");
     });
 
     let monitorAboutLink = this.doc.getElementById("monitor-link");
     monitorAboutLink.addEventListener("click", () => {
       this.doc.sendTelemetryEvent("click", "mtr_about_link");
     });
 
     let openLockwise = this.doc.getElementById("lockwise-link");