ash: Dismantle the document_scan crosapi service, part 2 [chromium/src : main]

0 views
Skip to first unread message

Georg Neis (Gerrit)

unread,
Mar 31, 2026, 4:00:16 AM (2 days ago) Mar 31
to Hidehiko Abe, Chromium LUCI CQ, chromium...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ffred...@chromium.org, gavinwill+sc...@chromium.org, ipc-securi...@chromium.org, oshima...@chromium.org, tluk+...@chromium.org
Attention needed from Hidehiko Abe

Georg Neis voted and added 6 comments

Votes added by Georg Neis

Commit-Queue+1

6 comments

File chrome/browser/extensions/api/document_scan/document_scan_api_handler.h
Line 34, Patchset 4 (Parent):class CancelScanResponse;
Georg Neis . unresolved

This was unused.

File chrome/browser/extensions/api/document_scan/document_scan_apitest.cc
Line 132, Patchset 4: lorgnette::OPERATION_RESULT_SUCCESS, std::move(config));
Georg Neis . unresolved

See the deleted FakeDocumentScanAsh::GetOptionGroups.

File chrome/browser/extensions/api/document_scan/document_scan_type_converters.h
Line 24, Patchset 4: const lorgnette::CancelScanResponse& response);
Georg Neis . unresolved

dito

Line 21, Patchset 4: lorgnette::OperationResult result);
Georg Neis . unresolved

This was accidentally still using the mojo machinery and in the mojo namespace.

File chrome/browser/extensions/api/document_scan/document_scan_type_converters.cc
Line 54, Patchset 4:}
Georg Neis . unresolved

moved only, no code change

Line 62, Patchset 4:}
Georg Neis . unresolved

dito

Open in Gerrit

Related details

Attention is currently required from:
  • Hidehiko Abe
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I4eb5c268d02224fb5b3ab86cce443192fa0d35d2
Gerrit-Change-Number: 7714058
Gerrit-PatchSet: 5
Gerrit-Owner: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Hidehiko Abe <hide...@chromium.org>
Gerrit-Attention: Hidehiko Abe <hide...@chromium.org>
Gerrit-Comment-Date: Tue, 31 Mar 2026 07:59:51 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Hidehiko Abe (Gerrit)

unread,
Apr 1, 2026, 10:08:54 PM (17 hours ago) Apr 1
to Georg Neis, Chromium LUCI CQ, chromium...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ffred...@chromium.org, gavinwill+sc...@chromium.org, ipc-securi...@chromium.org, oshima...@chromium.org, tluk+...@chromium.org
Attention needed from Georg Neis

Hidehiko Abe voted and added 4 comments

Votes added by Hidehiko Abe

Code-Review+1

4 comments

Patchset-level comments
File-level comment, Patchset 5 (Latest):
Hidehiko Abe . resolved

LGTM

File chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.cc
Line 357, Patchset 5 (Latest): std::optional<lorgnette::OperationResult> result,
std::optional<lorgnette::ScannerConfig> config) {
get_current_config_result_ = std::move(result);
get_current_config_config_ = std::move(config);
Hidehiko Abe . unresolved

nit: `SetGetCurrentConfigResponse` now sounds a bit tricky name, because this does not directly set GetCurrentConfigResponse (but set some values to construct the response).

Could you either:

  • change the name to reflect your conceptual change, i.e., configure the (fake) manager with the given scanne rconfig, or
  • undo to have optional<GetCurrentConfigResponse> as an argument, and construct the protobuf in callers?
File chrome/browser/extensions/api/document_scan/document_scan_api_handler.h
Line 34, Patchset 4 (Parent):class CancelScanResponse;
Georg Neis . resolved

This was unused.

Hidehiko Abe

Acknowledged

File chrome/browser/extensions/api/document_scan/document_scan_apitest.cc
Line 132, Patchset 4: lorgnette::OPERATION_RESULT_SUCCESS, std::move(config));
Georg Neis . resolved

See the deleted FakeDocumentScanAsh::GetOptionGroups.

Hidehiko Abe

Acknowledged

Open in Gerrit

Related details

Attention is currently required from:
  • Georg Neis
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I4eb5c268d02224fb5b3ab86cce443192fa0d35d2
Gerrit-Change-Number: 7714058
Gerrit-PatchSet: 5
Gerrit-Owner: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Hidehiko Abe <hide...@chromium.org>
Gerrit-Attention: Georg Neis <ne...@chromium.org>
Gerrit-Comment-Date: Thu, 02 Apr 2026 02:08:27 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Comment-In-Reply-To: Georg Neis <ne...@chromium.org>
satisfied_requirement
unsatisfied_requirement
open
diffy

Georg Neis (Gerrit)

unread,
Apr 1, 2026, 10:15:32 PM (17 hours ago) Apr 1
to Hidehiko Abe, Chromium LUCI CQ, chromium...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ffred...@chromium.org, gavinwill+sc...@chromium.org, ipc-securi...@chromium.org, oshima...@chromium.org, tluk+...@chromium.org
Attention needed from Hidehiko Abe

Georg Neis added 1 comment

File chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.cc
Line 357, Patchset 5 (Latest): std::optional<lorgnette::OperationResult> result,
std::optional<lorgnette::ScannerConfig> config) {
get_current_config_result_ = std::move(result);
get_current_config_config_ = std::move(config);
Hidehiko Abe . unresolved

nit: `SetGetCurrentConfigResponse` now sounds a bit tricky name, because this does not directly set GetCurrentConfigResponse (but set some values to construct the response).

Could you either:

  • change the name to reflect your conceptual change, i.e., configure the (fake) manager with the given scanne rconfig, or
  • undo to have optional<GetCurrentConfigResponse> as an argument, and construct the protobuf in callers?
Georg Neis

Hmm I don't understand the concern. Yes we don't pass the whole response but we do pass the components that fully determine the response, because by contract the scanner handle is always the one from the corresponding request: https://source.chromium.org/chromium/chromium/src/+/main:third_party/cros_system_api/dbus/lorgnette/lorgnette_service.proto;l=725;drc=c6a2b6946d14688c4e54506227e03714e374b000
(I.e. the previous SetGetCurrentConfigResponse unnecessarily allowed constructing invalid responses.)

Open in Gerrit

Related details

Attention is currently required from:
  • Hidehiko Abe
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I4eb5c268d02224fb5b3ab86cce443192fa0d35d2
Gerrit-Change-Number: 7714058
Gerrit-PatchSet: 5
Gerrit-Owner: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Hidehiko Abe <hide...@chromium.org>
Gerrit-Attention: Hidehiko Abe <hide...@chromium.org>
Gerrit-Comment-Date: Thu, 02 Apr 2026 02:15:05 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Hidehiko Abe <hide...@chromium.org>
satisfied_requirement
unsatisfied_requirement
open
diffy

Hidehiko Abe (Gerrit)

unread,
4:49 AM (10 hours ago) 4:49 AM
to Georg Neis, Chromium LUCI CQ, chromium...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ffred...@chromium.org, gavinwill+sc...@chromium.org, ipc-securi...@chromium.org, oshima...@chromium.org, tluk+...@chromium.org
Attention needed from Georg Neis

Hidehiko Abe voted and added 1 comment

Votes added by Hidehiko Abe

Code-Review+1

1 comment

File chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.cc
Line 357, Patchset 5: std::optional<lorgnette::OperationResult> result,

std::optional<lorgnette::ScannerConfig> config) {
get_current_config_result_ = std::move(result);
get_current_config_config_ = std::move(config);
Hidehiko Abe . unresolved

nit: `SetGetCurrentConfigResponse` now sounds a bit tricky name, because this does not directly set GetCurrentConfigResponse (but set some values to construct the response).

Could you either:

  • change the name to reflect your conceptual change, i.e., configure the (fake) manager with the given scanne rconfig, or
  • undo to have optional<GetCurrentConfigResponse> as an argument, and construct the protobuf in callers?
Georg Neis

Hmm I don't understand the concern. Yes we don't pass the whole response but we do pass the components that fully determine the response, because by contract the scanner handle is always the one from the corresponding request: https://source.chromium.org/chromium/chromium/src/+/main:third_party/cros_system_api/dbus/lorgnette/lorgnette_service.proto;l=725;drc=c6a2b6946d14688c4e54506227e03714e374b000
(I.e. the previous SetGetCurrentConfigResponse unnecessarily allowed constructing invalid responses.)

Hidehiko Abe

Sorry for miscommunication. My point was:

The method name looks like a simple setter, as its name is prefixed with "Set", and actually, the original code did so. The simple setter is to take the value directly, and store it in the member.

Now, with your change, it's no longer true. It does not take the value to be directly set to "get_current_config_resposne_".

Now, I'd interpret the method is to configure the fake manager to hold the specified scanner config. I think it is fine, moreover a good change to a good direction, assuming "all" fake manager will respect the scanner config when needed later (not necessary in this CL) . GetCurrentConfig() in this CL looks like a first step towards to the direction to me. It is a simple method, returning the scanner config of the configured scanner config, so it makes sense to return the value set from here.
In the sense, it no longer makes sense to keep the name "SetGetCurrentConfigResponse".

My suggestion is:

  • If you'd like to keep this as a simple setter to configure the return value of GetCurrentConfig() directly, it should be the original form.
  • If you'd like to move towards to the direction of my interpretation described above, please do not name it "SetGetCurrentConfigResponse" because it should no longer be so.
  • If you have different design, please let me know. I'm open for the discussion of course :-)
Open in Gerrit

Related details

Attention is currently required from:
  • Georg Neis
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I4eb5c268d02224fb5b3ab86cce443192fa0d35d2
Gerrit-Change-Number: 7714058
Gerrit-PatchSet: 6
Gerrit-Owner: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Georg Neis <ne...@chromium.org>
Gerrit-Reviewer: Hidehiko Abe <hide...@chromium.org>
Gerrit-Attention: Georg Neis <ne...@chromium.org>
Gerrit-Comment-Date: Thu, 02 Apr 2026 08:48:29 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Comment-In-Reply-To: Georg Neis <ne...@chromium.org>
Comment-In-Reply-To: Hidehiko Abe <hide...@chromium.org>
satisfied_requirement
unsatisfied_requirement
open
diffy

Georg Neis (Gerrit)

unread,
5:19 AM (10 hours ago) 5:19 AM
to Hidehiko Abe, Chromium LUCI CQ, chromium...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ffred...@chromium.org, gavinwill+sc...@chromium.org, ipc-securi...@chromium.org, oshima...@chromium.org, tluk+...@chromium.org

Georg Neis voted and added 5 comments

Votes added by Georg Neis

Commit-Queue+2

5 comments

File chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.cc
Line 357, Patchset 5: std::optional<lorgnette::OperationResult> result,
std::optional<lorgnette::ScannerConfig> config) {
get_current_config_result_ = std::move(result);
get_current_config_config_ = std::move(config);
Hidehiko Abe . resolved

nit: `SetGetCurrentConfigResponse` now sounds a bit tricky name, because this does not directly set GetCurrentConfigResponse (but set some values to construct the response).

Could you either:

  • change the name to reflect your conceptual change, i.e., configure the (fake) manager with the given scanne rconfig, or
  • undo to have optional<GetCurrentConfigResponse> as an argument, and construct the protobuf in callers?
Georg Neis

Hmm I don't understand the concern. Yes we don't pass the whole response but we do pass the components that fully determine the response, because by contract the scanner handle is always the one from the corresponding request: https://source.chromium.org/chromium/chromium/src/+/main:third_party/cros_system_api/dbus/lorgnette/lorgnette_service.proto;l=725;drc=c6a2b6946d14688c4e54506227e03714e374b000
(I.e. the previous SetGetCurrentConfigResponse unnecessarily allowed constructing invalid responses.)

Hidehiko Abe

Sorry for miscommunication. My point was:

The method name looks like a simple setter, as its name is prefixed with "Set", and actually, the original code did so. The simple setter is to take the value directly, and store it in the member.

Now, with your change, it's no longer true. It does not take the value to be directly set to "get_current_config_resposne_".

Now, I'd interpret the method is to configure the fake manager to hold the specified scanner config. I think it is fine, moreover a good change to a good direction, assuming "all" fake manager will respect the scanner config when needed later (not necessary in this CL) . GetCurrentConfig() in this CL looks like a first step towards to the direction to me. It is a simple method, returning the scanner config of the configured scanner config, so it makes sense to return the value set from here.
In the sense, it no longer makes sense to keep the name "SetGetCurrentConfigResponse".

My suggestion is:

  • If you'd like to keep this as a simple setter to configure the return value of GetCurrentConfig() directly, it should be the original form.
  • If you'd like to move towards to the direction of my interpretation described above, please do not name it "SetGetCurrentConfigResponse" because it should no longer be so.
  • If you have different design, please let me know. I'm open for the discussion of course :-)
Georg Neis

Renamed to Configure*

File chrome/browser/extensions/api/document_scan/document_scan_type_converters.h
Line 24, Patchset 4: const lorgnette::CancelScanResponse& response);
Georg Neis . resolved

dito

Georg Neis

Acknowledged

Line 21, Patchset 4: lorgnette::OperationResult result);
Georg Neis . resolved

This was accidentally still using the mojo machinery and in the mojo namespace.

Georg Neis

Acknowledged

File chrome/browser/extensions/api/document_scan/document_scan_type_converters.cc
Line 54, Patchset 4:}
Georg Neis . resolved

moved only, no code change

Georg Neis

Acknowledged

Line 62, Patchset 4:}
Georg Neis . resolved

dito

Georg Neis

Acknowledged

Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement satisfiedCode-Owners
    • requirement satisfiedCode-Review
    • requirement satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: I4eb5c268d02224fb5b3ab86cce443192fa0d35d2
    Gerrit-Change-Number: 7714058
    Gerrit-PatchSet: 7
    Gerrit-Owner: Georg Neis <ne...@chromium.org>
    Gerrit-Reviewer: Georg Neis <ne...@chromium.org>
    Gerrit-Reviewer: Hidehiko Abe <hide...@chromium.org>
    Gerrit-Comment-Date: Thu, 02 Apr 2026 09:19:18 +0000
    satisfied_requirement
    open
    diffy

    Chromium LUCI CQ (Gerrit)

    unread,
    6:07 AM (9 hours ago) 6:07 AM
    to Georg Neis, Hidehiko Abe, chromium...@chromium.org, chromium-a...@chromium.org, extension...@chromium.org, ffred...@chromium.org, gavinwill+sc...@chromium.org, ipc-securi...@chromium.org, oshima...@chromium.org, tluk+...@chromium.org

    Chromium LUCI CQ submitted the change with unreviewed changes

    Unreviewed changes

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

    ```
    The name of the file: chrome/browser/extensions/api/document_scan/document_scan_apitest.cc
    Insertions: 1, Deletions: 1.

    @@ -128,7 +128,7 @@
    group->set_title("title");
    group->add_members("item1");
    group->add_members("item2");
    - lorgnette_manager->SetGetCurrentConfigResponse(
    + lorgnette_manager->ConfigureGetCurrentConfigResponse(
    lorgnette::OPERATION_RESULT_SUCCESS, std::move(config));
    }

    ```
    ```
    The name of the file: chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.h
    Insertions: 5, Deletions: 4.

    @@ -80,10 +80,11 @@
    void SetSetOptionsResponse(
    const std::optional<lorgnette::SetOptionsResponse>& response);

    - // Sets the response returned by GetCurrentConfig(), modulo the scanner, which
    - // will be taken from the request. If `result` has no value, the response
    - // will be nullopt (that's the default).
    - void SetGetCurrentConfigResponse(
    + // Configures the response returned by GetCurrentConfig().
    + // If `result` has no value, the response will be nullopt (that's the
    + // default). Otherwise, the response will consist of the given values and the
    + // scanner from the request.
    + void ConfigureGetCurrentConfigResponse(

    std::optional<lorgnette::OperationResult> result,
           std::optional<lorgnette::ScannerConfig> config);

    ```
    ```
    The name of the file: chrome/browser/extensions/api/document_scan/document_scan_api_handler_unittest.cc
    Insertions: 2, Deletions: 2.

    @@ -750,7 +750,7 @@
    const std::string scanner_id = CreateScannerIdForExtension(extension_);
    ASSERT_FALSE(scanner_id.empty());

    - GetLorgnetteScannerManager()->SetGetCurrentConfigResponse(
    + GetLorgnetteScannerManager()->ConfigureGetCurrentConfigResponse(
    lorgnette::OPERATION_RESULT_SUCCESS, std::nullopt);

    // The first open succeeds because the scanner is not open.
    @@ -819,7 +819,7 @@
    lorgnette::OptionGroup* group = config.add_option_groups();
    group->set_title("group-title");
    group->add_members("group-member");
    - GetLorgnetteScannerManager()->SetGetCurrentConfigResponse(
    + GetLorgnetteScannerManager()->ConfigureGetCurrentConfigResponse(
    lorgnette::OPERATION_RESULT_SUCCESS, std::move(config));

    GetOptionGroupsFuture future;
    ```
    ```
    The name of the file: chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.cc
    Insertions: 1, Deletions: 1.

    @@ -353,7 +353,7 @@
    set_options_response_ = response;
    }

    -void FakeLorgnetteScannerManager::SetGetCurrentConfigResponse(
    +void FakeLorgnetteScannerManager::ConfigureGetCurrentConfigResponse(

    std::optional<lorgnette::OperationResult> result,
    std::optional<lorgnette::ScannerConfig> config) {
    get_current_config_result_ = std::move(result);
    ```

    Change information

    Commit message:
    ash: Dismantle the document_scan crosapi service, part 2

    Migrate DocumentScanAPIHandler::GetOptionGroups to call
    ash::LorgnetteScannerManager directly instead of using the crosapi
    service, and remove the GetOptionGroups from the latter.
    This is an incremental step in eliminating the document_scan crosapi
    service.
    Test: unit_tests --gtest_filter="DocumentScanAPIHandlerTest.*:ScanServiceTest.*"
    Test: browser_tests --gtest_filter="DocumentScanApiTest.*"
    Bug: b:365902693, b:479031241, b:365741912
    Change-Id: I4eb5c268d02224fb5b3ab86cce443192fa0d35d2
    Commit-Queue: Georg Neis <ne...@chromium.org>
    Reviewed-by: Hidehiko Abe <hide...@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#1609076}
    Files:
    • M chrome/browser/ash/crosapi/document_scan_ash.cc
    • M chrome/browser/ash/crosapi/document_scan_ash.h
    • M chrome/browser/ash/crosapi/document_scan_ash_type_converters.cc
    • M chrome/browser/ash/crosapi/document_scan_ash_type_converters.h
    • M chrome/browser/ash/crosapi/document_scan_ash_type_converters_unittest.cc
    • M chrome/browser/ash/crosapi/document_scan_ash_unittest.cc
    • M chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.cc
    • M chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.h
    • M chrome/browser/extensions/api/document_scan/document_scan_api_handler.cc
    • M chrome/browser/extensions/api/document_scan/document_scan_api_handler.h
    • M chrome/browser/extensions/api/document_scan/document_scan_api_handler_unittest.cc
    • M chrome/browser/extensions/api/document_scan/document_scan_apitest.cc
    • M chrome/browser/extensions/api/document_scan/document_scan_type_converters.cc
    • M chrome/browser/extensions/api/document_scan/document_scan_type_converters.h
    • M chrome/browser/extensions/api/document_scan/document_scan_type_converters_unittest.cc
    • M chrome/browser/extensions/api/document_scan/fake_document_scan_ash.cc
    • M chrome/browser/extensions/api/document_scan/fake_document_scan_ash.h
    • M chromeos/crosapi/mojom/document_scan.mojom
    Change size: L
    Delta: 18 files changed, 215 insertions(+), 298 deletions(-)
    Branch: refs/heads/main
    Submit Requirements:
    • requirement satisfiedCode-Review: +1 by Hidehiko Abe
    Open in Gerrit
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: merged
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: I4eb5c268d02224fb5b3ab86cce443192fa0d35d2
    Gerrit-Change-Number: 7714058
    Gerrit-PatchSet: 8
    Gerrit-Owner: Georg Neis <ne...@chromium.org>
    Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
    Gerrit-Reviewer: Georg Neis <ne...@chromium.org>
    Gerrit-Reviewer: Hidehiko Abe <hide...@chromium.org>
    open
    diffy
    satisfied_requirement
    Reply all
    Reply to author
    Forward
    0 new messages