Extensions: SidePanel: Create manifest key(s), API, and storage [chromium/src : main]

94 views
Skip to first unread message

Solomon Kinard (Gerrit)

unread,
May 23, 2022, 2:40:27 PM5/23/22
to Devlin Cronin, Kelvin Jiang, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org

Attention is currently required from: Devlin Cronin.

Solomon Kinard would like Devlin Cronin to review this change.

Solomon Kinard removed Kelvin Jiang from this change.

View Change

Extensions: SidePanel: Create manifest key(s), API, and storage

Design Doc:
https://docs.google.com/document/d/1EjRghIJR1u1-UadYHdBhCCtY3A108LtEznSWzz7FtwE

Bug: 477424
Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
---
M chrome/browser/extensions/BUILD.gn
A chrome/browser/extensions/api/side_panel/side_panel_api.cc
A chrome/browser/extensions/api/side_panel/side_panel_api.h
A chrome/browser/extensions/api/side_panel/side_panel_apitest.cc
A chrome/browser/extensions/api/side_panel/side_panel_service.cc
A chrome/browser/extensions/api/side_panel/side_panel_service.h
A chrome/browser/extensions/api/side_panel/side_panel_types.cc
A chrome/browser/extensions/api/side_panel/side_panel_types.h
M chrome/browser/extensions/browser_context_keyed_service_factories.cc
M chrome/common/extensions/api/_api_features.json
M chrome/common/extensions/api/_permission_features.json
M chrome/common/extensions/api/api_sources.gni
A chrome/common/extensions/api/side_panel.idl
A chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc
M chrome/common/extensions/permissions/chrome_api_permissions.cc
M chrome/common/extensions/permissions/permission_set_unittest.cc
M chrome/test/BUILD.gn
A chrome/test/data/extensions/api_test/side_panel/extension/default_path.html
A chrome/test/data/extensions/api_test/side_panel/extension/manifest.json
A chrome/test/data/extensions/api_test/side_panel/extension/panel.html
A chrome/test/data/extensions/api_test/side_panel/extension/test.html
A chrome/test/data/extensions/api_test/side_panel/extension/test.js
A chrome/test/data/extensions/api_test/side_panel/permission_missing/manifest.json
A chrome/test/data/extensions/api_test/side_panel/permission_missing/test.html
A chrome/test/data/extensions/api_test/side_panel/permission_missing/test.js
M extensions/browser/extension_function_histogram_value.h
M extensions/common/BUILD.gn
M extensions/common/api/_manifest_features.json
M extensions/common/api/schema.gni
A extensions/common/api/side_panel.idl
M extensions/common/common_manifest_handlers.cc
M extensions/common/extension_features.cc
M extensions/common/extension_features.h
M extensions/common/manifest_constants.cc
M extensions/common/manifest_constants.h
M extensions/common/manifest_handler.cc
A extensions/common/manifest_handlers/side_panel_info.cc
A extensions/common/manifest_handlers/side_panel_info.h
M extensions/common/mojom/api_permission_id.mojom
M tools/metrics/histograms/enums.xml
40 files changed, 878 insertions(+), 2 deletions(-)


To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 4
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-MessageType: newchange

Solomon Kinard (Gerrit)

unread,
May 23, 2022, 2:40:33 PM5/23/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Devlin Cronin.

View Change

1 comment:

  • Patchset:

    • Patch Set #4:

      Code complete. Can haz review? Thank you.

      This CL represents everything required for the Side Panel project. Anything else is nice to have.

      For context on my approach, the design doc can be commented if there are major disagreements.

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 4
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Comment-Date: Mon, 23 May 2022 18:40:24 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment

Solomon Kinard (Gerrit)

unread,
May 25, 2022, 11:54:14 AM5/25/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org

Attention is currently required from: Devlin Cronin.

Solomon Kinard uploaded patch set #7 to this change.

View Change

Extensions: SidePanel: Create manifest key(s), API, and storage

Design Doc:
https://docs.google.com/document/d/1EjRghIJR1u1-UadYHdBhCCtY3A108LtEznSWzz7FtwE

Bug: 1328645
M extensions/common/manifest.cc

M extensions/common/manifest_constants.cc
M extensions/common/manifest_constants.h
M extensions/common/manifest_handler.cc
A extensions/common/manifest_handlers/side_panel_info.cc
A extensions/common/manifest_handlers/side_panel_info.h
M extensions/common/mojom/api_permission_id.mojom
M tools/metrics/histograms/enums.xml
41 files changed, 948 insertions(+), 3 deletions(-)

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 7
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-MessageType: newpatchset

Devlin Cronin (Gerrit)

unread,
May 25, 2022, 6:01:05 PM5/25/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Solomon Kinard.

View Change

28 comments:

  • Patchset:

    • Patch Set #8:

      Thanks, Solomon!

      I made it most of the way through this one (and wanted to get it back to you now so you're unblocked).

  • File chrome/browser/extensions/api/side_panel/side_panel_api.h:

    • Patch Set #8, Line 27: SIDE_PANEL_GET

      IWYU extension_function_histogram_value

    • Patch Set #8, Line 27: sidePanel.get

      I think we can omit the "panel" from the name here, but I'd like to keep "options" - i.e., "getOptions", "setOptions". This makes it clear it's not returning the panel itself.

    • Patch Set #8, Line 27: SIDE_PANEL_GET

      Default style is to basically only use '_' for "." in the name, so this should be "SIDEPANEL_GET"

    • Patch Set #8, Line 48:


      class SidePanelRemoveFunction : public SidePanelApiFunction {
      public:
      DECLARE_EXTENSION_FUNCTION("sidePanel.remove", SIDE_PANEL_REMOVE)
      SidePanelRemoveFunction() = default;
      SidePanelRemoveFunction(const SidePanelRemoveFunction&) = delete;
      SidePanelRemoveFunction& operator=(const SidePanelRemoveFunction&) = delete;

      private:
      ~SidePanelRemoveFunction() override = default;
      ResponseAction RunSidePanelFunction() override;
      };

      rather than remove, extensions can use setOptions with enabled: false. (Separately, adding new methods should go through the API proposal, so let's discuss there if there are pieces missing)

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • Patch Set #8, Line 22: class BrowserContext;

      forward declarations are really only used in header files; this is unnecessary.

    • Patch Set #8, Line 32:

      SidePanelOptions GetOptionsFromValue(std::unique_ptr<base::Value> value) {
      base::Value::Dict dict = std::move(value->GetDict());
      const auto id = dict.FindInt("tabId");
      const auto* path = dict.FindString("path");
      const auto enabled = dict.FindBool("enabled");
      return SidePanelOptions(id, *path, enabled);
      }

      we should use the auto-generated types and conversion from the schema. It looks like you're doing this below, but then converting to a value, and then converting to a new type. Why not just use the auto-generated types directly?

    • Patch Set #8, Line 61: RespondNow(OneArgument(base::Value(true)));

      This isn't guaranteed to be the proper return type, which will crash the browser if response validation is enabled. We need to make sure to return the expected type.

    • Patch Set #8, Line 75:

        std::unique_ptr<api::side_panel::Set::Params> params(
      api::side_panel::Set::Params::Create(args()));
      EXTENSION_FUNCTION_VALIDATE(params);
      GetService()->SetPanel(GetOptionsFromValue(params->options.ToValue()));

      As mentioned above, I think we can simplify this.

      This flow:

      • Starts as a base::Value
      • Converts to a strongly-typed side panel options struct
      • Converts back to a base::Value
      • Converts to a custom type.

      Let's just use the generated types, and convert once.

  • File chrome/browser/extensions/api/side_panel/side_panel_apitest.cc:

    • Patch Set #8, Line 8: #include "chrome/test/base/ui_test_utils.h"

      are all these includes needed?

    • Patch Set #8, Line 31: {.extension_url = "test.html"}

      unlike the favicon work (where we need a DOM because we want to embed img tags), these can run directly from the extension's service worker - no need for a separate page.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #8, Line 75: static base::LazyInstance<BrowserContextKeyedAPIFactory<SidePanelService>>::

      prefer base::NoDestructor in new code

  • File chrome/common/extensions/api/_permission_features.json:

  • File chrome/common/extensions/api/side_panel.idl:

    • Patch Set #8, Line 7: // The options used when setting a side panel. Omitted properties are unchanged.

      nit: wrapping

    • Patch Set #8, Line 39:

      PanelOptions options,
      VoidCallback callback

      function arguments should either be aligned or all on the same line:

      ```
      static void setOptions(PanelOptions options,
      VoidCallback callback);
      ```
  • File chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc:

    • Patch Set #8, Line 97: All

      Prefer avoiding "All" as test suites. This covers a pretty specific case (the file doesn't exist), so let's give it a more descriptive name.

  • File chrome/test/data/extensions/api_test/side_panel/extension/test.js:

    • Patch Set #8, Line 4:


      // The options to change when updating a side panel.
      class PanelOptions {
      constructor(options) {
      // Int?. Side panel to specific tab id. If unset, all unspecified tabs.
      this.tabId;

      // String?. The local extension path to the side panel HTML file to use.
      this.path;

      // Bool?. Whether the side panel should be enabled.
      this.enabled;

      // Update this object from the constructor parameter.
      options && Object.keys(options).forEach(key => this[key] = options[key]);
      }
      };

      This appears to be unused? (And shouldn't be necessary - just passing a "bag of properties" is standard form in JS for things like this)

    • Patch Set #8, Line 92: compareObjects

      avoid re-inventing the wheel : ) chrome.test.assertEq() compares objects with > 1 depth and gives detailed error messages.

  • File extensions/common/api/_manifest_features.json:

  • File extensions/common/extension_features.cc:

    • Patch Set #8, Line 90: kSidePanel

      Let's call this something like ExtensionSidePanelIntegration. (While the feature object is prefixed with extensions_features, the string value is shared across all features, so should be reasonably unique and descriptive)

  • File extensions/common/manifest_handler.cc:

  • File extensions/common/manifest_handlers/side_panel_info.h:

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 8
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Wed, 25 May 2022 22:00:51 +0000

Solomon Kinard (Gerrit)

unread,
May 26, 2022, 6:24:58 PM5/26/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Devlin Cronin.

View Change

28 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_api.h:

    • Default style is to basically only use '_' for ". […]

      Done

    • I think we can omit the "panel" from the name here, but I'd like to keep "options" - i.e. […]

      I don't think Options (re: sidePanelOptions) were in the API when I LGTM'd it, based on still present references to "sidePanel.setPanel()" and crbug.com/1328645#c2. That said, I'm not opposed to adding sidePanel.setOptions(). That's better than sidePanel.setPanel(), but not as good as sidePanel.set().

    • Done

    • Patch Set #8, Line 48:


      class SidePanelRemoveFunction : public SidePanelApiFunction {
      public:
      DECLARE_EXTENSION_FUNCTION("sidePanel.remove", SIDE_PANEL_REMOVE)
      SidePanelRemoveFunction() = default;
      SidePanelRemoveFunction(const SidePanelRemoveFunction&) = delete;
      SidePanelRemoveFunction& operator=(const SidePanelRemoveFunction&) = delete;

      private:
      ~SidePanelRemoveFunction() override = default;
      ResponseAction RunSidePanelFunction() override;
      };

    • rather than remove, extensions can use setOptions with enabled: false. […]

      I added a comment to the proposal a few minutes after your comment here. I think I may also have added my reasoning for .remove() in the design doc before uploading. tldr remove is necessary for actual removal, where disabled only obfuscates.

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • Patch Set #8, Line 22: class BrowserContext;

      forward declarations are really only used in header files; this is unnecessary.

    • Done

    • Patch Set #8, Line 32:

      SidePanelOptions GetOptionsFromValue(std::unique_ptr<base::Value> value) {
      base::Value::Dict dict = std::move(value->GetDict());
      const auto id = dict.FindInt("tabId");
      const auto* path = dict.FindString("path");
      const auto enabled = dict.FindBool("enabled");
      return SidePanelOptions(id, *path, enabled);
      }

    • Done

    • Why not just use the auto-generated types directly?

    • 1) A custom SidePanelOptions type allows for one line calls such as:
      `GetService()->SetPanel(GetOptionsFromValue(params->options.ToValue()));`. 2) The manual type had the benefit of portability for the service file to use types agnostic of a generated api schema. 3) auto-generated types rely on deprecated DictionaryValue, and 4) auto-generated types don't have a default constructor for single line initialization.

    • This isn't guaranteed to be the proper return type, which will crash the browser if response validat […]

      Done

    • Patch Set #8, Line 75:

        std::unique_ptr<api::side_panel::Set::Params> params(
      api::side_panel::Set::Params::Create(args()));
      EXTENSION_FUNCTION_VALIDATE(params);
      GetService()->SetPanel(GetOptionsFromValue(params->options.ToValue()));

    • As mentioned above, I think we can simplify this. […]

      After the change, there was no need to convert in this file as options can be passed directly to _service.

  • File chrome/browser/extensions/api/side_panel/side_panel_apitest.cc:

    • Ack

    • unlike the favicon work (where we need a DOM because we want to embed img tags), these can run direc […]

      Good call.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Ack

    • Done

    • Patch Set #8, Line 25: class SidePanelService : public BrowserContextKeyedAPI {

      add a class comment describing what this is used for

    • Ack

    • Patch Set #8, Line 40:

      Get the
      // default options if already set, otherwise get manifest info.

      What if there's no manifest info?

    • Comment updated. Also, browser_test SidePanelApiTest.UndefinedManifestKey.

    • prefer `const Extension&` if the extension can't be null (we're bad about this, but should be better […]

      Done

    • The new way is extensionIds keyed to tabIds keyed to options. This makes it possible for OnExtensionUninstalled to remove options with ease, less memory usage, and chrome.sidePanel.getAll() functionality.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #8, Line 75: static base::LazyInstance<BrowserContextKeyedAPIFactory<SidePanelService>>::

      prefer base::NoDestructor in new code

    • Done

  • File chrome/common/extensions/api/_permission_features.json:

    • Done

  • File chrome/common/extensions/api/side_panel.idl:

    • Patch Set #8, Line 7: // The options used when setting a side panel. Omitted properties are unchanged.

      nit: wrapping

    • Done

    • function arguments should either be aligned or all on the same line: […]

      Done

  • File chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc:

    • Prefer avoiding "All" as test suites. […]

      Done

  • File chrome/test/data/extensions/api_test/side_panel/extension/test.js:

    • Patch Set #8, Line 4:


      // The options to change when updating a side panel.
      class PanelOptions {
      constructor(options) {
      // Int?. Side panel to specific tab id. If unset, all unspecified tabs.
      this.tabId;

      // String?. The local extension path to the side panel HTML file to use.
      this.path;

      // Bool?. Whether the side panel should be enabled.
      this.enabled;

      // Update this object from the constructor parameter.
      options && Object.keys(options).forEach(key => this[key] = options[key]);
      }
      };

    • This appears to be unused? (And shouldn't be necessary - just passing a "bag of properties" is stan […]

      Ack

    • avoid re-inventing the wheel : ) chrome.test. […]

      Ack

  • File extensions/common/api/_manifest_features.json:

    • Done

  • File extensions/common/extension_features.cc:

    • Let's call this something like ExtensionSidePanelIntegration. […]

      Done

  • File extensions/common/manifest_handler.cc:

    • Done

  • File extensions/common/manifest_handlers/side_panel_info.h:

    • Ack

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 9
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Comment-Date: Thu, 26 May 2022 22:24:47 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-MessageType: comment

Devlin Cronin (Gerrit)

unread,
May 27, 2022, 5:14:04 PM5/27/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Solomon Kinard.

View Change

27 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_api.h:

    • Patch Set #8, Line 27: sidePanel.get

      I don't think Options (re: sidePanelOptions) were in the API when I LGTM'd it, based on still presen […]

      There was a discussion about setPanel vs setPanelOptions on the doc; I think the reasoning there applies the same way for setOptions vs set.

    • Patch Set #8, Line 48:


      class SidePanelRemoveFunction : public SidePanelApiFunction {
      public:
      DECLARE_EXTENSION_FUNCTION("sidePanel.remove", SIDE_PANEL_REMOVE)
      SidePanelRemoveFunction() = default;
      SidePanelRemoveFunction(const SidePanelRemoveFunction&) = delete;
      SidePanelRemoveFunction& operator=(const SidePanelRemoveFunction&) = delete;

      private:
      ~SidePanelRemoveFunction() override = default;
      ResponseAction RunSidePanelFunction() override;
      };

    • I added a comment to the proposal a few minutes after your comment here. […]

      Let's continue the discussion on the doc (and add remove() in a followup if we go that route)

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • SidePanelOptions GetOptionsFromValue(std::unique_ptr<base::Value> value) {
      base::Value::Dict dict = std::move(value->GetDict());
      const auto id = dict.FindInt("tabId");
      const auto* path = dict.FindString("path");
      const auto enabled = dict.FindBool("enabled");
      return SidePanelOptions(id, *path, enabled);
      }

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • Patch Set #10, Line 35:

        if (!IsSidePanelApiAvailable())
      return RunRespondNow();

      Rather than returning a stub value, I think we should return an error in this case. That also avoids the need for a RunRespondNow() virtual function.

      ```
      if (!IsSidePanelApiAvailable())
      return RespondNow(Error("API Unavailable"));
      ```
    • Patch Set #10, Line 46: .get()

      no need for .get() call

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Patch Set #10, Line 8: #include <map>

      needed?

    • Patch Set #10, Line 19:

      using TabId = int;
      using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;
      using PanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

      Can these live in the SidePanelService class?

    • Patch Set #10, Line 45: std::unique_ptr<TabId> tab_id

      prefer absl::optional over unique_ptr to represent optionality (I know our generated types don't do this, but that's because they predate optional)

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Patch Set #8, Line 61: std::map<TabId, SidePanelOptions> panels_;

      The new way is extensionIds keyed to tabIds keyed to options. […]

      Ack

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #10, Line 30:

          base::Value::Dict dict;
      if (!path.empty()) {
      dict.Set("path", path);
      dict.Set("enabled", true);
      }
      api::side_panel::PanelOptions options;
      api::side_panel::PanelOptions::Populate(base::Value(std::move(dict)),
      &options);
      return options;

      We shouldn't generate types from base::Value except for in (de)serialization. Instead, we should just use the type directly:

      ```
      api::side_panel::PanelOptions options;
      if (!path.empty()) {
      options.path = path;
      options.enabled = true;
      }
      return options;
      ```
    • Patch Set #10, Line 43: auto* it = &panels_.find(extension.id())->second;

      We already do this lookup, so let's cache the result earlier.

      ```
      auto iter = panels_.find(extension.id());
      if (iter == panels_.end()) {
      // Check manifest info
      }

      TabPanelOptions& tab_options = iter->second;
      ```

    • Patch Set #10, Line 47:

          auto path = SidePanelInfo::GetDefaultPath(&extension);
      base::Value::Dict dict;
      if (!path.empty()) {
      dict.Set("path", path);
      dict.Set("enabled", true);
      }
      api::side_panel::PanelOptions options;
      api::side_panel::PanelOptions::Populate(base::Value(std::move(dict)),
      &options);
      return options;

      This code is duplicated. Pull it out into a helper function, GetPanelOptionsFromManifest()?

    • Patch Set #10, Line 61:

          auto dict = std::move((*it)[default_tab_id].ToValue()->GetDict());
      dict.Set("tabId", tab_id);
      api::side_panel::PanelOptions options;
      api::side_panel::PanelOptions::Populate(base::Value(std::move(dict)),
      &options);
      return options;

      I'd like to avoid creating a copy of PanelOptions if we can (especially since there isn't a handy Clone() method on it, which led to this dance between PanelOptions -> Value -> PanelOptions). Can we have this method return a const &? This would require us storing the manifest-specified panel options (because we can't return a reference to a temporary), but I think that might be cleaner overall.

    • Patch Set #10, Line 85:

        if (panels_.find(extension.id()) == panels_.end())
      panels_[extension.id()] = TabPanelOptions();
      auto* it = &panels_.find(extension.id())->second;

      This ends up doing 3 different lookups into the map:

      • the find()
      • the operator[]
      • the second find()

      We can instead just do:
      ```
      TabPanelOptions& tab_options = panels_[extension.id()];
      ```

      This will create a new entry in the map if one doesn't exist, and will re-use the existing one if it does.

  • File chrome/common/extensions/api/side_panel.idl:

  • File chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc:

  • File chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js:

  • File extensions/common/api/_manifest_features.json:

  • File extensions/common/api/side_panel.idl:

    • Patch Set #10, Line 5:

      // Namespace for the "side_panel" manifest key.
      [generate_error_messages] namespace sidePanel {
      dictionary SidePanel {
      // Developer specified path for side panel display.
      DOMString default_path;
      };

      dictionary ManifestKeys {
      SidePanel side_panel;
      };
      };

      An API should generally live at one "layer" (i.e., either at //chrome or //extensions). Side Panel should probably be in //chrome, because it depends heavily on browser concepts. We can combine this IDL file with the one at //chrome/common/extensions/api/side_panel.idl. Similarly, the features entries and manifest handlers should also be at the //chrome layer.

  • File extensions/common/manifest_handlers/side_panel_info.h:

    • Patch Set #10, Line 11: #include "base/containers/flat_set.h"

      needed?

    • Patch Set #10, Line 20: // Define out of line constructor/destructor for Clang.

      nit: I don't think this comment is necessary (since this goes for most ctors/dtors defined in a header file)

  • File extensions/common/manifest_handlers/side_panel_info.cc:

    • Patch Set #10, Line 48:

        auto gurl = extension->GetResourceURL(path);
      auto relative_path = file_util::ExtensionURLToRelativeFilePath(gurl);

      This seems to take a relative path, turn it into a GURL, and then turn it into a path. Could we instead just do `auto resource_path = extension->GetResource(path).GetFilePath()`?

    • Patch Set #10, Line 78:

        if (extension->manifest_version() < 3) {
      *error =
      ErrorUtils::FormatErrorMessageUTF16(errors::kManifestMinimumError, "3");
      return false;
      }

      This should be handled by our features system (with the addition of the min_manifest_version in the features files)

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 10
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Fri, 27 May 2022 21:13:54 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Solomon Kinard <solomo...@chromium.org>

Solomon Kinard (Gerrit)

unread,
Jun 2, 2022, 1:22:18 PM6/2/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Devlin Cronin.

View Change

23 comments:

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • Patch Set #8, Line 32:

      SidePanelOptions GetOptionsFromValue(std::unique_ptr<base::Value> value) {
      base::Value::Dict dict = std::move(value->GetDict());
      const auto id = dict.FindInt("tabId");
      const auto* path = dict.FindString("path");
      const auto enabled = dict.FindBool("enabled");
      return SidePanelOptions(id, *path, enabled);
      }

    • 4) They do have a default ctor

    • ::Populate(base::Value) is the closest option that I noticed to what I had in mind wrt a default constructor that allows for arguments emplace.

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • Rather than returning a stub value, I think we should return an error in this case. […]

      Done

    • no need for . […]

      Done

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Done

    • Patch Set #10, Line 19:

      using TabId = int;
      using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;
      using PanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

      Can these live in the SidePanelService class?

    • Done

    • prefer absl::optional over unique_ptr to represent optionality (I know our generated types don't do […]

      Done

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #10, Line 30:

          base::Value::Dict dict;
      if (!path.empty()) {
      dict.Set("path", path);
      dict.Set("enabled", true);
      }
      api::side_panel::PanelOptions options;
      api::side_panel::PanelOptions::Populate(base::Value(std::move(dict)),
      &options);
      return options;

    • We shouldn't generate types from base::Value except for in (de)serialization. […]

      Done

    • We already do this lookup, so let's cache the result earlier. […]

      Done

    • Patch Set #10, Line 47:

          auto path = SidePanelInfo::GetDefaultPath(&extension);
      base::Value::Dict dict;
      if (!path.empty()) {
      dict.Set("path", path);
      dict.Set("enabled", true);
      }
      api::side_panel::PanelOptions options;
      api::side_panel::PanelOptions::Populate(base::Value(std::move(dict)),
      &options);
      return options;

    • This code is duplicated. […]

      Done

    • Patch Set #10, Line 61:

          auto dict = std::move((*it)[default_tab_id].ToValue()->GetDict());
      dict.Set("tabId", tab_id);
      api::side_panel::PanelOptions options;
      api::side_panel::PanelOptions::Populate(base::Value(std::move(dict)),
      &options);
      return options;

    • CloneOptions() has been locally created to make it cleaner. A copy has to be made regardless. A member variable was considered in addition to passing an option by reference from the api to the service. Neither was chosen because it adds more code without enough benefits to mitigate the downsides, imho.

    • This would require us storing the manifest-specified panel options

    • It seems like member storage could be racy and be harder to reason after while.

    • This ends up doing 3 different lookups into the map: […]

      Done

  • File chrome/common/extensions/api/side_panel.idl:

    • Patch Set #10, Line 27:


      dictionary RemoveOptions {
      // If specified, the side panel for the given tab will be removed.
      long? tabId;
      };

      no longer used in this CL

    • Done

    • Patch Set #10, Line 46:

          [supportsPromises] static void getOptions(GetPanelOptions options,
      PanelOptionsCallback callback);

    • As mentioned here [1], arguments either be aligned or all on the same line […]

      I wonder if there's a bug open for git cl format to handle this.

  • File chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc:

    • Done

  • File chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js:

    • let's call this "new_default. […]

      Done

    • Let's also add a case for retrieving the newly-set default when we try to fetch the options for a ta […]

      Done

    • Patch Set #10, Line 49:


      // Compare dictionary with a depth of 1.
      function compareObjects(obj1, obj2) {
      for (const [key, value] of Object.entries(obj1)) {
      if (!(key in obj2 && value == obj2[key]))
      return false;
      }
      return Object.keys(obj1).length == Object.keys(obj2).length;
      }

    • Sorry, maybe this comment [1] was unclear. Please use chrome.test. […]

      Done. I moved to a new machine during the time of the last upload, so anything could have happened along the way.

  • File extensions/common/api/_manifest_features.json:

    • Done

  • File extensions/common/api/side_panel.idl:

    • Patch Set #10, Line 5:

      // Namespace for the "side_panel" manifest key.
      [generate_error_messages] namespace sidePanel {
      dictionary SidePanel {
      // Developer specified path for side panel display.
      DOMString default_path;
      };

      dictionary ManifestKeys {
      SidePanel side_panel;
      };
      };

    • An API should generally live at one "layer" (i.e., either at //chrome or //extensions). […]

      Starting this yielded breaking changes such as [generated] side_panel_info.h not found and too few arguments, so it's not included in this patch set. That seems like an LSC (large scale change), so this patch aims to address all other resolved comments while considering which files to move into //c.

  • File extensions/common/manifest_handlers/side_panel_info.h:

    • Done

    • nit: I don't think this comment is necessary (since this goes for most ctors/dtors defined in a head […]

      Done

  • File extensions/common/manifest_handlers/side_panel_info.cc:

    • Patch Set #10, Line 48:

        auto gurl = extension->GetResourceURL(path);
      auto relative_path = file_util::ExtensionURLToRelativeFilePath(gurl);

    • This seems to take a relative path, turn it into a GURL, and then turn it into a path. […]

      Done

    • Patch Set #10, Line 78:

        if (extension->manifest_version() < 3) {
      *error =
      ErrorUtils::FormatErrorMessageUTF16(errors::kManifestMinimumError, "3");
      return false;
      }

    • This should be handled by our features system (with the addition of the min_manifest_version in the […]

      Removed. It seems like your message is worded that way. Also removed associated tests.

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 11
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Comment-Date: Thu, 02 Jun 2022 17:22:10 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Devlin Cronin <rdevlin...@chromium.org>
Comment-In-Reply-To: Solomon Kinard <solomo...@chromium.org>
Gerrit-MessageType: comment

Solomon Kinard (Gerrit)

unread,
Jun 2, 2022, 1:35:12 PM6/2/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Devlin Cronin.

View Change

1 comment:

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 11
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Comment-Date: Thu, 02 Jun 2022 17:35:05 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment

Devlin Cronin (Gerrit)

unread,
Jun 2, 2022, 9:33:06 PM6/2/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Solomon Kinard.

View Change

14 comments:

  • Patchset:

    • Patch Set #11:

      Thanks, Solomon! I wasn't able to take a thorough pass this time, given the size of the CL, but there are a few more comments here.

  • File chrome/browser/extensions/api/side_panel/side_panel_apitest.cc:

    • Patch Set #11, Line 31:

      // // Verify chrome.sidePanel behavior without permissions.
      // IN_PROC_BROWSER_TEST_F(SidePanelApiTest, PermissionMissing) {
      // ASSERT_TRUE(RunExtensionTest("side_panel/permission_missing")) << message_;
      // }

      // // Verify chrome.sidePanel.get behavior without side_panel manifest key.
      // IN_PROC_BROWSER_TEST_F(SidePanelApiTest, UndefinedManifestKey) {
      // ASSERT_TRUE(RunExtensionTest("side_panel/undefined_manifest_key"))
      // << message_;
      // }

      Do we want to keep these tests? (I think the undefined manifest key is at least valuable, and I'm not against keeping the permission missing - though it should be handled by the feature system.) If so, uncomment them?

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    •   using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;

    •   // TODO(1328645): Remove options for matching ExtensionId on uninstallation.
      using ExtensionPanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

      These type aliases, since they're only used in the private data members, should themselves be private.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #11, Line 28: path

      std::move(path)

    • Patch Set #11, Line 38: clone ?

      This should never fail. If you want to check it, we can make it a DCHECK, but I'd also be fine just directly returning it.

    • Patch Set #11, Line 33:


      api::side_panel::PanelOptions CloneOptions(
      const api::side_panel::PanelOptions& options) {
      auto clone = api::side_panel::PanelOptions::FromValue(
      base::Value(std::move(options.ToValue()->GetDict())));
      return clone ? std::move(*clone) : api::side_panel::PanelOptions();
      }

      It's a shame (but understandable) that we need this. Let's file a bug and add a TODO for our generated types to allow conditionally including a Clone() method for types with a given attribute.

    • Patch Set #11, Line 51: extensionPanelOptions

      c++ code uses snake_case_variable_names

    • Patch Set #11, Line 67: if (tab_id != default_tab_id && it->find(default_tab_id) != it->end()) {

      this logic seems incorrect. It says "if the tab id is not the default tab id (i.e., we're looking for a specific tab) and there is a value for the default tab id, return the default tab id" - but if we're looking for a specific tab, we should check if that's present first. Otherwise, this will return the default options if they're set, even if we have more specific options in the map.

    • Patch Set #11, Line 68: (*it)[default_tab_id]

      This results in a duplicate lookup for default_tab_id, as does the line on 74. Instead, we should re-use the existing iters.

    • Patch Set #11, Line 87:

        auto it = tab_options.find(tab_id);
      if (it == tab_options.end()) {
      panels_[extension.id()][tab_id] = std::move(options);

      these are also duplicate lookups in the panels_ map

  • File extensions/browser/extension_function_histogram_value.h:

  • File extensions/common/api/side_panel.idl:

    • Patch Set #10, Line 5:

      // Namespace for the "side_panel" manifest key.
      [generate_error_messages] namespace sidePanel {
      dictionary SidePanel {
      // Developer specified path for side panel display.
      DOMString default_path;
      };

      dictionary ManifestKeys {
      SidePanel side_panel;
      };
      };

    • Starting this yielded breaking changes such as [generated] side_panel_info. […]

      I'd like us to handle this in this CL, since it should only require modifying the files that are introduced here. Can you provide more detail about the errors you're seeing when you try to move them? (Shot in the dark: you will have to update all includes of the generated side_panel.h file to point to //chrome/common/extensions/api/side_panel/side_panel.h, and the old //extensions copy will still exist in your out dir if you don't remove it, so maybe there's a stale one there?)

  • File extensions/common/manifest_constants.h:

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 11
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Fri, 03 Jun 2022 01:32:52 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No

Solomon Kinard (Gerrit)

unread,
Jun 6, 2022, 5:22:11 PM6/6/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Devlin Cronin.

View Change

15 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_apitest.cc:

    • Patch Set #11, Line 31:

      // // Verify chrome.sidePanel behavior without permissions.
      // IN_PROC_BROWSER_TEST_F(SidePanelApiTest, PermissionMissing) {
      // ASSERT_TRUE(RunExtensionTest("side_panel/permission_missing")) << message_;
      // }

      // // Verify chrome.sidePanel.get behavior without side_panel manifest key.
      // IN_PROC_BROWSER_TEST_F(SidePanelApiTest, UndefinedManifestKey) {
      // ASSERT_TRUE(RunExtensionTest("side_panel/undefined_manifest_key"))
      // << message_;
      // }

    • Do we want to keep these tests? (I think the undefined manifest key is at least valuable, and I'm n […]

      Yep, debug upload oversight.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Patch Set #11, Line 34:

        using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;
      // TODO(1328645): Remove options for matching ExtensionId on uninstallation.
      using ExtensionPanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

    • These type aliases, since they're only used in the private data members, should themselves be privat […]

      Done

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    •     auto dict = std::move((*it)[default_tab_id].ToValue()->GetDict());
      dict.Set("tabId", tab_id);
      api::side_panel::PanelOptions options;
      api::side_panel::PanelOptions::Populate(base::Value(std::move(dict)),
      &options);
      return options;

    • CloneOptions() has been locally created to make it cleaner. A copy has to be made regardless. […]

      Ack

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Done

    • This should never fail. […]

      What about this annotation?
      ```
      // Creates a PanelOptions object from a base::Value, or NULL on failure.
      static std::unique_ptr<PanelOptions> FromValue(const base::Value& value);
      ```

    • Patch Set #11, Line 33:


      api::side_panel::PanelOptions CloneOptions(
      const api::side_panel::PanelOptions& options) {
      auto clone = api::side_panel::PanelOptions::FromValue(
      base::Value(std::move(options.ToValue()->GetDict())));
      return clone ? std::move(*clone) : api::side_panel::PanelOptions();
      }

    • It's a shame (but understandable) that we need this. […]

      Done

    • Done

    • this logic seems incorrect. It says "if the tab id is not the default tab id (i.e. […]

      A direct check has been added before this conditional, for clarity. The setAndGetPanel tests were already passing before this addition.

    • This results in a duplicate lookup for default_tab_id, as does the line on 74. […]

      Done

    • Patch Set #11, Line 87:

        auto it = tab_options.find(tab_id);
      if (it == tab_options.end()) {
      panels_[extension.id()][tab_id] = std::move(options);

      these are also duplicate lookups in the panels_ map

    • Done

  • File extensions/browser/extension_function_histogram_value.h:

    • Done

  • File extensions/common/api/side_panel.idl:

    • Patch Set #10, Line 5:

      // Namespace for the "side_panel" manifest key.
      [generate_error_messages] namespace sidePanel {
      dictionary SidePanel {
      // Developer specified path for side panel display.
      DOMString default_path;
      };

      dictionary ManifestKeys {
      SidePanel side_panel;
      };
      };

    • I'd like us to handle this in this CL, since it should only require modifying the files that are int […]

      idl, manifest, and features that already had a similarly named landing spot were moved from //e to //c.

  • File extensions/common/manifest_constants.h:

    • Done

    • Done

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 12
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Comment-Date: Mon, 06 Jun 2022 21:22:00 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No

Devlin Cronin (Gerrit)

unread,
Jun 8, 2022, 2:43:25 PM6/8/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Solomon Kinard.

View Change

17 comments:

  • Patchset:

    • Patch Set #16:

      Awesome, Solomon! This is looking really good. A few more comments, but mostly small.

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • Patch Set #16, Line 56: GetService()->SetOptions(*extension(), std::move(params->options));

      Not for this CL (since it's already very, very large), but flagging so we don't forget: we also need to validate the passed `path` is a relative path in the extension.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #11, Line 38: clone ?

      What about this annotation? […]

      It can fail if the value doesn't have the appropriate fields, which is completely possible when, say, parsing values passed in by extensions. However, in this case, the value we have here is directly created from a PanelOptions, so the value should *always* be a valid serialization of PanelOptions.

    • The setAndGetPanel tests were already passing before this addition.

      Yep, the test succeeded because at the time it's called, there isn't a default tab value set, which meant that we didn't enter this condition. The default tab id entry is later set in defaultSetAndGetPanel(), but then we never test again for a specific tab ID.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #16, Line 62: * it

      nit: prefer a reference over a pointer here (since it should never be null)

    • Patch Set #16, Line 64: auto default_panel_options = it->find(default_tab_id);

      nit: move this below the `panel_options != it->end()` check, since we otherwise don't need to do this lookup.

      Additionally, in the case where tab_id *is* default_tab_id, we've already done this lookup.

      Can we restructure the below to be:

      ```
      if (tab_id != default_tab_id) {
      auto specific_tab_options = it.find(tab_id);
      if (specific_tab_options != it.end()) {
      // return specific tab options
      }
      }
      // Fall back to the default tab if no tab ID
      // was specified or entries for the specific tab weren't found.
      auto default_options = it.find(default_tab_id);
      if (default_options != it.end()) {
      // return default tab options
      }

      // Fall back to the manifest-specified options as a last resort.
      // return manifest options
      ```

      That way, we do the minimum number of lookups into the map.

    • Patch Set #16, Line 70: options.tab_id = std::make_unique<int>(tab_id);

      we seem to be setting options.tab_id in some cases, but not all. Specifically, we set it to the extension-specified tab_id if we find either options for the specific tab or options for the default tab, but not if we fall back to the manifest. Is that desired? It seems strange that we're setting it for one default case (default tab id) but not the other (manifest specified)

    • Patch Set #16, Line 72: } else {

      nit: no `else` after `return` (though moot with comment above)

  • File chrome/common/extensions/api/side_panel.idl:

    •     [supportsPromises] static void getOptions(GetPanelOptions options,
      PanelOptionsCallback callback);

    • I wonder if there's a bug open for git cl format to handle this.

      Ack

  • File chrome/common/extensions/api/side_panel.idl:

    • Patch Set #16, Line 45: VoidCallback

      This should be "optional VoidCallback callback", since an extension may not care to specify a callback to setOptions(). (This is my bad; I mistyped this in the API proposal. I fixed it there just now.)

  • File chrome/common/extensions/api/side_panel/side_panel_info.cc:

  • File chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js:

    • Patch Set #16, Line 24: new_default

      nit: instead of `new_default`, let's call this `tab_specific.html` or similar. That way, we can verify that when we set a default value of `new_default` below, we're returning the right value. Otherwise, we can't tell if the service is returning the default or the tab-specific entry.

    • Patch Set #16, Line 32: setAndGetPanel

      nit: differentiate this test case name from the one above.

    • Patch Set #16, Line 51: defaultSetAndGetPanel

      nit: here, too, differentiate test names

    • Patch Set #16, Line 57: },

      let's add one final test that retrieves the old `tabId`'s options to validate that we get the right value for a specified tab ID even when there is a default tab ID value present.

  • File extensions/common/api/side_panel.idl:

    • Patch Set #10, Line 5:

      // Namespace for the "side_panel" manifest key.
      [generate_error_messages] namespace sidePanel {
      dictionary SidePanel {
      // Developer specified path for side panel display.
      DOMString default_path;
      };

      dictionary ManifestKeys {
      SidePanel side_panel;
      };
      };

    • idl, manifest, and features that already had a similarly named landing spot were moved from //e to / […]

      Perfect; thanks!

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 16
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Wed, 08 Jun 2022 18:43:18 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No

Solomon Kinard (Gerrit)

unread,
Jun 29, 2022, 3:36:52 PM6/29/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Devlin Cronin.

View Change

15 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_api.cc:

    • Not for this CL (since it's already very, very large), but flagging so we don't forget: we also need […]

      Done

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Done

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • It can fail if the value doesn't have the appropriate fields, which is completely possible when, say […]

      Done

    • > The setAndGetPanel tests were already passing before this addition. […]

      Ack

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Done

    • nit: move this below the `panel_options != it->end()` check, since we otherwise don't need to do thi […]

      Done

    • we seem to be setting options.tab_id in some cases, but not all. […]

      `chrome.sidePanel.getOptions({})` is an example case when it doesn't make sense to return a `tabId`.

    • Ack

  • File chrome/common/extensions/api/side_panel.idl:

    • This should be "optional VoidCallback callback", since an extension may not care to specify a callba […]

      Done

  • File chrome/common/extensions/api/side_panel/side_panel_info.cc:

    • Done

  • File chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js:

    • nit: instead of `new_default`, let's call this `tab_specific.html` or similar. […]

      Done

    • Done

    • Done

    • let's add one final test that retrieves the old `tabId`'s options to validate that we get the right […]

      Done

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 17
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Comment-Date: Wed, 29 Jun 2022 19:36:45 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No

Solomon Kinard (Gerrit)

unread,
Jun 29, 2022, 5:02:33 PM6/29/22
to Kelvin Jiang, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin

Attention is currently required from: Kelvin Jiang.

Solomon Kinard would like Kelvin Jiang to review this change.

View Change

Extensions: SidePanel: Create manifest key(s), API, and storage

Design Doc:
https://docs.google.com/document/d/1EjRghIJR1u1-UadYHdBhCCtY3A108LtEznSWzz7FtwE

Bug: 1328645
Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
---
M chrome/browser/extensions/BUILD.gn
A chrome/browser/extensions/api/side_panel/side_panel_api.cc
A chrome/browser/extensions/api/side_panel/side_panel_api.h
A chrome/browser/extensions/api/side_panel/side_panel_apitest.cc
A chrome/browser/extensions/api/side_panel/side_panel_service.cc
A chrome/browser/extensions/api/side_panel/side_panel_service.h
M chrome/browser/extensions/browser_context_keyed_service_factories.cc
M chrome/common/BUILD.gn
M chrome/common/extensions/api/_api_features.json
M chrome/common/extensions/api/_manifest_features.json

M chrome/common/extensions/api/_permission_features.json
M chrome/common/extensions/api/api_sources.gni
A chrome/common/extensions/api/side_panel.idl
A chrome/common/extensions/api/side_panel/side_panel_info.cc
A chrome/common/extensions/api/side_panel/side_panel_info.h
M chrome/common/extensions/chrome_manifest_handlers.cc

A chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc
M chrome/common/extensions/permissions/chrome_api_permissions.cc
M chrome/common/extensions/permissions/permission_set_unittest.cc
M chrome/test/BUILD.gn
A chrome/test/data/extensions/api_test/side_panel/extension/default_path.html
A chrome/test/data/extensions/api_test/side_panel/extension/manifest.json
A chrome/test/data/extensions/api_test/side_panel/extension/panel.html
A chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js
A chrome/test/data/extensions/api_test/side_panel/permission_missing/manifest.json
A chrome/test/data/extensions/api_test/side_panel/permission_missing/service_worker.js
A chrome/test/data/extensions/api_test/side_panel/undefined_manifest_key/manifest.json
A chrome/test/data/extensions/api_test/side_panel/undefined_manifest_key/panel.html
A chrome/test/data/extensions/api_test/side_panel/undefined_manifest_key/service_worker.js
M extensions/browser/extension_function_histogram_value.h

M extensions/common/extension_features.cc
M extensions/common/extension_features.h
M extensions/common/manifest.cc
M extensions/common/manifest_constants.cc
M extensions/common/manifest_constants.h
M extensions/common/mojom/api_permission_id.mojom
M tools/metrics/histograms/enums.xml
37 files changed, 821 insertions(+), 1 deletion(-)


To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 19
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-MessageType: newchange

Solomon Kinard (Gerrit)

unread,
Jun 29, 2022, 5:02:37 PM6/29/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Kelvin Jiang, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Kelvin Jiang.

View Change

1 comment:

  • Patchset:

    • Patch Set #19:

      Adding Kelvin to attention set based on a quick chat. Thanks Kelvin. Removing Devlin from attention set in case Kelvin has time to take a look? Thanks.

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 19
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Comment-Date: Wed, 29 Jun 2022 21:02:30 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment

Solomon Kinard (Gerrit)

unread,
Jun 30, 2022, 4:08:56 PM6/30/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Solomon Kinard abandoned this change.

View Change

Abandoned

To view, visit change 3736155. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I0d77cee6b782756b5a81fc1b02bb720b4121b56d
Gerrit-Change-Number: 3736155
Gerrit-PatchSet: 5
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-MessageType: abandon

Solomon Kinard (Gerrit)

unread,
Jun 30, 2022, 5:37:58 PM6/30/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Solomon Kinard restored this change.

View Change

To view, visit change 3736155. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I0d77cee6b782756b5a81fc1b02bb720b4121b56d
Gerrit-Change-Number: 3736155
Gerrit-PatchSet: 5
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-MessageType: restore

Kelvin Jiang (Gerrit)

unread,
Jun 30, 2022, 6:25:00 PM6/30/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

View Change

9 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_apitest.cc:

    • Patch Set #21, Line 37: UndefinedManifestKey

      tiny nit: `missing_manifest_key` may be may be a slightly more accurate name?

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    •   using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;

    •   using ExtensionPanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

    • Based on what this CL entails, I don't see TabPanelOptions existing outside of an ExtensionPanelOptions.

      Was the 2 level mapping here done so we can return `GetPanelOptionsFromManifest`/make checking easier ?

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #21, Line 52: // Maybe get default path if there are no records for a given extension_id.

      replace with TODO if this will be done in a follow up?

    • Patch Set #21, Line 65: specific_tab_options

      may need to take another pass but:

    • Patch Set #21, Line 65: return CloneOptions(specific_tab_options->second);

      maybe I'm just confused but: do we really need to Clone() here since we're probably copying the object anyway? or is this because said object has a bunch of unique_ptrs inside it that need to be cloned

  • File chrome/common/extensions/api/side_panel.idl:

  • File chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js:

    • Patch Set #21, Line 60: defaultSetAndGetPanelAgain

      nit: this is a duplicate function to what's above, maybe mention in the name that this is for a specific tab?

      defaultGetPanelForSpecificTab?

  • File chrome/test/data/extensions/api_test/side_panel/permission_missing/service_worker.js:

    • Patch Set #21, Line 7: chrome.test.assertEq(undefined, chrome.sidePanel);

      thanks for the coverage, I wonder if cases like these for other APIs are covered by a more specific test class/might this test be redundant?

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 21
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Comment-Date: Thu, 30 Jun 2022 22:24:52 +0000

Solomon Kinard (Gerrit)

unread,
Jun 30, 2022, 7:10:07 PM6/30/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Kelvin Jiang, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Kelvin Jiang.

View Change

9 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_apitest.cc:

    • Patch Set #21, Line 37: UndefinedManifestKey

      tiny nit: `missing_manifest_key` may be may be a slightly more accurate name?

    • Done

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Patch Set #21, Line 55:

        using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;
      using ExtensionPanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

    • Based on what this CL entails, I don't see TabPanelOptions existing outside of an ExtensionPanelOpti […]

      You're right that it might be unnecessary. LMK? ExtensionPanelOptions is only used explicitly once in this file and TabPanelOptions is only used twice in .cc. I may have added them thinking idealistically that it'd make the code easier to read with named complex-types.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #21, Line 52: // Maybe get default path if there are no records for a given extension_id.

      replace with TODO if this will be done in a follow up?

    • Wording updated.

    • It looks like your comment was cut off here.

  • File chrome/common/extensions/api/side_panel.idl:

    • hmm.jpg […]

      This probably came from the API Proposal. I don't have a preference. Devlin, any preference here?

  • File chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js:

    • nit: this is a duplicate function to what's above, maybe mention in the name that this is for a spec […]

      Done

  • File chrome/test/data/extensions/api_test/side_panel/permission_missing/service_worker.js:

    • thanks for the coverage, I wonder if cases like these for other APIs are covered by a more specific […]

      It would be okay to remove this `permission_missing` extension/test. I didn't know that we already had test coverage for this. LMK if you think we do and it can be deduplicated here?

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 22
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Comment-Date: Thu, 30 Jun 2022 23:09:55 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-MessageType: comment

Solomon Kinard (Gerrit)

unread,
Jul 1, 2022, 12:35:31 PM7/1/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Solomon Kinard abandoned this change.

View Change

Abandoned

To view, visit change 3736155. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I0d77cee6b782756b5a81fc1b02bb720b4121b56d
Gerrit-Change-Number: 3736155
Gerrit-PatchSet: 6
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-MessageType: abandon

Devlin Cronin (Gerrit)

unread,
Jul 1, 2022, 4:24:50 PM7/1/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Kelvin Jiang, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Kelvin Jiang, Solomon Kinard.

Patch set 23:Code-Review +1

View Change

6 comments:

  • Patchset:

    • Patch Set #23:

      This looks great, Solomon! Only real comment left is the one about tabId behavior when returning a default. Otherwise, LGTM!

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Patch Set #21, Line 55:

        using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;
      using ExtensionPanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

    • thinking idealistically that it'd make the code easier to read with named complex-types.

      I agree with this. I find these aliases make it much cleaner than inlining them all together. I'd keep the aliases.

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #16, Line 70: options.tab_id = std::make_unique<int>(tab_id);

      `chrome.sidePanel.getOptions({})` is an example case when it doesn't make sense to return a `tabId`.

      I agree with that, but we're being inconsistent in setting `tab_id` for different default cases.

      Consider:

      Case 1:

      • Extension has a manifest entry, but has not explicitly set default options via the API.
      • Extension calls `sidePanel.getOptions({tabId: 22});
      In this case, we'd return the manifest-specified options and `tabId` would be undefined.  The result would be something like:
      ```
      {
      enabled: true,
      path: 'panel.html',
      }
      ```

      Case 2:

      • Extension has a manifest entry and *has* explicitly set default options via the API (but hasn't set any specific tab options)
      • Extension calls `sidePanel.getOptions({tabId: 22});

      Here, we'd return an options *with* the tab ID specified. The result would be something like:

      ```
      {
      enabled: true,
      path: 'panel.html',
      tabId: 22,
      }
      ```

      Even though in both these cases, we return a default options value (and there's never a specific value for tabId 22), the second case has tabId set whereas the first does not. That seems inconsistent to me.

      How about we don't set tabId in either case where a default is used? That way, developers could tell whether an option is being applied to that specific tab (in which case tabId would be set) or if a default (from either the API or manifest) is being used.

      WDYT?

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • Patch Set #21, Line 65: return CloneOptions(specific_tab_options->second);

      You might be right. The following comment seems directly related to what you're asking […]

      We can't just return a const & to this here because we return a constructed object in other paths (and you can't return a temporary as a const &), and the generated types have their copy ctors deleted so we need an explicit Clone() method.

      One way to get around that (as mentioned in the comment Solomon linked) is to have a static "empty options" that we can return in those cases; the other way is to return by value and copy the object in other cases (which is what this CL does). I don't have a strong preference either way, so I'd kinda default to the one that's written : )

  • File chrome/common/extensions/api/side_panel.idl:

    • This probably came from the API Proposal. I don't have a preference. […]

      Sorry, I don't follow - what do you mean "as a constant"?

      (This entry allows us to use the generated types in order to do parsing of the manifest key)

  • File chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc:

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 23
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Fri, 01 Jul 2022 20:24:39 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Comment-In-Reply-To: Kelvin Jiang <kelvi...@chromium.org>

Solomon Kinard (Gerrit)

unread,
Jul 11, 2022, 2:22:43 PM7/11/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Kelvin Jiang, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Kelvin Jiang.

View Change

4 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • How about we don't set tabId in either case where a default is used? That way, developers could tell whether an option is being applied to that specific tab (in which case tabId would be set) or if a default (from either the API or manifest) is being used.

      Done.

  • File chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc:

    •   if (extension->manifest_version() < 3) {
      *error =
      ErrorUtils::FormatErrorMessageUTF16(errors::kManifestMinimumError, "3");
      return false;
      }

    • Removed. It seems like your message is worded that way. Also removed associated tests.

      Done

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 25
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Comment-Date: Mon, 11 Jul 2022 18:22:21 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No

Solomon Kinard (Gerrit)

unread,
Jul 11, 2022, 2:27:45 PM7/11/22
to Alex Gough, David Trainor, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Devlin Cronin, Kelvin Jiang

Attention is currently required from: Alex Gough, David Trainor, Kelvin Jiang.

Solomon Kinard would like Alex Gough and David Trainor to review this change.

View Change

Extensions: SidePanel: Create manifest key(s), API, and storage

Design Doc:
https://docs.google.com/document/d/1EjRghIJR1u1-UadYHdBhCCtY3A108LtEznSWzz7FtwE

Bug: 1328645
Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
---
M chrome/browser/extensions/BUILD.gn
A chrome/browser/extensions/api/side_panel/side_panel_api.cc
A chrome/browser/extensions/api/side_panel/side_panel_api.h
A chrome/browser/extensions/api/side_panel/side_panel_apitest.cc
A chrome/browser/extensions/api/side_panel/side_panel_service.cc
A chrome/browser/extensions/api/side_panel/side_panel_service.h
M chrome/browser/extensions/browser_context_keyed_service_factories.cc
M chrome/browser/profiles/profile_keyed_service_browsertest.cc

M chrome/common/BUILD.gn
M chrome/common/extensions/api/_api_features.json
M chrome/common/extensions/api/_manifest_features.json
M chrome/common/extensions/api/_permission_features.json
M chrome/common/extensions/api/api_sources.gni
A chrome/common/extensions/api/side_panel.idl
A chrome/common/extensions/api/side_panel/side_panel_info.cc
A chrome/common/extensions/api/side_panel/side_panel_info.h
M chrome/common/extensions/chrome_manifest_handlers.cc
A chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc
M chrome/common/extensions/permissions/chrome_api_permissions.cc
M chrome/common/extensions/permissions/permission_set_unittest.cc
M chrome/test/BUILD.gn
A chrome/test/data/extensions/api_test/side_panel/extension/default_path.html
A chrome/test/data/extensions/api_test/side_panel/extension/manifest.json
A chrome/test/data/extensions/api_test/side_panel/extension/panel.html
A chrome/test/data/extensions/api_test/side_panel/extension/service_worker.js
A chrome/test/data/extensions/api_test/side_panel/missing_manifest_key/manifest.json
A chrome/test/data/extensions/api_test/side_panel/missing_manifest_key/service_worker.js
A chrome/test/data/extensions/api_test/side_panel/permission_missing/manifest.json
A chrome/test/data/extensions/api_test/side_panel/permission_missing/service_worker.js

M extensions/browser/extension_function_histogram_value.h
M extensions/common/extension_features.cc
M extensions/common/extension_features.h
M extensions/common/manifest.cc
M extensions/common/manifest_constants.cc
M extensions/common/manifest_constants.h
M extensions/common/mojom/api_permission_id.mojom
M tools/metrics/histograms/enums.xml
37 files changed, 809 insertions(+), 1 deletion(-)


To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 25
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Alex Gough <aj...@chromium.org>
Gerrit-Attention: David Trainor <dtra...@chromium.org>

Solomon Kinard (Gerrit)

unread,
Jul 11, 2022, 2:28:21 PM7/11/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, David Trainor, Alex Gough, Devlin Cronin, Kelvin Jiang, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Alex Gough, David Trainor, Kelvin Jiang.

View Change

1 comment:

  • Patchset:

    • Patch Set #25:

      Can specific file owners take a look?
      +dtrainor: profile_keyed_service_browsertest.cc
      +ajgo: api_permission_id.mojom

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 25
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Alex Gough <aj...@chromium.org>
Gerrit-Attention: David Trainor <dtra...@chromium.org>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Comment-Date: Mon, 11 Jul 2022 18:27:42 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment

Alex Gough (Gerrit)

unread,
Jul 11, 2022, 2:51:13 PM7/11/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Alex Gough, David Trainor, Devlin Cronin, Kelvin Jiang, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: David Trainor, Kelvin Jiang, Solomon Kinard.

Patch set 25:Code-Review +1

View Change

1 comment:

  • Patchset:

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 25
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: David Trainor <dtra...@chromium.org>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Mon, 11 Jul 2022 18:50:51 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Gerrit-MessageType: comment

David Trainor (Gerrit)

unread,
Jul 12, 2022, 1:02:06 PM7/12/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Alex Gough, Devlin Cronin, Kelvin Jiang, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Kelvin Jiang, Solomon Kinard.

Patch set 26:Code-Review +1

View Change

1 comment:

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 26
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Tue, 12 Jul 2022 17:01:57 +0000

Kelvin Jiang (Gerrit)

unread,
Jul 12, 2022, 7:14:59 PM7/12/22
to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, David Trainor, Alex Gough, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Solomon Kinard.

Patch set 26:Code-Review +1

View Change

6 comments:

  • Patchset:

  • File chrome/browser/extensions/api/side_panel/side_panel_service.h:

    • Patch Set #21, Line 55:

        using TabPanelOptions = base::flat_map<TabId, api::side_panel::PanelOptions>;
      using ExtensionPanelOptions = base::flat_map<ExtensionId, TabPanelOptions>;

      > thinking idealistically that it'd make the code easier to read with named complex-types. […]

    • I was thinking instead of using something like `base::flatmap<pair<ExtensionId, TabId>, PanelOptions>` but it's probably overkill in this case

  • File chrome/browser/extensions/api/side_panel/side_panel_service.cc:

    • It looks like your comment was cut off here.

    • oops, this was from another tab and I forgot I had this draft... (resolving)

    • We can't just return a const & to this here because we return a constructed object in other paths (a […]

      I'm fine with just copying the object (cloning)

  • File chrome/common/extensions/api/side_panel.idl:

    • Sorry, I don't follow - what do you mean "as a constant"? […]

      ^oh I see. was thinking if we could just have a constant in a .h file instead of adding it again here

      (resolving comment)

  • File chrome/test/data/extensions/api_test/side_panel/permission_missing/service_worker.js:

    • It would be okay to remove this `permission_missing` extension/test. […]

      Not sure... this was just a guess based on the existence if `_api_features.json`, I'm fine with leaving this test in.

      @Devlin, do you know which tests would cover what we list in `_api_features.json` for permissions?

To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
Gerrit-Change-Number: 3652544
Gerrit-PatchSet: 26
Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
Gerrit-Comment-Date: Tue, 12 Jul 2022 23:14:50 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes

Solomon Kinard (Gerrit)

unread,
Jul 13, 2022, 11:38:13 AM7/13/22
to asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Kelvin Jiang, David Trainor, Alex Gough, Devlin Cronin, Tricium, Chromium LUCI CQ, Chromium Metrics Reviews, chromium...@chromium.org

Attention is currently required from: Devlin Cronin, Solomon Kinard.

Patch set 28:Commit-Queue +2

View Change

    To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
    Gerrit-Change-Number: 3652544
    Gerrit-PatchSet: 28
    Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
    Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
    Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
    Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
    Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
    Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
    Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
    Gerrit-Attention: Solomon Kinard <solomo...@chromium.org>
    Gerrit-Attention: Devlin Cronin <rdevlin...@chromium.org>
    Gerrit-Comment-Date: Wed, 13 Jul 2022 15:38:02 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    Gerrit-MessageType: comment

    Chromium LUCI CQ (Gerrit)

    unread,
    Jul 13, 2022, 2:07:14 PM7/13/22
    to Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Kelvin Jiang, David Trainor, Alex Gough, Devlin Cronin, Tricium, Chromium Metrics Reviews, chromium...@chromium.org

    Chromium LUCI CQ submitted this change.

    View Change



    26 is the latest approved patch-set.
    The change was submitted with unreviewed changes in the following files:

    ```
    The name of the file: tools/metrics/histograms/enums.xml
    Insertions: 4, Deletions: 2.

    The diff is too large to show. Please review the diff.
    ```
    ```
    The name of the file: extensions/common/extension_features.h
    Insertions: 2, Deletions: 0.

    The diff is too large to show. Please review the diff.
    ```
    ```
    The name of the file: extensions/common/extension_features.cc
    Insertions: 8, Deletions: 0.

    The diff is too large to show. Please review the diff.
    ```
    ```
    The name of the file: extensions/browser/extension_function_histogram_value.h
    Insertions: 4, Deletions: 2.

    The diff is too large to show. Please review the diff.
    ```

    Approvals: Solomon Kinard: Commit Kelvin Jiang: Looks good to me David Trainor: Looks good to me Devlin Cronin: Looks good to me Alex Gough: Looks good to me
    Extensions: SidePanel: Create manifest key(s), API, and storage

    Design Doc:
    https://docs.google.com/document/d/1EjRghIJR1u1-UadYHdBhCCtY3A108LtEznSWzz7FtwE

    Bug: 1328645
    Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3652544
    Reviewed-by: Devlin Cronin <rdevlin...@chromium.org>
    Reviewed-by: Alex Gough <aj...@chromium.org>
    Reviewed-by: Kelvin Jiang <kelvi...@chromium.org>
    Commit-Queue: Solomon Kinard <solomo...@chromium.org>
    Reviewed-by: David Trainor <dtra...@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#1023830}
    37 files changed, 816 insertions(+), 1 deletion(-)


    To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
    Gerrit-Change-Number: 3652544
    Gerrit-PatchSet: 29
    Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
    Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
    Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
    Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
    Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
    Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
    Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
    Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
    Gerrit-MessageType: merged

    Devlin Cronin (Gerrit)

    unread,
    Jul 13, 2022, 2:22:04 PM7/13/22
    to Chromium LUCI CQ, Solomon Kinard, asvitkine...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ipc-securi...@chromium.org, Kelvin Jiang, David Trainor, Alex Gough, Devlin Cronin, Tricium, Chromium Metrics Reviews, chromium...@chromium.org

    View Change

    1 comment:

    • File chrome/test/data/extensions/api_test/side_panel/permission_missing/service_worker.js:

      • Not sure... this was just a guess based on the existence if `_api_features. […]

        Following up here, this exercises the basic features and bindings system, which, depending on the level you're interested in, is tested in extension_bindings_apitest.cc, native_bindings_apitest.cc, simple/complex_feature_unittest.cc, and a few others. Those test that features are unavailable under certain conditions. What they _don't_ test is that the definition for side panel in _api_features.json is properly entered (i.e., lists the dependency on the permission), and that's exercised by this. We don't usually require that (because the definitions in features.json are usually fairly straightforward and may generate compile / runtime errors if malformed), but it never hurts : )

    To view, visit change 3652544. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Ic6cae327ac911b48a1ef9cb069f9efbd80bfd80a
    Gerrit-Change-Number: 3652544
    Gerrit-PatchSet: 29
    Gerrit-Owner: Solomon Kinard <solomo...@chromium.org>
    Gerrit-Reviewer: Alex Gough <aj...@chromium.org>
    Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
    Gerrit-Reviewer: David Trainor <dtra...@chromium.org>
    Gerrit-Reviewer: Devlin Cronin <rdevlin...@chromium.org>
    Gerrit-Reviewer: Kelvin Jiang <kelvi...@chromium.org>
    Gerrit-Reviewer: Solomon Kinard <solomo...@chromium.org>
    Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
    Gerrit-Comment-Date: Wed, 13 Jul 2022 18:21:52 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Kelvin Jiang <kelvi...@chromium.org>
    Comment-In-Reply-To: Solomon Kinard <solomo...@chromium.org>
    Gerrit-MessageType: comment
    Reply all
    Reply to author
    Forward
    0 new messages