WebUI: Disallow console.log() statements with ESlint's no-console check.

console.log() statements are in the vast majority of cases spam that is
forgotten to be removed after done with debugging. ESLint can
automatically detect such statements at PRESUBMIT time and save code
review time.

Turning on the no-console ESLint check by default in the top-level
.eslintrc.js configuration.

Existing violations have been dealt as follows:

 - Removed console.log() when it was obvious it was just forgotten.
 - Changed to console.info() or console.warn()  when it was obvious it
   was intentional.
 - Turned off checks with eslint-disable or eslint-disable-next-line
   comments in a few files.
 - Turned off checks using .eslintrc.js in a few folders
   (ui/file_manager/, ash/webui/, c/b/r/chromeos/accessibility/) that
   have lot of violations. The OWNERS of such folders should decide
   separately if they prefer to enable this check and address existing
   violations.

Bug: 720034
Change-Id: Ief1aceaf17aa0cc3f29c9adf9b0a7554405814fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3549216
Reviewed-by: Rebekah Potter <[email protected]>
Reviewed-by: Luciano Pacheco <[email protected]>
Reviewed-by: Kyle Horimoto <[email protected]>
Commit-Queue: Demetrios Papadopoulos <[email protected]>
Cr-Commit-Position: refs/heads/main@{#985873}
diff --git a/.eslintrc.js b/.eslintrc.js
index f2f6fbd..fbde0a1 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -16,6 +16,7 @@
     // Enabled checks.
     'brace-style': ['error', '1tbs'],
     'curly': ['error', 'multi-line', 'consistent'],
+    'no-console': ['error', {allow: ['info', 'warn', 'error', 'assert']}],
     'no-extra-boolean-cast': 'error',
     'no-extra-semi': 'error',
     'no-new-wrappers': 'error',
diff --git a/ash/webui/.eslintrc.js b/ash/webui/.eslintrc.js
new file mode 100644
index 0000000..7b1f71f
--- /dev/null
+++ b/ash/webui/.eslintrc.js
@@ -0,0 +1,9 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+  'rules': {
+    'no-console': 'off',
+  },
+};
diff --git a/chrome/browser/resources/accessibility/accessibility.js b/chrome/browser/resources/accessibility/accessibility.js
index 2c1bcf92..bbc7736 100644
--- a/chrome/browser/resources/accessibility/accessibility.js
+++ b/chrome/browser/resources/accessibility/accessibility.js
@@ -86,7 +86,6 @@
   xhr.open('GET', 'targets-data.json', false);
   xhr.send(null);
   if (xhr.status === 200) {
-    console.log(xhr.responseText);
     return JSON.parse(xhr.responseText);
   }
   return [];
@@ -177,7 +176,6 @@
 }
 
 function initialize() {
-  console.log('initialize');
   const data = requestData();
 
   bindCheckbox('native', data['native']);
diff --git a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
index 4a8dcde..8945d332 100644
--- a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
+++ b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
@@ -7,7 +7,8 @@
     'brace-style': ['error', '1tbs'],
     'curly': ['error', 'multi-line', 'consistent'],
     'eqeqeq': ['error', 'always', {'null': 'ignore'}],
-    'prefer-const': ['error', {'destructuring': 'all'}],
+    'no-console': 'off',
     'object-shorthand': ['error', 'always'],
+    'prefer-const': ['error', {'destructuring': 'all'}],
   },
 };
diff --git a/chrome/browser/resources/chromeos/login/display_manager.js b/chrome/browser/resources/chromeos/login/display_manager.js
index 2fb0d4e..f3887a6 100644
--- a/chrome/browser/resources/chromeos/login/display_manager.js
+++ b/chrome/browser/resources/chromeos/login/display_manager.js
@@ -387,7 +387,7 @@
       // condition. This if statement was introduced to fix http://b/113786350.
       if (this.currentScreen.id == SCREEN_APP_LAUNCH_SPLASH &&
           screen.id == SCREEN_GAIA_SIGNIN) {
-        console.log(
+        console.info(
             this.currentScreen.id +
             ' screen showing. Ignoring switch to Gaia screen.');
         return;
diff --git a/chrome/browser/resources/chromeos/login/oobe_polymer3.js b/chrome/browser/resources/chromeos/login/oobe_polymer3.js
index 4058a92..f4a67327 100644
--- a/chrome/browser/resources/chromeos/login/oobe_polymer3.js
+++ b/chrome/browser/resources/chromeos/login/oobe_polymer3.js
@@ -73,20 +73,19 @@
 // Create the global values attached to `window` that are used
 // for accessing OOBE controls from the browser side.
 function prepareGlobalValues(globalValue) {
-    console.log('Preparing global values.');
-    if (globalValue.cr == undefined) {
-        globalValue.cr = {};
-    }
-    if (globalValue.cr.ui == undefined) {
-      globalValue.cr.ui = {};
-    }
-    if (globalValue.cr.ui.login == undefined) {
-      globalValue.cr.ui.login = {};
-    }
+  if (globalValue.cr == undefined) {
+    globalValue.cr = {};
+  }
+  if (globalValue.cr.ui == undefined) {
+    globalValue.cr.ui = {};
+  }
+  if (globalValue.cr.ui.login == undefined) {
+    globalValue.cr.ui.login = {};
+  }
 
-    // Expose some values in the global object that are needed by OOBE.
-    globalValue.cr.ui.Oobe = Oobe;
-    globalValue.Oobe = Oobe;
+  // Expose some values in the global object that are needed by OOBE.
+  globalValue.cr.ui.Oobe = Oobe;
+  globalValue.Oobe = Oobe;
 }
 
 (function (root) {
diff --git a/chrome/browser/resources/connectors_internals/zero_trust_connector.ts b/chrome/browser/resources/connectors_internals/zero_trust_connector.ts
index 150ae2a..ea829bc 100644
--- a/chrome/browser/resources/connectors_internals/zero_trust_connector.ts
+++ b/chrome/browser/resources/connectors_internals/zero_trust_connector.ts
@@ -120,7 +120,7 @@
     return this.pageHandler.getZeroTrustState().then(
         (response: {state: ZeroTrustState}) => response && response.state,
         (e: object) => {
-          console.log(`fetchZeroTrustValues failed: ${JSON.stringify(e)}`);
+          console.warn(`fetchZeroTrustValues failed: ${JSON.stringify(e)}`);
           return undefined;
         });
   }
diff --git a/chrome/browser/resources/cryptotoken/appid.js b/chrome/browser/resources/cryptotoken/appid.js
index e94ee994..55640335 100644
--- a/chrome/browser/resources/cryptotoken/appid.js
+++ b/chrome/browser/resources/cryptotoken/appid.js
@@ -203,7 +203,7 @@
   }
 
   if (appId.indexOf('http://') === 0 && !this.allowHttp_) {
-    console.log(UTIL_fmt('http app ids disallowed, ' + appId + ' requested'));
+    console.info(UTIL_fmt('http app ids disallowed, ' + appId + ' requested'));
     return Promise.resolve([]);
   }
 
@@ -216,7 +216,7 @@
   var self = this;
   return p.then(getOriginsFromJson, function(rc_) {
     var rc = /** @type {number} */ (rc_);
-    console.log(UTIL_fmt('fetching ' + appId + ' failed: ' + rc));
+    console.info(UTIL_fmt('fetching ' + appId + ' failed: ' + rc));
     if (!(rc >= 400 && rc < 500) && !self.timer_.expired()) {
       // Retry
       return self.fetchAllowedOriginsForAppId_(appId);
diff --git a/chrome/browser/resources/cryptotoken/enroller.js b/chrome/browser/resources/cryptotoken/enroller.js
index a82f7c0e..e48f655 100644
--- a/chrome/browser/resources/cryptotoken/enroller.js
+++ b/chrome/browser/resources/cryptotoken/enroller.js
@@ -856,7 +856,7 @@
       return;
     }
 
-    console.log('Proxying registration request to WebAuthn');
+    console.info('Proxying registration request to WebAuthn');
     this.doRegisterWebAuthn_(enrollAppIds[0], v2Challenge, request);
   });
 };
@@ -1279,7 +1279,7 @@
 Enroller.prototype.helperComplete_ = function(reply) {
   if (reply.code) {
     var reportedError = mapDeviceStatusCodeToU2fError(reply.code);
-    console.log(UTIL_fmt(
+    console.info(UTIL_fmt(
         'helper reported ' + reply.code.toString(16) + ', returning ' +
         reportedError.errorCode));
     // Log non-expected reply codes if we have url to send them.
@@ -1291,7 +1291,7 @@
     }
     this.notifyError_(reportedError);
   } else {
-    console.log(UTIL_fmt('Gnubby enrollment succeeded!!!!!'));
+    console.info(UTIL_fmt('Gnubby enrollment succeeded!!!!!'));
     var browserData;
 
     if (reply.version === 'U2F_V2') {
diff --git a/chrome/browser/resources/cryptotoken/requestqueue.js b/chrome/browser/resources/cryptotoken/requestqueue.js
index 4b2f8817..6ff08bf8 100644
--- a/chrome/browser/resources/cryptotoken/requestqueue.js
+++ b/chrome/browser/resources/cryptotoken/requestqueue.js
@@ -99,7 +99,7 @@
  * @private
  */
 RequestQueue.prototype.insertToken_ = function(token) {
-  console.log(UTIL_fmt('token ' + this.id_ + ' inserted'));
+  console.info(UTIL_fmt('token ' + this.id_ + ' inserted'));
   if (this.head_ === null) {
     this.head_ = token;
     this.tail_ = token;
@@ -170,13 +170,13 @@
 RequestQueue.prototype.complete = function(token) {
   var next = this.removeToken_(token);
   if (next) {
-    console.log(
+    console.info(
         UTIL_fmt('token ' + token.id() + ' completed, starting ' + next.id()));
     next.begin();
   } else if (this.empty()) {
-    console.log(UTIL_fmt('token ' + token.id() + ' completed, queue empty'));
+    console.info(UTIL_fmt('token ' + token.id() + ' completed, queue empty'));
   } else {
-    console.log(UTIL_fmt(
+    console.info(UTIL_fmt(
         'token ' + token.id() + ' completed (earlier token still running)'));
   }
 };
diff --git a/chrome/browser/resources/cryptotoken/signer.js b/chrome/browser/resources/cryptotoken/signer.js
index e70571e..948f1d7 100644
--- a/chrome/browser/resources/cryptotoken/signer.js
+++ b/chrome/browser/resources/cryptotoken/signer.js
@@ -227,9 +227,9 @@
   }
   if (this.token_) {
     if (hadBegunSigning) {
-      console.log(UTIL_fmt('closing in-progress request'));
+      console.info(UTIL_fmt('closing in-progress request'));
     } else {
-      console.log(UTIL_fmt('closing timed-out request before processing'));
+      console.info(UTIL_fmt('closing timed-out request before processing'));
     }
     this.token_.complete();
   }
@@ -250,7 +250,7 @@
  */
 QueuedSignRequest.prototype.begin = function(token) {
   if (this.timer_.expired()) {
-    console.log(UTIL_fmt('Queued request begun after timeout'));
+    console.info(UTIL_fmt('Queued request begun after timeout'));
     this.close();
     this.errorCb_({errorCode: ErrorCodes.TIMEOUT});
     return;
@@ -460,7 +460,7 @@
 
   var timeoutSeconds = this.timer_.millisecondsUntilExpired() / 1000.0;
 
-  console.log('Proxying sign request to WebAuthn');
+  console.info('Proxying sign request to WebAuthn');
   return this.doSignWebAuthn_(encodedChallenges, challengeVal);
 };
 
@@ -717,7 +717,7 @@
 
   if (reply.code) {
     var reportedError = mapDeviceStatusCodeToU2fError(reply.code);
-    console.log(UTIL_fmt(
+    console.info(UTIL_fmt(
         'helper reported ' + reply.code.toString(16) + ', returning ' +
         reportedError.errorCode));
     // Log non-expected reply codes if we have an url to send them
diff --git a/chrome/browser/resources/feed/feed.ts b/chrome/browser/resources/feed/feed.ts
index 97422075..9b1f308d 100644
--- a/chrome/browser/resources/feed/feed.ts
+++ b/chrome/browser/resources/feed/feed.ts
@@ -2,4 +2,4 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-console.log('Success!');
+console.info('Success!');
diff --git a/chrome/browser/resources/feedback/js/event_handler.js b/chrome/browser/resources/feedback/js/event_handler.js
index 987c83b..c3d83ea1 100644
--- a/chrome/browser/resources/feedback/js/event_handler.js
+++ b/chrome/browser/resources/feedback/js/event_handler.js
@@ -182,7 +182,7 @@
     chrome.feedbackPrivate.sendFeedback(
         this.feedbackInfo_, function(result, landingPageType) {
           if (result === chrome.feedbackPrivate.Status.SUCCESS) {
-            console.log('Feedback: Report sent for request with ID ' + ID);
+            console.info('Feedback: Report sent for request with ID ' + ID);
             if (FLOW !== chrome.feedbackPrivate.FeedbackFlow.LOGIN &&
                 landingPageType !==
                     chrome.feedbackPrivate.LandingPageType.NO_LANDING_PAGE) {
@@ -193,7 +193,7 @@
               window.open(landingPage, '_blank');
             }
           } else {
-            console.log(
+            console.info(
                 'Feedback: Report for request with ID ' + ID +
                 ' will be sent later.');
           }
diff --git a/chrome/browser/resources/feedback/js/feedback.js b/chrome/browser/resources/feedback/js/feedback.js
index f1d8f57b..1c8c7f0 100644
--- a/chrome/browser/resources/feedback/js/feedback.js
+++ b/chrome/browser/resources/feedback/js/feedback.js
@@ -322,7 +322,7 @@
 
   // Prevent double clicking from sending additional reports.
   $('send-report-button').disabled = true;
-  console.log('Feedback: Sending report');
+  console.info('Feedback: Sending report');
   if (!feedbackInfo.attachedFile && attachedFileBlob) {
     feedbackInfo.attachedFile = {
       name: $('attach-file').value,
diff --git a/chrome/browser/resources/nearby_share/nearby_discovery_page.js b/chrome/browser/resources/nearby_share/nearby_discovery_page.js
index a2675ad..a6110373 100644
--- a/chrome/browser/resources/nearby_share/nearby_discovery_page.js
+++ b/chrome/browser/resources/nearby_share/nearby_discovery_page.js
@@ -313,7 +313,6 @@
     const currentShareTarget = event.currentTarget.shareTarget;
     const currentIndex = this.shareTargets_.findIndex(
         (target) => tokensEqual(target.id, currentShareTarget.id));
-    console.log(event.code);
     event.stopPropagation();
     switch (event.code) {
       // Down arrow: bring into focus the next shareTarget in list.
diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts
index 1c9eba8a..23a64c30 100644
--- a/chrome/browser/resources/new_tab_page/app.ts
+++ b/chrome/browser/resources/new_tab_page/app.ts
@@ -621,11 +621,9 @@
     if (!this.shouldPrintPerformance_) {
       return;
     }
-    if (!auxTime) {
-      console.log(`${name}: ${time}`);
-    } else {
-      console.log(`${name}: ${time} (${auxTime})`);
-    }
+
+    console.info(
+        !auxTime ? `${name}: ${time}` : `${name}: ${time} (${auxTime})`);
   }
 
   /**
diff --git a/chrome/browser/resources/predictors/autocomplete_action_predictor.js b/chrome/browser/resources/predictors/autocomplete_action_predictor.js
index c0f0cdfc..cc46614 100644
--- a/chrome/browser/resources/predictors/autocomplete_action_predictor.js
+++ b/chrome/browser/resources/predictors/autocomplete_action_predictor.js
@@ -35,8 +35,6 @@
  *     a boolean indicating if the system is enabled and the current hit weight.
  */
 function updateAutocompleteActionPredictorDb(database) {
-  console.debug('Updating Table NAP DB');
-
   const filter = $('filter');
   filter.disabled = false;
   filter.onchange = function() {
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js
index a7f6e3d..d425fb3 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_disk_resize_dialog.js
@@ -146,7 +146,7 @@
               }
             },
             reason => {
-              console.log(`Unable to get info: ${reason}`);
+              console.warn(`Unable to get info: ${reason}`);
               this.displayState_ = DisplayState.ERROR;
             });
   },
@@ -179,7 +179,7 @@
               }
             },
             (reason) => {
-              console.log(`Unable to resize disk: ${reason}`);
+              console.warn(`Unable to resize disk: ${reason}`);
               this.resizeState_ = ResizeState.ERROR;
             });
   },
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js
index 095eb34d..2a721249 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_subpage.js
@@ -324,7 +324,7 @@
               }
             },
             reason => {
-              console.log(`Unable to get info: ${reason}`);
+              console.warn(`Unable to get info: ${reason}`);
             });
   },
 
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js b/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js
index 80f3369f..1d6e5a35 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/update_warning_dialog.js
@@ -51,7 +51,7 @@
   /** @private */
   onContinueTap_() {
     if (!this.updateInfo || !this.updateInfo.version || !this.updateInfo.size){
-      console.log('ERROR: requestUpdateOverCellular arguments are undefined');
+      console.warn('ERROR: requestUpdateOverCellular arguments are undefined');
       return;
     }
     this.browserProxy_.requestUpdateOverCellular(
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js
index 7fdea0ef..a2232cd 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js
@@ -50,7 +50,7 @@
               .handler.getExtensionAppPermissionMessages(this.app_.id);
       this.messages_ = messages;
     } catch (err) {
-      console.log(err);
+      console.warn(err);
     }
   },
 
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js
index 4e97b2c..e5e7c72e 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js
@@ -185,7 +185,7 @@
     } catch (err) {
       // If we fail to get the overlapping preferred apps, do not
       // show the overlap warning.
-      console.log(err);
+      console.warn(err);
       this.showOverlappingAppsWarning_ = false;
       return;
     }
@@ -274,7 +274,7 @@
     } catch (err) {
       // If we fail to get the overlapping preferred apps, don't prevent the
       // user from setting their preference.
-      console.log(err);
+      console.warn(err);
     }
 
     // If there are overlapping apps, show the overlap dialog to the user.
diff --git a/chrome/browser/resources/settings/chromeos/pref_to_setting_metric_converter.js b/chrome/browser/resources/settings/chromeos/pref_to_setting_metric_converter.js
index e4269c1..aabf1cf 100644
--- a/chrome/browser/resources/settings/chromeos/pref_to_setting_metric_converter.js
+++ b/chrome/browser/resources/settings/chromeos/pref_to_setting_metric_converter.js
@@ -30,7 +30,6 @@
 
       // device_page/pointers.js
       case 'settings.touchpad.sensitivity2':
-        console.log(prefValue);
         return {
           setting: chromeos.settings.mojom.Setting.kTouchpadSpeed,
           value: {intValue: /** @type {number} */ (prefValue)}
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.ts b/chrome/browser/resources/settings/site_settings/all_sites.ts
index b47e877e..1bbfe06 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.ts
+++ b/chrome/browser/resources/settings/site_settings/all_sites.ts
@@ -487,7 +487,6 @@
       updatedSiteGroup.origins = siteGroupToUpdate.origins.filter(
           o => (o.isPartitioned !== isPartitioned || o.origin !== origin));
 
-      console.log(updatedSiteGroup.origins);
       updatedSiteGroup.hasInstalledPWA =
           updatedSiteGroup.origins.some(o => o.isInstalled);
       updatedSiteGroup.numCookies -=
diff --git a/chrome/test/data/webui/a11y/accessibility_test.js b/chrome/test/data/webui/a11y/accessibility_test.js
index 0f6cfaa..e5cac59 100644
--- a/chrome/test/data/webui/a11y/accessibility_test.js
+++ b/chrome/test/data/webui/a11y/accessibility_test.js
@@ -194,5 +194,6 @@
       });
     }
   }
+  // eslint-disable-next-line no-console
   console.log(JSON.stringify(violations, null, 4));
 };
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js
index 37c453e..80b3903 100644
--- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js
+++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_trie_test.js
@@ -63,7 +63,6 @@
         const actualAllKeys = trie.getKeys();
         assertTrue(Array.isArray(actualAllKeys));
         assertEquals(4, actualAllKeys.length);
-        console.log(actualAllKeys);
         assertTrue(actualAllKeys.includes('grin'));
         assertTrue(actualAllKeys.includes('message'));
         assertTrue(actualAllKeys.includes('moon'));
@@ -79,4 +78,4 @@
     assertFalse(trie.containsKey('helen'));
     assertFalse(trie.containsKey('fish'));
   });
-});
\ No newline at end of file
+});
diff --git a/chrome/test/data/webui/draganddroptoinput.js b/chrome/test/data/webui/draganddroptoinput.js
index 6351d93..3d13b05 100644
--- a/chrome/test/data/webui/draganddroptoinput.js
+++ b/chrome/test/data/webui/draganddroptoinput.js
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-console.log('start guest js');
+console.info('start guest js');
 
 var embedder = null;
 window.addEventListener('message', function(e) {
   var data = JSON.parse(e.data)[0];
-  window.console.log('guest gets message ' + data);
+  window.console.info('guest gets message ' + data);
   if (data === 'create-channel') {
     embedder = e.source;
     doPostMessage('connected');
@@ -15,7 +15,7 @@
 });
 
 var doPostMessage = function(msg) {
-  window.console.log('guest posts message: ' + msg);
+  window.console.info('guest posts message: ' + msg);
   embedder.postMessage(JSON.stringify([msg]), '*');
 };
 
@@ -26,7 +26,7 @@
 var destNode = document.getElementById('dest');
 var testStep = 0;
 destNode.addEventListener('dragenter', function(e) {
-  console.log('node drag enter');
+  console.info('node drag enter');
   if (testStep === 0) {
     doPostMessage('Step1: destNode gets dragenter');
     testStep = 1;
@@ -47,4 +47,4 @@
   }
 });
 
-console.log('finish guest js');
\ No newline at end of file
+console.info('finish guest js');
diff --git a/chrome/test/data/webui/history/history_metrics_test.ts b/chrome/test/data/webui/history/history_metrics_test.ts
index d0f5a2ee..fc7fa50 100644
--- a/chrome/test/data/webui/history/history_metrics_test.ts
+++ b/chrome/test/data/webui/history/history_metrics_test.ts
@@ -104,7 +104,7 @@
 
     // TODO(https://crbug.com/1000573): Log the contents of this histogram
     // for debugging in case the flakiness reoccurs.
-    console.log(Object.keys(histogramMap['HistoryPage.ClickAgeInDays']!));
+    console.info(Object.keys(histogramMap['HistoryPage.ClickAgeInDays']!));
 
     // The "age in days" histogram should record 8 days, since the history
     // entry was created between 7 and 8 days ago and we round the
diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js
index f7f6c9e..785649cb 100644
--- a/chrome/test/data/webui/test_api.js
+++ b/chrome/test/data/webui/test_api.js
@@ -6,6 +6,8 @@
  * @fileoverview Library providing basic test framework functionality.
  */
 
+/* eslint-disable no-console */
+
 /**
  * See assert.js for where this is used.
  * @suppress {globalThis}
diff --git a/chrome/test/data/webui/webview_content_script_test.js b/chrome/test/data/webui/webview_content_script_test.js
index 7178e7dd..05dec1e 100644
--- a/chrome/test/data/webui/webview_content_script_test.js
+++ b/chrome/test/data/webui/webview_content_script_test.js
@@ -60,7 +60,7 @@
 function testAddContentScript(url) {
   var webview = document.createElement('webview');
 
-  console.log('Step 1: call <webview>.addContentScripts.');
+  console.info('Step 1: call <webview>.addContentScripts.');
   webview.addContentScripts([{
     name: 'myrule',
     matches: ['http://*/empty*'],
@@ -71,7 +71,7 @@
   }]);
 
   webview.addEventListener('loadstop', function() {
-    console.log('Step 2: postMessage to build connection.');
+    console.info('Step 2: postMessage to build connection.');
     var msg = [REQUEST_TO_COMM_CHANNEL_1];
     webview.contentWindow.postMessage(JSON.stringify(msg), '*');
   });
@@ -82,12 +82,12 @@
     }
     var data = JSON.parse(e.data);
     if (data[0] === RESPONSE_FROM_COMM_CHANNEL_1) {
-      console.log(
+      console.info(
           'Step 3: A communication channel has been established with webview.');
       chrome.send('testResult', [true]);
       return;
     }
-    console.log('Unexpected message: \'' + data[0] + '\'');
+    console.info('Unexpected message: \'' + data[0] + '\'');
     chrome.send('testResult', [false]);
   });
 
@@ -101,7 +101,7 @@
 function testAddMultiContentScripts(url) {
   var webview = document.createElement('webview');
 
-  console.log('Step 1: call <webview>.addContentScripts(myrule1 & myrule2)');
+  console.info('Step 1: call <webview>.addContentScripts(myrule1 & myrule2)');
   webview.addContentScripts([
     {
       name: 'myrule1',
@@ -118,10 +118,11 @@
   ]);
 
   webview.addEventListener('loadstop', function() {
-    console.log('Step 2: postMessage to build connection.');
+    console.info('Step 2: postMessage to build connection.');
     var msg1 = [REQUEST_TO_COMM_CHANNEL_1];
     webview.contentWindow.postMessage(JSON.stringify(msg1), '*');
-    console.log('Step 3: postMessage to build connection to the other script.');
+    console.info(
+        'Step 3: postMessage to build connection to the other script.');
     var msg2 = [REQUEST_TO_COMM_CHANNEL_2];
     webview.contentWindow.postMessage(JSON.stringify(msg2), '*');
   });
@@ -134,7 +135,7 @@
     }
     var data = JSON.parse(e.data);
     if (data[0] === RESPONSE_FROM_COMM_CHANNEL_1) {
-      console.log(
+      console.info(
           'Step 4: A communication channel has been established with webview.');
       response_1 = true;
       if (response_1 && response_2) {
@@ -142,7 +143,7 @@
       }
       return;
     } else if (data[0] === RESPONSE_FROM_COMM_CHANNEL_2) {
-      console.log(
+      console.info(
           'Step 5: A communication channel has been established with webview.');
       response_2 = true;
       if (response_1 && response_2) {
@@ -150,7 +151,7 @@
       }
       return;
     }
-    console.log('Unexpected message: \'' + data[0] + '\'');
+    console.info('Unexpected message: \'' + data[0] + '\'');
     chrome.send('testResult', [false]);
   });
 
@@ -166,7 +167,7 @@
 function testAddContentScriptWithSameNameShouldOverwriteTheExistingOne(url) {
   var webview = document.createElement('webview');
 
-  console.log('Step 1: call <webview>.addContentScripts(myrule1)');
+  console.info('Step 1: call <webview>.addContentScripts(myrule1)');
   webview.addContentScripts([{
     name: 'myrule1',
     matches: ['http://*/empty*'],
@@ -197,9 +198,9 @@
     var data = JSON.parse(e.data);
     if (data[0] === RESPONSE_FROM_COMM_CHANNEL_1) {
       if (should_get_response_from_script_1) {
-        console.log(
+        console.info(
             'Step 2: A communication channel has been established with webview.');
-        console.log(
+        console.info(
             'Step 3: <webview>.addContentScripts() with a updated' +
             ' \'myrule1\'');
         webview.addContentScripts([{
@@ -216,7 +217,7 @@
       }
       return;
     } else if (data[0] === RESPONSE_FROM_COMM_CHANNEL_2) {
-      console.log(
+      console.info(
           'Step 4: Another communication channel has been established ' +
           'with webview.');
       setTimeout(function() {
@@ -224,7 +225,7 @@
       }, 0);
       return;
     }
-    console.log('Unexpected message: \'' + data[0] + '\'');
+    console.info('Unexpected message: \'' + data[0] + '\'');
     chrome.send('testResult', [false]);
   });
 
@@ -239,7 +240,7 @@
   var webview1 = document.createElement('webview');
   var webview2 = document.createElement('webview');
 
-  console.log('Step 1: call <webview1>.addContentScripts.');
+  console.info('Step 1: call <webview1>.addContentScripts.');
   webview1.addContentScripts([{
     name: 'myrule',
     matches: ['http://*/empty*'],
@@ -248,7 +249,7 @@
   }]);
 
   webview2.addEventListener('loadstop', function() {
-    console.log('Step 2: webview2 requests to build communication channel.');
+    console.info('Step 2: webview2 requests to build communication channel.');
     var msg = [REQUEST_TO_COMM_CHANNEL_1];
     webview2.contentWindow.postMessage(JSON.stringify(msg), '*');
     setTimeout(function() {
@@ -265,7 +266,7 @@
       chrome.send('testResult', [false]);
       return;
     }
-    console.log('Unexpected message: \'' + data[0] + '\'');
+    console.info('Unexpected message: \'' + data[0] + '\'');
     chrome.send('testResult', [false]);
   });
 
@@ -283,7 +284,7 @@
 function testAddAndRemoveContentScripts(url) {
   var webview = document.createElement('webview');
 
-  console.log('Step 1: call <webview>.addContentScripts.');
+  console.info('Step 1: call <webview>.addContentScripts.');
   webview.addContentScripts([{
     name: 'myrule',
     matches: ['http://*/empty*'],
@@ -296,12 +297,12 @@
   var count = 0;
   webview.addEventListener('loadstop', function() {
     if (count === 0) {
-      console.log('Step 2: post message to build connect.');
+      console.info('Step 2: post message to build connect.');
       var msg = [REQUEST_TO_COMM_CHANNEL_1];
       webview.contentWindow.postMessage(JSON.stringify(msg), '*');
       ++count;
     } else if (count === 1) {
-      console.log('Step 5: post message to build connect again.');
+      console.info('Step 5: post message to build connect again.');
       var msg = [REQUEST_TO_COMM_CHANNEL_1];
       webview.contentWindow.postMessage(JSON.stringify(msg), '*');
       setTimeout(function() {
@@ -317,16 +318,16 @@
     var data = JSON.parse(e.data);
     if (data[0] === RESPONSE_FROM_COMM_CHANNEL_1 &&
         should_get_response_from_script_1) {
-      console.log(
+      console.info(
           'Step 3: A communication channel has been established ' +
           'with webview.');
       should_get_response_from_script_1 = false;
-      console.log('Step 4: call <webview>.removeContentScripts and navigate.');
+      console.info('Step 4: call <webview>.removeContentScripts and navigate.');
       webview.removeContentScripts();
       webview.src = url;
       return;
     }
-    console.log('Unexpected message: \'' + data[0] + '\'');
+    console.info('Unexpected message: \'' + data[0] + '\'');
     chrome.send('testResult', [false]);
   });
 
@@ -344,7 +345,7 @@
     e.preventDefault();
     newwebview = document.createElement('webview');
 
-    console.log('Step 2: call newwebview.addContentScripts.');
+    console.info('Step 2: call newwebview.addContentScripts.');
     newwebview.addContentScripts([{
       name: 'myrule',
       matches: ['http://*/guest_from_opener*'],
@@ -354,7 +355,7 @@
 
     newwebview.addEventListener('loadstop', function(evt) {
       var msg = [REQUEST_TO_COMM_CHANNEL_1];
-      console.log(
+      console.info(
           'Step 4: new webview postmessage to build communication ' +
           'channel.');
       newwebview.contentWindow.postMessage(JSON.stringify(msg), '*');
@@ -362,7 +363,7 @@
 
     document.body.appendChild(newwebview);
     // attach the new window to the new <webview>.
-    console.log('Step 3: attaches the new webview.');
+    console.info('Step 3: attaches the new webview.');
     e.window.attach(newwebview);
   });
 
@@ -373,7 +374,7 @@
     var data = JSON.parse(e.data);
     if (data[0] === RESPONSE_FROM_COMM_CHANNEL_1 &&
         e.source === newwebview.contentWindow) {
-      console.log(
+      console.info(
           'Step 5: a communication channel has been established ' +
           'with the new webview.');
       chrome.send('testResult', [true]);
@@ -382,11 +383,11 @@
       chrome.send('testResult', [false]);
       return;
     }
-    console.log('Unexpected message: \'' + data[0] + '\'');
+    console.info('Unexpected message: \'' + data[0] + '\'');
     chrome.send('testResult', [false]);
   });
 
-  console.log('Step 1: navigates the webview to window open guest URL.');
+  console.info('Step 1: navigates the webview to window open guest URL.');
   webview.setAttribute('src', url);
   document.body.appendChild(webview);
 }
@@ -396,7 +397,7 @@
 function testContentScriptIsInjectedAfterTerminateAndReloadWebView(url) {
   var webview = document.createElement('webview');
 
-  console.log('Step 1: call <webview>.addContentScripts.');
+  console.info('Step 1: call <webview>.addContentScripts.');
   webview.addContentScripts([{
     name: 'myrule',
     matches: ['http://*/empty*'],
@@ -407,12 +408,12 @@
   var count = 0;
   webview.addEventListener('loadstop', function() {
     if (count === 0) {
-      console.log('Step 2: call webview.terminate().');
+      console.info('Step 2: call webview.terminate().');
       webview.terminate();
       ++count;
       return;
     } else if (count === 1) {
-      console.log('Step 4: call <webview>.executeScript to check result.');
+      console.info('Step 4: call <webview>.executeScript to check result.');
       webview.executeScript(
           {code: 'document.body.style.backgroundColor;'},
           onGetBackgroundExecuted);
@@ -420,7 +421,7 @@
   });
 
   webview.addEventListener('exit', function() {
-    console.log('Step 3: call webview.reload().');
+    console.info('Step 3: call webview.reload().');
     webview.reload();
   });
 
@@ -433,7 +434,7 @@
 function testContentScriptExistsAsLongAsWebViewTagExists(url) {
   var webview = document.createElement('webview');
 
-  console.log('Step 1: call <webview>.addContentScripts.');
+  console.info('Step 1: call <webview>.addContentScripts.');
   webview.addContentScripts([{
     name: 'myrule',
     matches: ['http://*/empty*'],
@@ -444,20 +445,21 @@
   var count = 0;
   webview.addEventListener('loadstop', function() {
     if (count === 0) {
-      console.log('Step 2: check the result of content script injected.');
+      console.info('Step 2: check the result of content script injected.');
       webview.executeScript(
           {code: 'document.body.style.backgroundColor;'}, function(results) {
             assertEquals(1, results.length);
             assertEquals('red', results[0]);
 
-            console.log('Step 3: remove webview from the DOM.');
+            console.info('Step 3: remove webview from the DOM.');
             document.body.removeChild(webview);
-            console.log('Step 4: add webview back to the DOM.');
+            console.info('Step 4: add webview back to the DOM.');
             document.body.appendChild(webview);
             ++count;
           });
     } else if (count === 1) {
-      console.log('Step 5: check the result of content script injected again.');
+      console.info(
+          'Step 5: check the result of content script injected again.');
       webview.executeScript(
           {code: 'document.body.style.backgroundColor;'},
           onGetBackgroundExecuted);
@@ -471,7 +473,7 @@
 function testAddContentScriptWithCode(url) {
   var webview = document.createElement('webview');
 
-  console.log('Step 1: call <webview>.addContentScripts.');
+  console.info('Step 1: call <webview>.addContentScripts.');
   webview.addContentScripts([{
     name: 'myrule',
     matches: ['http://*/empty*'],
@@ -480,7 +482,7 @@
   }]);
 
   webview.addEventListener('loadstop', function() {
-    console.log('Step 2: call webview.executeScript() to check result.');
+    console.info('Step 2: call webview.executeScript() to check result.');
     webview.executeScript(
         {code: 'document.body.style.backgroundColor;'},
         onGetBackgroundExecuted);
@@ -507,7 +509,7 @@
 
   window.addEventListener('message', function(e) {
     var data = JSON.parse(e.data)[0];
-    console.log('get message: ' + data);
+    console.info('get message: ' + data);
     if (data === 'connected') {
       chrome.send('testResult', [true]);
       return;
@@ -520,10 +522,10 @@
     if (webview.src !== 'about:blank') {
       return;
     }
-    console.log('load stop of src = :' + webview.src);
+    console.info('load stop of src = :' + webview.src);
     webview.executeScript(
         {file: 'test/draganddroptoinput.js'}, function(results) {
-          console.log('finish guest load');
+          console.info('finish guest load');
           webview.contentWindow.postMessage(
               JSON.stringify(['create-channel']), '*');
         });
@@ -531,7 +533,7 @@
 
   // For debug messages from guests.
   webview.addEventListener('consolemessage', function(e) {
-    console.log('[Guest]: ' + e.message);
+    console.info('[Guest]: ' + e.message);
   });
 
   webview.src = 'about:blank';
diff --git a/content/browser/resources/gpu/info_view.js b/content/browser/resources/gpu/info_view.js
index c24cf5a..a869873 100644
--- a/content/browser/resources/gpu/info_view.js
+++ b/content/browser/resources/gpu/info_view.js
@@ -319,7 +319,7 @@
 
         const nameEl = document.createElement('span');
         if (!featureLabelMap[featureName]) {
-          console.log('Missing featureLabel for', featureName);
+          console.info('Missing featureLabel for', featureName);
         }
         nameEl.textContent = featureLabelMap[featureName] + ': ';
         featureEl.appendChild(nameEl);
@@ -327,7 +327,7 @@
         const statusEl = document.createElement('span');
         const statusInfo = statusMap[featureStatus];
         if (!statusInfo) {
-          console.log('Missing status for ', featureStatus);
+          console.info('Missing status for ', featureStatus);
           statusEl.textContent = 'Unknown';
           statusEl.className = 'feature-red';
         } else {
diff --git a/ui/file_manager/.eslintrc.js b/ui/file_manager/.eslintrc.js
new file mode 100644
index 0000000..7b1f71f
--- /dev/null
+++ b/ui/file_manager/.eslintrc.js
@@ -0,0 +1,9 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+  'rules': {
+    'no-console': 'off',
+  },
+};
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js
index d2fdb61..f5603c93 100644
--- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js
+++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js
@@ -73,7 +73,7 @@
   /** @override */
   setHostDevice(hostInstanceIdOrLegacyDeviceId) {
     if (this.shouldSetHostSucceed) {
-      console.log(
+      console.info(
           'setHostDevice(' + hostInstanceIdOrLegacyDeviceId +
           ') called; simulating ' +
           'success.');
diff --git a/ui/webui/resources/js/cr/ui/splitter.js b/ui/webui/resources/js/cr/ui/splitter.js
index 1c7f07d8..8e72fd9 100644
--- a/ui/webui/resources/js/cr/ui/splitter.js
+++ b/ui/webui/resources/js/cr/ui/splitter.js
@@ -59,7 +59,7 @@
    */
   startDrag(clientX, isTouchEvent) {
     if (this.handlers_) {
-      console.log('Concurent drags');
+      // Case of concurrent drags.
       this.endDrag_();
     }
     if (isTouchEvent) {
diff --git a/ui/webui/resources/js/post_message_api_client.js b/ui/webui/resources/js/post_message_api_client.js
index 58df1c5e..fe67df7 100644
--- a/ui/webui/resources/js/post_message_api_client.js
+++ b/ui/webui/resources/js/post_message_api_client.js
@@ -175,7 +175,7 @@
     }
 
     if (!this.methodsAwaitingResponse_.has(event.data.methodId)) {
-      console.log('discarding event method is not waiting for a response');
+      console.info('discarding event method is not waiting for a response');
       return;
     }
 
diff --git a/ui/webui/resources/js/post_message_api_request_handler.js b/ui/webui/resources/js/post_message_api_request_handler.js
index be5734e..fc5f8473 100644
--- a/ui/webui/resources/js/post_message_api_request_handler.js
+++ b/ui/webui/resources/js/post_message_api_request_handler.js
@@ -99,7 +99,8 @@
    */
   async handleMessage_(event) {
     if (!this.originMatchesFilter(event.origin)) {
-      console.log('Message received from unauthorized origin: ' + event.origin);
+      console.info(
+          'Message received from unauthorized origin: ' + event.origin);
       return;
     }
 
@@ -114,7 +115,7 @@
     const args = event.data.args || [];
 
     if (!this.canHandle(fn)) {
-      console.log('Unknown function requested: ' + fn);
+      console.info('Unknown function requested: ' + fn);
       return;
     }
 
diff --git a/ui/webui/resources/js/post_message_api_server.js b/ui/webui/resources/js/post_message_api_server.js
index 75a7aed..c1ddd91 100644
--- a/ui/webui/resources/js/post_message_api_server.js
+++ b/ui/webui/resources/js/post_message_api_server.js
@@ -73,7 +73,7 @@
       // Tell the embedded webviews whose src matches our origin to initialize
       // by sending it a message, which will include a handle for it to use to
       // send messages back.
-      console.log(
+      console.info(
           'Sending init message to guest content,  attempt # :' +
           this.numInitializationAttempts_);
 
@@ -121,7 +121,8 @@
    */
   async onMessage_(event) {
     if (!this.originMatchesFilter(event.origin)) {
-      console.log('Message received from unauthorized origin: ' + event.origin);
+      console.info(
+          'Message received from unauthorized origin: ' + event.origin);
       return;
     }
 
diff --git a/ui/webui/resources/js/webui_resource_test.js b/ui/webui/resources/js/webui_resource_test.js
index dac953a..202680c 100644
--- a/ui/webui/resources/js/webui_resource_test.js
+++ b/ui/webui/resources/js/webui_resource_test.js
@@ -239,7 +239,7 @@
 async function continueTesting(opt_asyncTestFailure) {
   const now = performance.now();
   if (testName) {
-    console.log(
+    console.info(
         'TEST ' + testName +
         ' complete, status=' + (opt_asyncTestFailure ? 'FAIL' : 'PASS') +
         ', duration=' + Math.round(now - testStartTime) + 'ms');
@@ -255,7 +255,7 @@
   if (testCases.length > 0) {
     testStartTime = now;
     testName = testCases.pop();
-    console.log('TEST ' + testName + ' starting...');
+    console.info('TEST ' + testName + ' starting...');
     const isAsyncTest = testScope[testName].length;
     let testError = false;
     try {
@@ -266,7 +266,7 @@
       await testScope[testName](continueTesting);
     } catch (err) {
       console.error('Failure in test ' + testName + '\n' + err);
-      console.log(err.stack);
+      console.info(err.stack);
       cleanTestRun = false;
       testError = true;
     }
@@ -291,7 +291,7 @@
 function endTests(success) {
   const duration =
       runnerStartTime === 0 ? 0 : performance.now() - runnerStartTime;
-  console.log(
+  console.info(
       'TEST all complete, status=' + (success ? 'PASS' : 'FAIL') +
       ', duration=' + Math.round(duration) + 'ms');
   testName = null;
diff --git a/ui/webui/resources/tools/tests/.eslintrc.js b/ui/webui/resources/tools/tests/.eslintrc.js
new file mode 100644
index 0000000..7b1f71f
--- /dev/null
+++ b/ui/webui/resources/tools/tests/.eslintrc.js
@@ -0,0 +1,9 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+  'rules': {
+    'no-console': 'off',
+  },
+};