Commit 7ab54109 authored by nancy's avatar nancy Committed by Commit Bot

Add instance when launching Chrome apps and PWAs.

Add an InstanceRegistry pointer to ExtensionApps, to add the
instance to the InstanceRegistry when launching apps.

BUG=1011235

Change-Id: I85aea523ecd5e1ea68810bcc8e7e364d1798b5a1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1913286
Commit-Queue: Nancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#715599}
parent 1781840a
......@@ -144,9 +144,11 @@ void AppServiceProxy::Initialize() {
std::make_unique<BuiltInChromeOsApps>(app_service_, profile_);
crostini_apps_ = std::make_unique<CrostiniApps>(app_service_, profile_);
extension_apps_ = std::make_unique<ExtensionApps>(
app_service_, profile_, apps::mojom::AppType::kExtension);
app_service_, profile_, apps::mojom::AppType::kExtension,
&instance_registry_);
extension_web_apps_ = std::make_unique<ExtensionApps>(
app_service_, profile_, apps::mojom::AppType::kWeb);
app_service_, profile_, apps::mojom::AppType::kWeb,
&instance_registry_);
// Asynchronously add app icon source, so we don't do too much work in the
// constructor.
......
......@@ -14,6 +14,7 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/extension_prefs_factory.h"
#include "extensions/browser/extension_registry_factory.h"
#endif // OS_CHROMEOS
......@@ -50,6 +51,7 @@ AppServiceProxyFactory::AppServiceProxyFactory()
BrowserContextDependencyManager::GetInstance()) {
#if defined(OS_CHROMEOS)
DependsOn(crostini::CrostiniRegistryServiceFactory::GetInstance());
DependsOn(extensions::AppWindowRegistry::Factory::GetInstance());
DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
DependsOn(extensions::ExtensionRegistryFactory::GetInstance());
#endif // OS_CHROMEOS
......
......@@ -15,6 +15,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/apps/app_service/app_icon_factory.h"
#include "chrome/browser/apps/launch_service/launch_service.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
......@@ -36,6 +37,8 @@
#include "chrome/browser/web_applications/system_web_app_manager.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_metrics.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/services/app_service/public/cpp/intent_filter_util.h"
......@@ -45,6 +48,7 @@
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "content/public/browser/clear_site_data_utils.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_urls.h"
......@@ -127,6 +131,26 @@ apps::AppLaunchParams CreateAppLaunchParamsForIntent(
return params;
}
// Get the LaunchId for a given |app_window|. Set launch_id default value to an
// empty string. If showInShelf parameter is true and the window key is not
// empty, its value is appended to the launch_id. Otherwise, if the window key
// is empty, the session_id is used.
std::string GetLaunchId(extensions::AppWindow* app_window) {
std::string launch_id;
if (app_window->extension_id() == extension_misc::kChromeCameraAppId)
return launch_id;
if (app_window->show_in_shelf()) {
if (!app_window->window_key().empty()) {
launch_id = app_window->window_key();
} else {
launch_id = base::StringPrintf("%d", app_window->session_id().id());
}
}
return launch_id;
}
} // namespace
namespace apps {
......@@ -197,12 +221,17 @@ void ExtensionApps::RecordUninstallCanceledAction(Profile* profile,
ExtensionApps::ExtensionApps(
const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile,
apps::mojom::AppType app_type)
: profile_(profile), app_type_(app_type) {
apps::mojom::AppType app_type,
apps::InstanceRegistry* instance_registry)
: profile_(profile),
app_type_(app_type),
instance_registry_(instance_registry) {
Initialize(app_service);
}
ExtensionApps::~ExtensionApps() {
app_window_registry_.RemoveAll();
// In unit tests, AppServiceProxy might be ReInitializeForTesting, so
// ExtensionApps might be destroyed without calling Shutdown, so arc_prefs_
// needs to be removed from observer in the destructor function.
......@@ -248,6 +277,7 @@ void ExtensionApps::Initialize(
prefs_observer_.Add(extensions::ExtensionPrefs::Get(profile_));
registry_observer_.Add(extensions::ExtensionRegistry::Get(profile_));
app_window_registry_.Add(extensions::AppWindowRegistry::Get(profile_));
content_settings_observer_.Add(
HostContentSettingsMapFactory::GetForProfile(profile_));
}
......@@ -618,6 +648,17 @@ void ExtensionApps::OnContentSettingChanged(
}
}
void ExtensionApps::OnAppWindowAdded(extensions::AppWindow* app_window) {
RegisterInstance(app_window, InstanceState::kStarted);
}
void ExtensionApps::OnAppWindowShown(extensions::AppWindow* app_window,
bool was_hidden) {
RegisterInstance(app_window,
static_cast<InstanceState>(InstanceState::kStarted |
InstanceState::kRunning));
}
void ExtensionApps::OnExtensionLastLaunchTimeChanged(
const std::string& app_id,
const base::Time& last_launch_time) {
......@@ -1053,4 +1094,41 @@ void ExtensionApps::SetIconEffect(const std::string& app_id) {
Publish(std::move(app));
}
void ExtensionApps::RegisterInstance(extensions::AppWindow* app_window,
InstanceState new_state) {
if (!base::FeatureList::IsEnabled(features::kAppServiceInstanceRegistry)) {
return;
}
if (!instance_registry_ || !app_window) {
return;
}
const extensions::Extension* extension = app_window->GetExtension();
if (!extension) {
return;
}
if (!Accepts(extension)) {
return;
}
InstanceState state = InstanceState::kUnknown;
instance_registry_->ForOneInstance(
app_window->GetNativeWindow(),
[&state](const apps::InstanceUpdate& update) { state = update.State(); });
// If |state| has been marked as |new_state|, we don't need to update.
if ((state & new_state) == new_state) {
return;
}
std::vector<std::unique_ptr<apps::Instance>> deltas;
auto instance = std::make_unique<apps::Instance>(
app_window->extension_id(), app_window->GetNativeWindow());
instance->SetLaunchId(GetLaunchId(app_window));
instance->UpdateState(static_cast<InstanceState>(state | new_state),
base::Time::Now());
deltas.push_back(std::move(instance));
instance_registry_->OnInstances(deltas);
}
} // namespace apps
......@@ -13,9 +13,12 @@
#include "chrome/browser/apps/app_service/app_icon_factory.h"
#include "chrome/browser/apps/app_service/icon_key_util.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
#include "chrome/services/app_service/public/cpp/instance.h"
#include "chrome/services/app_service/public/cpp/instance_registry.h"
#include "chrome/services/app_service/public/mojom/app_service.mojom.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_prefs_observer.h"
#include "extensions/browser/extension_registry.h"
......@@ -28,6 +31,7 @@
class Profile;
namespace extensions {
class AppWindow;
class ExtensionSet;
}
......@@ -42,6 +46,7 @@ class ExtensionAppsEnableFlow;
//
// See chrome/services/app_service/README.md.
class ExtensionApps : public apps::mojom::Publisher,
public extensions::AppWindowRegistry::Observer,
public extensions::ExtensionPrefsObserver,
public extensions::ExtensionRegistryObserver,
public content_settings::Observer,
......@@ -53,7 +58,8 @@ class ExtensionApps : public apps::mojom::Publisher,
ExtensionApps(const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile,
apps::mojom::AppType app_type);
apps::mojom::AppType app_type,
apps::InstanceRegistry* instance_registry);
~ExtensionApps() override;
void FlushMojoCallsForTesting();
......@@ -105,6 +111,11 @@ class ExtensionApps : public apps::mojom::Publisher,
ContentSettingsType content_type,
const std::string& resource_identifier) override;
// Overridden from AppWindowRegistry::Observer:
void OnAppWindowAdded(extensions::AppWindow* app_window) override;
void OnAppWindowShown(extensions::AppWindow* app_window,
bool was_hidden) override;
// extensions::ExtensionPrefsObserver overrides.
void OnExtensionLastLaunchTimeChanged(
const std::string& app_id,
......@@ -172,6 +183,8 @@ class ExtensionApps : public apps::mojom::Publisher,
void SetIconEffect(const std::string& app_id);
void RegisterInstance(extensions::AppWindow* app_window, InstanceState state);
mojo::Receiver<apps::mojom::Publisher> receiver_{this};
mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
......@@ -189,6 +202,11 @@ class ExtensionApps : public apps::mojom::Publisher,
apps::mojom::AppType app_type_;
apps::InstanceRegistry* instance_registry_;
ScopedObserver<extensions::AppWindowRegistry,
extensions::AppWindowRegistry::Observer>
app_window_registry_{this};
using EnableFlowPtr = std::unique_ptr<ExtensionAppsEnableFlow>;
std::map<std::string, EnableFlowPtr> enable_flow_map_;
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <vector>
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
#include "chrome/common/chrome_features.h"
#include "chrome/services/app_service/public/cpp/instance.h"
#include "chrome/services/app_service/public/cpp/instance_registry.h"
#include "extensions/common/extension.h"
namespace apps {
using InstanceRegistryBrowserTest = extensions::PlatformAppBrowserTest;
class InstanceRegistryObserver : public apps::InstanceRegistry::Observer {
public:
explicit InstanceRegistryObserver(apps::InstanceRegistry* instance_registry)
: instance_registry_(instance_registry), instance_update_num_(0) {
Observe(instance_registry);
}
~InstanceRegistryObserver() override = default;
std::vector<apps::InstanceState>& States() { return states_; }
int InstanceUpdateNum() { return instance_update_num_; }
protected:
// apps::InstanceRegistry::Observer overrides.
void OnInstanceUpdate(const apps::InstanceUpdate& update) override {
instance_update_num_++;
states_.push_back(update.State());
}
void OnInstanceRegistryWillBeDestroyed(
apps::InstanceRegistry* instance_registry) override {
Observe(nullptr);
}
apps::InstanceRegistry* instance_registry_;
std::vector<apps::InstanceState> states_;
int instance_update_num_;
};
IN_PROC_BROWSER_TEST_F(InstanceRegistryBrowserTest, ExtensionAppsWindow) {
if (!base::FeatureList::IsEnabled(features::kAppServiceInstanceRegistry)) {
return;
}
AppServiceProxy* app_service_proxy_ =
apps::AppServiceProxyFactory::GetForProfile(profile());
ASSERT_TRUE(app_service_proxy_);
InstanceRegistryObserver observer(&app_service_proxy_->InstanceRegistry());
const extensions::Extension* app =
LoadAndLaunchPlatformApp("app_view/host_app", "AppViewTest.LAUNCHED");
ASSERT_TRUE(app);
int instance_num = 0;
InstanceState latest_state = InstanceState::kUnknown;
app_service_proxy_->InstanceRegistry().ForEachInstance(
[&instance_num, &latest_state](const apps::InstanceUpdate& inner) {
instance_num++;
latest_state = inner.State();
});
EXPECT_EQ(1, instance_num);
EXPECT_NE(0, latest_state | InstanceState::kStarted);
EXPECT_NE(0, latest_state | InstanceState::kRunning);
EXPECT_EQ(2, observer.InstanceUpdateNum());
EXPECT_EQ(2, (int)observer.States().size());
EXPECT_EQ(InstanceState::kStarted, observer.States()[0]);
EXPECT_EQ(InstanceState::kStarted | InstanceState::kRunning,
observer.States()[1]);
}
} // namespace apps
......@@ -2022,6 +2022,7 @@ if (!is_android) {
if (is_chromeos) {
sources += [
"../browser/apps/app_service/instance_registry_browsertest.cc",
"../browser/apps/platform_apps/app_window_interactive_uitest_base.cc",
"../browser/apps/platform_apps/app_window_interactive_uitest_base.h",
"../browser/chromeos/accessibility/accessibility_manager_browsertest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment