Skip to content

Commit

Permalink
Create abstract classes for device system tray icon
Browse files Browse the repository at this point in the history
This change creates abstract classes in
chrome/browser/device_notifications for common device system tray icon
that will be used by WebHID and WebUSB system tray icon.

There will be follow-up CLs to move common logic into these common
classes.

Bug: 1303193
Change-Id: Ie9a6c894381c9defe427380333dabd31a9465ef8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4483156
Reviewed-by: Theresa Sullivan <twellington@chromium.org>
Commit-Queue: Jack Hsieh <chengweih@chromium.org>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1146565}
  • Loading branch information
chengweih001 authored and Chromium LUCI CQ committed May 19, 2023
1 parent 42c273b commit e057e15
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 216 deletions.
4 changes: 4 additions & 0 deletions chrome/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -3569,6 +3569,10 @@ static_library("browser") {
"device_identity/device_oauth2_token_service_factory.cc",
"device_identity/device_oauth2_token_service_factory.h",
"device_identity/device_oauth2_token_store.h",
"device_notifications/device_connection_tracker.cc",
"device_notifications/device_connection_tracker.h",
"device_notifications/device_system_tray_icon.cc",
"device_notifications/device_system_tray_icon.h",
"diagnostics/diagnostics_controller.cc",
"diagnostics/diagnostics_controller.h",
"diagnostics/diagnostics_metrics.cc",
Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/device_notifications/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
file://chrome/browser/usb/OWNERS
file://chrome/browser/hid/OWNERS
140 changes: 140 additions & 0 deletions chrome/browser/device_notifications/device_connection_tracker.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/device_notifications/device_connection_tracker.h"

#include <string>

#include "base/notreached.h"
#include "build/build_config.h"
#include "chrome/browser/device_notifications/device_system_tray_icon.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/buildflags/buildflags.h"
#include "url/origin.h"

#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h"
#endif // BUILDFLAG(ENABLE_EXTENSIONS)

namespace {

using base::TimeTicks;

std::string GetOriginName(Profile* profile, const url::Origin& origin) {
#if BUILDFLAG(ENABLE_EXTENSIONS)
if (origin.scheme() == extensions::kExtensionScheme) {
const auto* extension_registry =
extensions::ExtensionRegistry::Get(profile);
CHECK(extension_registry);
const extensions::Extension* extension =
extension_registry->GetExtensionById(
origin.host(), extensions::ExtensionRegistry::EVERYTHING);
// The extension must be installed if we are generating the name.
CHECK(extension);
return extension->name();
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
NOTREACHED_NORETURN();
}

} // namespace

DeviceConnectionTracker::DeviceConnectionTracker(Profile* profile)
: profile_(profile) {}

DeviceConnectionTracker::~DeviceConnectionTracker() {
CleanUp();
}

void DeviceConnectionTracker::IncrementConnectionCount(
const url::Origin& origin) {
bool to_stage_profile = origins_.empty();
auto& state = origins_[origin];

CHECK_GE(state.count, 0);
if (state.count == 0) {
state.name = GetOriginName(profile_, origin);
}
++state.count;
state.timestamp = TimeTicks::Now();
++total_connection_count_;

auto* system_tray_icon = GetSystemTrayIcon();
if (!system_tray_icon) {
return;
}
if (to_stage_profile) {
system_tray_icon->StageProfile(profile_);
} else {
system_tray_icon->NotifyConnectionCountUpdated(profile_);
}
}

void DeviceConnectionTracker::DecrementConnectionCount(
const url::Origin& origin) {
auto it = origins_.find(origin);
CHECK(it != origins_.end());

auto& state = it->second;
CHECK_GT(state.count, 0);
--state.count;
state.timestamp = TimeTicks::Now();
--total_connection_count_;
if (state.count == 0) {
content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)
->PostDelayedTask(
FROM_HERE,
base::BindOnce(&DeviceConnectionTracker::CleanUpOrigin,
weak_factory_.GetWeakPtr(), origin, state.timestamp),
kOriginInactiveTime);
}

auto* system_tray_icon = GetSystemTrayIcon();
if (!system_tray_icon) {
return;
}
system_tray_icon->NotifyConnectionCountUpdated(profile_);
}

void DeviceConnectionTracker::ShowSiteSettings(const url::Origin& origin) {
chrome::ShowSiteSettings(profile_, origin.GetURL());
}

void DeviceConnectionTracker::CleanUp() {
if (!origins_.empty()) {
origins_.clear();
total_connection_count_ = 0;
auto* system_tray_icon = GetSystemTrayIcon();
if (system_tray_icon) {
system_tray_icon->UnstageProfile(profile_, /*immediate=*/true);
}
}
}

void DeviceConnectionTracker::CleanUpOrigin(const url::Origin& origin,
const TimeTicks& timestamp) {
auto it = origins_.find(origin);
if (it == origins_.end()) {
// This can happen if the connection bounces within 1 microsecond, which is
// the base unit of base::TimeTicks. The first CleanUpOrigin call will clear
// the origin because it sees the timestamp as the same.
return;
}
auto& state = it->second;
if (state.count == 0 && state.timestamp == timestamp) {
origins_.erase(it);
auto* system_tray_icon = GetSystemTrayIcon();
if (!system_tray_icon) {
return;
}
if (origins_.empty()) {
system_tray_icon->UnstageProfile(profile_, /*immediate=*/true);
} else {
system_tray_icon->NotifyConnectionCountUpdated(profile_);
}
}
}
74 changes: 74 additions & 0 deletions chrome/browser/device_notifications/device_connection_tracker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_DEVICE_NOTIFICATIONS_DEVICE_CONNECTION_TRACKER_H_
#define CHROME_BROWSER_DEVICE_NOTIFICATIONS_DEVICE_CONNECTION_TRACKER_H_

#include "base/containers/flat_map.h"
#include "chrome/browser/device_notifications/device_system_tray_icon.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/core/keyed_service.h"
#include "url/origin.h"

// Manages the opened device connection count by the profile.
class DeviceConnectionTracker : public KeyedService {
public:
struct OriginState {
// The number of active connections.
int count;
// The last time the state was updated.
base::TimeTicks timestamp;
// String representation for the origin.
std::string name;

bool operator==(const OriginState& other) const {
return count == other.count && timestamp == other.timestamp &&
name == other.name;
}
};

explicit DeviceConnectionTracker(Profile* profile);
DeviceConnectionTracker(DeviceConnectionTracker&&) = delete;
DeviceConnectionTracker& operator=(DeviceConnectionTracker&) = delete;
~DeviceConnectionTracker() override;

virtual void IncrementConnectionCount(const url::Origin& origin);
virtual void DecrementConnectionCount(const url::Origin& origin);

virtual void ShowContentSettingsExceptions() = 0;
virtual void ShowSiteSettings(const url::Origin& origin);

// This is used by either the destructor or
// the corresponding ConnectionTrackerFactory::BrowserContextShutdown to
// remove its profile from DeviceSystemTrayIcon.
void CleanUp();

int total_connection_count() { return total_connection_count_; }
Profile* profile() { return profile_; }

const base::flat_map<url::Origin, OriginState>& origins() { return origins_; }

// The time period that an origin remains tracked before it is removed from
// `origins_`.
static constexpr base::TimeDelta kOriginInactiveTime = base::Seconds(10);

// Removes the `origin` from the `origins_` list if it has not had any new
// connections since `timestamp`.
void CleanUpOrigin(const url::Origin& origin,
const base::TimeTicks& timestamp);

int total_connection_count_ = 0;
raw_ptr<Profile> profile_;

// The structure that tracks the connection count for each origin that has
// active connection(s).
base::flat_map<url::Origin, OriginState> origins_;

private:
virtual DeviceSystemTrayIcon* GetSystemTrayIcon() = 0;

base::WeakPtrFactory<DeviceConnectionTracker> weak_factory_{this};
};

#endif // CHROME_BROWSER_DEVICE_NOTIFICATIONS_DEVICE_CONNECTION_TRACKER_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/device_notifications/device_system_tray_icon.h"

DeviceSystemTrayIcon::DeviceSystemTrayIcon() = default;

DeviceSystemTrayIcon::~DeviceSystemTrayIcon() = default;
40 changes: 40 additions & 0 deletions chrome/browser/device_notifications/device_system_tray_icon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_DEVICE_NOTIFICATIONS_DEVICE_SYSTEM_TRAY_ICON_H_
#define CHROME_BROWSER_DEVICE_NOTIFICATIONS_DEVICE_SYSTEM_TRAY_ICON_H_

class Profile;

class DeviceSystemTrayIcon {
public:
DeviceSystemTrayIcon();
DeviceSystemTrayIcon(const DeviceSystemTrayIcon&) = delete;
DeviceSystemTrayIcon& operator=(const DeviceSystemTrayIcon&) = delete;
virtual ~DeviceSystemTrayIcon();

// Stage `profile` to be shown in the system tray icon.
virtual void StageProfile(Profile* profile) = 0;

// TODO(crbug.com/1353104): Remove support for non-immediate unstage request.
// Unstage `profile` that is being shown in the system tray icon. The profile
// will be removed immediately when `immediate` is true, otherwise it is
// scheduled to be removed later.
virtual void UnstageProfile(Profile* profile, bool immediate) = 0;

// Notify the system tray icon the connection count of the `profile` has
// changed.
virtual void NotifyConnectionCountUpdated(Profile* profile) = 0;

protected:
// This function is called after the `profile` object is added to the
// `profiles_`.
virtual void ProfileAdded(Profile* profile) = 0;

// This function is called after the `profile` object is removed from the
// `profiles_`.
virtual void ProfileRemoved(Profile* profile) = 0;
};

#endif // CHROME_BROWSER_DEVICE_NOTIFICATIONS_DEVICE_SYSTEM_TRAY_ICON_H_

0 comments on commit e057e15

Please sign in to comment.