Commit 258eb74f authored by Glen Robertson's avatar Glen Robertson Committed by Commit Bot

Extensions API: change installReplacementWebApp to launch if already installed.

Also fixes bug where web app would not be considered installed if
replacement_web_app_url did not match start_url specified in the web app's
manifest.


https://docs.google.com/document/d/18ILBOp7lPP9faAC7mF9hwBC40egzrnGS8GUSkAdG3Lk/edit

Bug: 1007860
Change-Id: I6e70d5ae4dda797b4760dad4b4876ff205873dd8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1847609
Commit-Queue: Glen Robertson <glenrob@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Reviewed-by: default avatarAlexey Baskakov <loyso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712419}
parent dfb30745
......@@ -28,11 +28,13 @@
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
#include "chrome/browser/ui/tab_helpers.h"
#include "chrome/browser/ui/web_applications/web_app_dialog_utils.h"
#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
#include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/components/install_manager.h"
#include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/components/web_app_install_utils.h"
#include "chrome/browser/web_applications/components/web_app_provider_base.h"
#include "chrome/browser/web_applications/components/web_app_utils.h"
......@@ -74,10 +76,11 @@ using InstallAndroidAppCallback =
extensions::ManagementAPIDelegate::InstallAndroidAppCallback;
using AndroidAppInstallStatusCallback =
extensions::ManagementAPIDelegate::AndroidAppInstallStatusCallback;
using InstallWebAppCallback =
extensions::ManagementAPIDelegate::InstallWebAppCallback;
using InstallWebAppResult =
extensions::ManagementAPIDelegate::InstallWebAppResult;
using InstallOrLaunchWebAppCallback =
extensions::ManagementAPIDelegate::InstallOrLaunchWebAppCallback;
using InstallOrLaunchWebAppResult =
extensions::ManagementAPIDelegate::InstallOrLaunchWebAppResult;
using InstallableCheckResult = web_app::InstallManager::InstallableCheckResult;
#if defined(OS_CHROMEOS)
void OnDidCheckForIntentToPlayStore(const std::string& intent,
......@@ -253,40 +256,60 @@ class ChromeAppForLinkDelegate : public extensions::AppForLinkDelegate {
DISALLOW_COPY_AND_ASSIGN(ChromeAppForLinkDelegate);
};
void OnWebAppInstallCompleted(InstallWebAppCallback callback,
void LaunchWebApp(const web_app::AppId& app_id, Profile* profile) {
// Look at prefs to find the right launch container. If the user has not set a
// preference, the default launch value will be returned.
// TODO(crbug.com/1003602): Make AppLaunchParams launch container Optional or
// add a "default" launch container enum value.
auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile);
DCHECK(provider);
blink::mojom::DisplayMode display_mode =
provider->registrar().GetAppUserDisplayMode(app_id);
auto launch_container = apps::mojom::LaunchContainer::kLaunchContainerWindow;
if (display_mode == blink::mojom::DisplayMode::kBrowser)
launch_container = apps::mojom::LaunchContainer::kLaunchContainerTab;
apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams(
app_id, launch_container, WindowOpenDisposition::NEW_FOREGROUND_TAB,
apps::mojom::AppLaunchSource::kSourceManagementApi));
}
void OnWebAppInstallCompleted(InstallOrLaunchWebAppCallback callback,
const web_app::AppId& app_id,
web_app::InstallResultCode code) {
InstallWebAppResult result;
// TODO(loyso): Update this when more of the web_app::InstallResultCodes are
// actually set.
switch (code) {
case web_app::InstallResultCode::kSuccessNewInstall:
result = InstallWebAppResult::kSuccess;
break;
default:
result = InstallWebAppResult::kUnknownError;
}
InstallOrLaunchWebAppResult result =
IsSuccess(code) ? InstallOrLaunchWebAppResult::kSuccess
: InstallOrLaunchWebAppResult::kUnknownError;
std::move(callback).Run(result);
}
void OnDidInstallWebAppInstallableCheck(
void OnWebAppInstallabilityChecked(
Profile* profile,
InstallWebAppCallback callback,
InstallOrLaunchWebAppCallback callback,
std::unique_ptr<content::WebContents> web_contents,
bool is_installable) {
if (!is_installable) {
std::move(callback).Run(InstallWebAppResult::kInvalidWebApp);
return;
InstallableCheckResult result,
base::Optional<web_app::AppId> app_id) {
switch (result) {
case InstallableCheckResult::kAlreadyInstalled:
DCHECK(app_id);
LaunchWebApp(*app_id, profile);
std::move(callback).Run(InstallOrLaunchWebAppResult::kSuccess);
return;
case InstallableCheckResult::kNotInstallable:
std::move(callback).Run(InstallOrLaunchWebAppResult::kInvalidWebApp);
return;
case InstallableCheckResult::kInstallable:
content::WebContents* containing_contents = web_contents.get();
chrome::ScopedTabbedBrowserDisplayer displayer(profile);
chrome::AddWebContents(
displayer.browser(), nullptr, std::move(web_contents),
WindowOpenDisposition::NEW_FOREGROUND_TAB, gfx::Rect());
web_app::CreateWebAppFromManifest(
containing_contents, WebappInstallSource::MANAGEMENT_API,
base::BindOnce(&OnWebAppInstallCompleted, std::move(callback)));
return;
}
content::WebContents* containing_contents = web_contents.get();
chrome::ScopedTabbedBrowserDisplayer displayer(profile);
chrome::AddWebContents(displayer.browser(), nullptr, std::move(web_contents),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
gfx::Rect());
web_app::CreateWebAppFromManifest(
containing_contents, WebappInstallSource::MANAGEMENT_API,
base::BindOnce(&OnWebAppInstallCompleted, std::move(callback)));
NOTREACHED();
}
} // namespace
......@@ -303,6 +326,8 @@ void ChromeManagementAPIDelegate::LaunchAppFunctionDelegate(
// Look at prefs to find the right launch container.
// If the user has not set a preference, the default launch value will be
// returned.
// TODO(crbug.com/1003602): Make AppLaunchParams launch container Optional or
// add a "default" launch container enum value.
extensions::LaunchContainer launch_container =
GetLaunchContainer(extensions::ExtensionPrefs::Get(context), extension);
Profile* profile = Profile::FromBrowserContext(context);
......@@ -408,32 +433,32 @@ ChromeManagementAPIDelegate::GenerateAppForLinkFunctionDelegate(
return std::unique_ptr<extensions::AppForLinkDelegate>(delegate);
}
bool ChromeManagementAPIDelegate::IsWebAppInstalled(
content::BrowserContext* context,
const GURL& web_app_url) const {
auto* provider = web_app::WebAppProviderBase::GetProviderBase(
Profile::FromBrowserContext(context));
DCHECK(provider);
return provider->registrar().IsLocallyInstalled(web_app_url);
}
bool ChromeManagementAPIDelegate::CanContextInstallWebApps(
content::BrowserContext* context) const {
return web_app::AreWebAppsUserInstallable(
Profile::FromBrowserContext(context));
}
void ChromeManagementAPIDelegate::InstallReplacementWebApp(
void ChromeManagementAPIDelegate::InstallOrLaunchReplacementWebApp(
content::BrowserContext* context,
const GURL& web_app_url,
InstallWebAppCallback callback) const {
InstallOrLaunchWebAppCallback callback) const {
Profile* profile = Profile::FromBrowserContext(context);
auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile);
DCHECK(provider);
// Launch the app if web_app_url happens to match start_url. If not, the app
// could still be installed with different start_url.
if (provider->registrar().IsLocallyInstalled(web_app_url)) {
LaunchWebApp(web_app::GenerateAppIdFromURL(web_app_url), profile);
std::move(callback).Run(InstallOrLaunchWebAppResult::kSuccess);
return;
}
provider->install_manager().LoadWebAppAndCheckInstallability(
web_app_url, base::BindOnce(&OnDidInstallWebAppInstallableCheck, profile,
std::move(callback)));
web_app_url, WebappInstallSource::MANAGEMENT_API,
base::BindOnce(&OnWebAppInstallabilityChecked, profile,
std::move(callback)));
}
bool ChromeManagementAPIDelegate::CanContextInstallAndroidApps(
......
......@@ -46,14 +46,13 @@ class ChromeManagementAPIDelegate : public extensions::ManagementAPIDelegate {
content::BrowserContext* context,
const std::string& title,
const GURL& launch_url) const override;
bool IsWebAppInstalled(content::BrowserContext* context,
const GURL& web_app_url) const override;
bool CanContextInstallWebApps(
content::BrowserContext* context) const override;
void InstallReplacementWebApp(
void InstallOrLaunchReplacementWebApp(
content::BrowserContext* context,
const GURL& web_app_url,
ManagementAPIDelegate::InstallWebAppCallback callback) const override;
ManagementAPIDelegate::InstallOrLaunchWebAppCallback callback)
const override;
bool CanContextInstallAndroidApps(
content::BrowserContext* context) const override;
void CheckAndroidAppInstallStatus(
......
......@@ -18,6 +18,7 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/components/web_app_provider_base.h"
#include "chrome/browser/web_applications/test/test_web_app_ui_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "extensions/browser/api/management/management_api.h"
......@@ -189,6 +190,43 @@ class InstallReplacementWebAppApiTest : public ExtensionManagementApiTest {
ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
}
void RunInstallableWebAppTest(const char* manifest,
const char* web_app_url,
const char* web_app_start_url) {
static constexpr char kInstallReplacementWebApp[] =
R"(chrome.test.runWithUserGesture(function() {
chrome.management.installReplacementWebApp(function() {
chrome.test.assertNoLastError();
chrome.test.notifyPass();
});
});)";
chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
const GURL start_url = https_test_server_.GetURL(web_app_start_url);
web_app::AppId web_app_id = web_app::GenerateAppIdFromURL(start_url);
auto* provider =
web_app::WebAppProviderBase::GetProviderBase(browser()->profile());
EXPECT_FALSE(provider->registrar().IsLocallyInstalled(start_url));
EXPECT_EQ(0, static_cast<int>(
provider->ui_manager().GetNumWindowsForApp(web_app_id)));
RunTest(manifest, web_app_url, kInstallReplacementWebApp,
true /* from_webstore */);
EXPECT_TRUE(provider->registrar().IsLocallyInstalled(start_url));
EXPECT_EQ(1, static_cast<int>(
provider->ui_manager().GetNumWindowsForApp(web_app_id)));
// Call API again. It should launch the app.
RunTest(manifest, web_app_url, kInstallReplacementWebApp,
true /* from_webstore */);
EXPECT_TRUE(provider->registrar().IsLocallyInstalled(start_url));
EXPECT_EQ(2, static_cast<int>(
provider->ui_manager().GetNumWindowsForApp(web_app_id)));
chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false);
}
net::EmbeddedTestServer https_test_server_;
};
......@@ -254,76 +292,32 @@ IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest, NotInstallableWebApp) {
}
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest, InstallableWebApp) {
static constexpr char kBackground[] =
R"(chrome.test.runTests([
function runInstall() {
chrome.test.runWithUserGesture(function() {
chrome.management.installReplacementWebApp(function() {
chrome.test.assertNoLastError();
chrome.test.succeed();
});
});
},
function runInstallWhenAlreadyInstalled() {
chrome.test.runWithUserGesture(function() {
chrome.management.installReplacementWebApp(function() {
chrome.test.assertLastError(
'Web app is already installed.');
chrome.test.succeed();
});
});
}
]);)";
static constexpr char kGoodWebAppURL[] =
"/management/install_replacement_web_app/good_web_app/index.html";
chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
const GURL good_web_app_url = https_test_server_.GetURL(kGoodWebAppURL);
auto* provider =
web_app::WebAppProviderBase::GetProviderBase(browser()->profile());
EXPECT_FALSE(provider->registrar().IsLocallyInstalled(good_web_app_url));
RunInstallableWebAppTest(kManifest, kGoodWebAppURL, kGoodWebAppURL);
}
RunTest(kManifest, kGoodWebAppURL, kBackground, true /* from_webstore */);
EXPECT_TRUE(provider->registrar().IsLocallyInstalled(good_web_app_url));
chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false);
// Check that web app still installs and launches correctly when start_url does
// not match replacement_web_app_url.
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,
InstallableWebAppWithStartUrl) {
static constexpr char kGoodWebAppUrl[] =
"/management/install_replacement_web_app/good_web_app_with_start_url/"
"index.html";
static constexpr char kGoodWebAppStartUrl[] =
"/management/install_replacement_web_app/good_web_app_with_start_url/"
"pwa_start_url.html";
RunInstallableWebAppTest(kManifest, kGoodWebAppUrl, kGoodWebAppStartUrl);
}
IN_PROC_BROWSER_TEST_F(InstallReplacementWebAppApiTest,
InstallableWebAppInPlatformApp) {
static constexpr char kBackground[] =
R"(chrome.test.runTests([
function runInstall() {
chrome.test.runWithUserGesture(function() {
chrome.management.installReplacementWebApp(function() {
chrome.test.assertNoLastError();
chrome.test.succeed();
});
});
},
function runInstallWhenAlreadyInstalled() {
chrome.test.runWithUserGesture(function() {
chrome.management.installReplacementWebApp(function() {
chrome.test.assertLastError(
'Web app is already installed.');
chrome.test.succeed();
});
});
}
]);)";
static constexpr char kGoodWebAppURL[] =
"/management/install_replacement_web_app/good_web_app/index.html";
chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
const GURL good_web_app_url = https_test_server_.GetURL(kGoodWebAppURL);
auto* provider =
web_app::WebAppProviderBase::GetProviderBase(browser()->profile());
EXPECT_FALSE(provider->registrar().IsLocallyInstalled(good_web_app_url));
RunTest(kAppManifest, kGoodWebAppURL, kBackground, true /* from_webstore */);
EXPECT_TRUE(provider->registrar().IsLocallyInstalled(good_web_app_url));
chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false);
RunInstallableWebAppTest(kAppManifest, kGoodWebAppURL, kGoodWebAppURL);
}
// Fails often on Windows dbg bots. http://crbug.com/177163
......
......@@ -51,9 +51,18 @@ class InstallManager {
ForInstallableSite for_installable_site,
WebAppInstallationAcceptanceCallback acceptance_callback)>;
using WebAppInstallabilityCheckCallback =
base::OnceCallback<void(std::unique_ptr<content::WebContents>,
bool is_installable)>;
enum class InstallableCheckResult {
kNotInstallable,
kInstallable,
kAlreadyInstalled,
};
// Callback with the result of an installability check.
// |web_contents| owns the WebContents that was used to check installability.
// |app_id| will be present iff already installed.
using WebAppInstallabilityCheckCallback = base::OnceCallback<void(
std::unique_ptr<content::WebContents> web_contents,
InstallableCheckResult result,
base::Optional<AppId> app_id)>;
// Returns true if a web app can be installed for a given |web_contents|.
virtual bool CanInstallWebApp(content::WebContents* web_contents) = 0;
......@@ -130,13 +139,12 @@ class InstallManager {
AppShortcutManager* shortcut_manager,
InstallFinalizer* finalizer);
// Loads |web_app_url| in a new WebContents and determines if it is
// installable.
// Calls back with a unique_ptr owning the WebContents used to check
// installability, and whether the app is installable.
// Loads |web_app_url| in a new WebContents and determines whether it is
// installable. Calls |callback| with results.
virtual void LoadWebAppAndCheckInstallability(
const GURL& web_app_url,
WebAppInstallabilityCheckCallback) = 0;
WebappInstallSource install_source,
WebAppInstallabilityCheckCallback callback) = 0;
protected:
Profile* profile() { return profile_; }
......
......@@ -42,13 +42,14 @@ bool WebAppInstallManager::CanInstallWebApp(
void WebAppInstallManager::LoadWebAppAndCheckInstallability(
const GURL& web_app_url,
WebappInstallSource install_source,
WebAppInstallabilityCheckCallback callback) {
auto task = std::make_unique<WebAppInstallTask>(
profile(), shortcut_manager(), finalizer(),
data_retriever_factory_.Run());
task->LoadWebAppAndCheckInstallability(
web_app_url, WebappInstallSource::MANAGEMENT_API, url_loader_.get(),
web_app_url, install_source, url_loader_.get(),
base::BindOnce(
&WebAppInstallManager::OnLoadWebAppAndCheckInstallabilityCompleted,
base::Unretained(this), task.get(), std::move(callback)));
......@@ -292,7 +293,20 @@ void WebAppInstallManager::OnLoadWebAppAndCheckInstallabilityCompleted(
InstallResultCode code) {
DeleteTask(task);
std::move(callback).Run(std::move(web_contents), IsSuccess(code));
InstallableCheckResult result;
base::Optional<AppId> opt_app_id;
if (IsSuccess(code)) {
if (!app_id.empty() && registrar()->IsInstalled(app_id)) {
result = InstallableCheckResult::kAlreadyInstalled;
opt_app_id = app_id;
} else {
result = InstallableCheckResult::kInstallable;
}
} else {
result = InstallableCheckResult::kNotInstallable;
}
std::move(callback).Run(std::move(web_contents), result, opt_app_id);
}
void WebAppInstallManager::OnWebAppInstalledAfterSync(
......
......@@ -40,6 +40,7 @@ class WebAppInstallManager final : public InstallManager,
bool CanInstallWebApp(content::WebContents* web_contents) override;
void LoadWebAppAndCheckInstallability(
const GURL& web_app_url,
WebappInstallSource install_source,
WebAppInstallabilityCheckCallback callback) override;
void InstallWebAppFromManifest(content::WebContents* contents,
WebappInstallSource install_source,
......
<html>
<head>
<title>Installable web app</title>
<link rel="manifest" href="manifest.json"></link>
</head>
<body>
Do-nothing page with a manifest and a service worker.
<script>
navigator.serviceWorker.register("sw.js");
</script>
</body>
</html>
{
"name": "Installable web app",
"icons": [
{
"src": "image-512px.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "pwa_start_url.html",
"display": "standalone"
}
<html>
<head>
<title>Installable web app</title>
<link rel="manifest" href="manifest.json"></link>
</head>
<body>
Do-nothing page with a manifest and a service worker.
<script>
navigator.serviceWorker.register("sw.js");
</script>
</body>
</html>
// 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.
// A no-op fetch handler.
self.addEventListener('fetch', e => {});
......@@ -958,33 +958,27 @@ ManagementInstallReplacementWebAppFunction::Run() {
Error(keys::kInstallReplacementWebAppInvalidContextError));
}
if (api_delegate->IsWebAppInstalled(browser_context(), web_app_url)) {
return RespondNow(
Error(keys::kInstallReplacementWebAppAlreadyInstalledError));
}
// Adds a ref-count.
api_delegate->InstallReplacementWebApp(
api_delegate->InstallOrLaunchReplacementWebApp(
browser_context(), web_app_url,
base::BindOnce(
&ManagementInstallReplacementWebAppFunction::FinishCreateWebApp,
this));
&ManagementInstallReplacementWebAppFunction::FinishResponse, this));
// Response is sent async in FinishCreateWebApp().
// Response is sent async in FinishResponse().
return RespondLater();
}
void ManagementInstallReplacementWebAppFunction::FinishCreateWebApp(
ManagementAPIDelegate::InstallWebAppResult result) {
void ManagementInstallReplacementWebAppFunction::FinishResponse(
ManagementAPIDelegate::InstallOrLaunchWebAppResult result) {
ResponseValue response;
switch (result) {
case ManagementAPIDelegate::InstallWebAppResult::kSuccess:
case ManagementAPIDelegate::InstallOrLaunchWebAppResult::kSuccess:
response = NoArguments();
break;
case ManagementAPIDelegate::InstallWebAppResult::kInvalidWebApp:
case ManagementAPIDelegate::InstallOrLaunchWebAppResult::kInvalidWebApp:
response = Error(keys::kInstallReplacementWebAppInvalidWebAppError);
break;
case ManagementAPIDelegate::InstallWebAppResult::kUnknownError:
case ManagementAPIDelegate::InstallOrLaunchWebAppResult::kUnknownError:
response = Error(keys::kGenerateAppForLinkInstallError);
}
Respond(std::move(response));
......
......@@ -261,7 +261,8 @@ class ManagementInstallReplacementWebAppFunction : public ExtensionFunction {
ResponseAction Run() override;
private:
void FinishCreateWebApp(ManagementAPIDelegate::InstallWebAppResult result);
void FinishResponse(
ManagementAPIDelegate::InstallOrLaunchWebAppResult result);
};
class ManagementEventRouter : public ExtensionRegistryObserver {
......
......@@ -47,8 +47,6 @@ const char kGenerateAppForLinkInstallError[] =
const char kNotAllowedInKioskError[] = "Not allowed in kiosk.";
const char kCannotChangePrimaryKioskAppError[] =
"Cannot change the primary kiosk app state.";
const char kInstallReplacementWebAppAlreadyInstalledError[] =
"Web app is already installed.";
const char kInstallReplacementWebAppInvalidWebAppError[] =
"Web app is not a valid installable web app.";
const char kInstallReplacementWebAppInvalidContextError[] =
......
......@@ -36,7 +36,6 @@ extern const char kEmptyTitleError[];
extern const char kGenerateAppForLinkInstallError[];
extern const char kNotAllowedInKioskError[];
extern const char kCannotChangePrimaryKioskAppError[];
extern const char kInstallReplacementWebAppAlreadyInstalledError[];
extern const char kInstallReplacementWebAppInvalidWebAppError[];
extern const char kInstallReplacementWebAppInvalidContextError[];
extern const char kInstallReplacementWebAppNotFromWebstoreError[];
......
......@@ -52,8 +52,13 @@ class ManagementAPIDelegate {
using AndroidAppInstallStatusCallback = base::OnceCallback<void(bool)>;
using InstallAndroidAppCallback = base::OnceCallback<void(bool)>;
enum class InstallWebAppResult { kSuccess, kInvalidWebApp, kUnknownError };
typedef base::OnceCallback<void(InstallWebAppResult)> InstallWebAppCallback;
enum class InstallOrLaunchWebAppResult {
kSuccess,
kInvalidWebApp,
kUnknownError
};
using InstallOrLaunchWebAppCallback =
base::OnceCallback<void(InstallOrLaunchWebAppResult)>;
// Launches the app |extension|.
virtual void LaunchAppFunctionDelegate(
......@@ -124,18 +129,15 @@ class ManagementAPIDelegate {
const std::string& title,
const GURL& launch_url) const = 0;
// Returns true if there is already a web app installed for |web_app_url|.
virtual bool IsWebAppInstalled(content::BrowserContext* context,
const GURL& web_app_url) const = 0;
// Returns whether the current user type can install web apps.
virtual bool CanContextInstallWebApps(
content::BrowserContext* context) const = 0;
// Installs a web app for |web_app_url|.
virtual void InstallReplacementWebApp(
// Installs a web app for |web_app_url| or launches if already installed.
virtual void InstallOrLaunchReplacementWebApp(
content::BrowserContext* context,
const GURL& web_app_url,
InstallWebAppCallback callback) const = 0;
InstallOrLaunchWebAppCallback callback) const = 0;
// Returns whether arc apps can be installed in the given |context|.
virtual bool CanContextInstallAndroidApps(
......
......@@ -455,7 +455,7 @@
},
{
"name": "installReplacementWebApp",
"description": "Prompts the user to install the replacement web app from the manifest.",
"description": "Launches the replacement_web_app specified in the manifest. Prompts the user to install if not already installed.",
"parameters": [
{
"name": "callback",
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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.
// This file was generated by:
// ./tools/json_schema_compiler/compiler.py.
// tools/json_schema_compiler/compiler.py.
// NOTE: The format of types has changed. 'FooType' is now
// 'chrome.management.FooType'.
// Please run the closure compiler before committing changes.
......@@ -56,6 +56,7 @@ chrome.management.ExtensionType = {
PACKAGED_APP: 'packaged_app',
LEGACY_PACKAGED_APP: 'legacy_packaged_app',
THEME: 'theme',
LOGIN_SCREEN_EXTENSION: 'login_screen_extension',
};
/**
......@@ -78,7 +79,9 @@ chrome.management.ExtensionInstallType = {
* shortName: string,
* description: string,
* version: string,
* versionName: (string|undefined),
* mayDisable: boolean,
* mayEnable: (boolean|undefined),
* enabled: boolean,
* disabledReason: (!chrome.management.ExtensionDisabledReason|undefined),
* isApp: boolean,
......@@ -144,7 +147,10 @@ chrome.management.getPermissionWarningsById = function(id, callback) {};
chrome.management.getPermissionWarningsByManifest = function(manifestStr, callback) {};
/**
* Enables or disables an app or extension.
* Enables or disables an app or extension. In most cases this function must be
* called in the context of a user gesture (e.g. an onclick handler for a
* button), and may present the user with a native confirmation UI as a way of
* preventing abuse.
* @param {string} id This should be the id from an item of
* $(ref:management.ExtensionInfo).
* @param {boolean} enabled Whether this item should be enabled or disabled.
......@@ -217,6 +223,32 @@ chrome.management.setLaunchType = function(id, launchType, callback) {};
*/
chrome.management.generateAppForLink = function(url, title, callback) {};
/**
* Checks if the replacement android app can be installed. Errors generated by
* this API are reported by setting $(ref:runtime.lastError) and executing the
* function's regular callback.
* @param {function(boolean):void} callback
* @see https://developer.chrome.com/extensions/management#method-canInstallReplacementAndroidApp
*/
chrome.management.canInstallReplacementAndroidApp = function(callback) {};
/**
* Prompts the user to install the replacement Android app from the manifest.
* Errors generated by this API are reported by setting $(ref:runtime.lastError)
* and executing the function's regular callback.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/management#method-installReplacementAndroidApp
*/
chrome.management.installReplacementAndroidApp = function(callback) {};
/**
* Launches the replacement_web_app specified in the manifest. Prompts the user
* to install if not already installed.
* @param {function():void=} callback
* @see https://developer.chrome.com/extensions/management#method-installReplacementWebApp
*/
chrome.management.installReplacementWebApp = function(callback) {};
/**
* Fired when an app or extension has been installed.
* @type {!ChromeEvent}
......
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