Commit be8f8b48 authored by Owen Min's avatar Owen Min Committed by Commit Bot

Add webstorePrivate.getExtensionStatus API

The API returns the extension status for installation. It returns a value
based on an extension's install state, policy setting and request status.
This API will be used by CWS extension detail page.

Bug: 1006899, 995385
Change-Id: Icedc653829e255cf56d8c84c86fcd169fc4674e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1885450
Commit-Queue: Owen Min <zmin@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#715050}
parent d3bb3826
......@@ -20,6 +20,7 @@
#include "base/version.h"
#include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/webstore_private/extension_install_status.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
......@@ -42,6 +43,7 @@
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
......@@ -61,6 +63,7 @@ namespace CompleteInstall = api::webstore_private::CompleteInstall;
namespace GetBrowserLogin = api::webstore_private::GetBrowserLogin;
namespace GetEphemeralAppsEnabled =
api::webstore_private::GetEphemeralAppsEnabled;
namespace GetExtensionStatus = api::webstore_private::GetExtensionStatus;
namespace GetIsLauncherEnabled = api::webstore_private::GetIsLauncherEnabled;
namespace GetStoreLogin = api::webstore_private::GetStoreLogin;
namespace GetWebGLStatus = api::webstore_private::GetWebGLStatus;
......@@ -730,4 +733,65 @@ WebstorePrivateGetReferrerChainFunction::Run() {
serialized_referrer_proto)));
}
WebstorePrivateGetExtensionStatusFunction::
WebstorePrivateGetExtensionStatusFunction()
: chrome_details_(this) {}
WebstorePrivateGetExtensionStatusFunction::
~WebstorePrivateGetExtensionStatusFunction() = default;
ExtensionFunction::ResponseAction
WebstorePrivateGetExtensionStatusFunction::Run() {
std::unique_ptr<GetExtensionStatus::Params> params(
GetExtensionStatus::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
Profile* profile = chrome_details_.GetProfile();
const ExtensionId& extension_id = params->id;
if (!crx_file::id_util::IdIsValid(extension_id)) {
return RespondNow(Error(kWebstoreInvalidIdError));
}
ExtensionInstallStatus status =
GetWebstoreExtensionInstallStatus(extension_id, profile);
api::webstore_private::ExtensionInstallStatus api_status =
api::webstore_private::EXTENSION_INSTALL_STATUS_NONE;
switch (status) {
case kCanRequest:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_CAN_REQUEST;
break;
case kRequestPending:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_REQUEST_PENDING;
break;
case kBlockedByPolicy:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_BLOCKED_BY_POLICY;
break;
case kInstallable:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_INSTALLABLE;
break;
case kEnabled:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_ENABLED;
break;
case kDisabled:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_DISABLED;
break;
case kTerminated:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_TERMINATED;
break;
case kBlacklisted:
api_status = api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_BLACKLISTED;
break;
}
return RespondNow(
OneArgument(GetExtensionStatus::Results::Create(api_status)));
}
} // namespace extensions
......@@ -316,6 +316,24 @@ class WebstorePrivateGetReferrerChainFunction : public ExtensionFunction {
DISALLOW_COPY_AND_ASSIGN(WebstorePrivateGetReferrerChainFunction);
};
class WebstorePrivateGetExtensionStatusFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("webstorePrivate.getExtensionStatus",
WEBSTOREPRIVATE_GETEXTENSIONSTATUS)
WebstorePrivateGetExtensionStatusFunction();
private:
~WebstorePrivateGetExtensionStatusFunction() override;
// ExtensionFunction:
ExtensionFunction::ResponseAction Run() override;
ChromeExtensionFunctionDetails chrome_details_;
DISALLOW_COPY_AND_ASSIGN(WebstorePrivateGetExtensionStatusFunction);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_PRIVATE_WEBSTORE_PRIVATE_API_H_
// 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 "chrome/browser/extensions/api/webstore_private/webstore_private_api.h"
#include <vector>
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/extension_api_unittest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension_builder.h"
namespace extensions {
namespace {
constexpr char kInvalidId[] = "Invalid id";
constexpr char kExtensionId[] = "abcdefghijklmnopabcdefghijklmnop";
} // namespace
class WebstorePrivateGetExtensionStatusTest : public ExtensionApiUnittest {
public:
using ExtensionInstallStatus = api::webstore_private::ExtensionInstallStatus;
WebstorePrivateGetExtensionStatusTest() = default;
std::string GenerateArgs(const char* id) {
return base::StringPrintf(R"(["%s"])", id);
}
scoped_refptr<const Extension> CreateExtension(const ExtensionId& id) {
return ExtensionBuilder("extension").SetID(id).Build();
}
void VerifyResponse(const ExtensionInstallStatus& expected_response,
const base::Value* actual_response) {
ASSERT_TRUE(actual_response->is_list());
const auto& actual_list = actual_response->GetList();
ASSERT_EQ(1u, actual_list.size());
ASSERT_TRUE(actual_list[0].is_string());
EXPECT_EQ(ToString(expected_response), actual_list[0].GetString());
}
private:
DISALLOW_COPY_AND_ASSIGN(WebstorePrivateGetExtensionStatusTest);
};
TEST_F(WebstorePrivateGetExtensionStatusTest, InvalidExtensionId) {
auto function =
base::MakeRefCounted<WebstorePrivateGetExtensionStatusFunction>();
EXPECT_EQ(kInvalidId,
RunFunctionAndReturnError(function.get(),
GenerateArgs("invalid-extension-id")));
}
TEST_F(WebstorePrivateGetExtensionStatusTest, ExtensionEnabled) {
ExtensionRegistry::Get(profile())->AddEnabled(CreateExtension(kExtensionId));
auto function =
base::MakeRefCounted<WebstorePrivateGetExtensionStatusFunction>();
std::unique_ptr<base::Value> response =
RunFunctionAndReturnValue(function.get(), GenerateArgs(kExtensionId));
VerifyResponse(ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_ENABLED,
response.get());
}
} // namespace extensions
......@@ -74,6 +74,35 @@
"id": "WebGlStatus",
"type": "string",
"enum": ["webgl_allowed", "webgl_blocked"]
},
{
"id": "ExtensionInstallStatus",
"type": "string",
"enum" : [{
"name": "can_request",
"description": "The extension install request feature is enabled and the extension can be requested."
}, {
"name": "request_pending",
"description": "The extension install request has been sent and is waiting to be reviewed."
}, {
"name": "blocked_by_policy",
"description": "The extension cannot be installed due to enterprise policy."
}, {
"name": "installable",
"description": "The extension can be installed."
}, {
"name": "enabled",
"description": "The extension has been installed already and it's enabled."
}, {
"name": "disabled",
"description": "The extension has been installed already but it's disabled."
}, {
"name": "terminated",
"description": "The extension has been installed already but it's terminated."
}, {
"name": "blacklisted",
"description": "The extension has been blacklisted."
}]
}
],
"functions": [
......@@ -352,6 +381,24 @@
]
}
]
},
{
"name": "getExtensionStatus",
"description": "Returns the install status of the extension.",
"parameters": [
{
"name": "id",
"type": "string",
"description": "The id of the extension"
},
{
"name": "callback",
"type": "function",
"parameters": [
{ "name": "status", "$ref": "ExtensionInstallStatus" }
]
}
]
}
]
}
......
......@@ -4350,6 +4350,7 @@ test("unit_tests") {
"../browser/extensions/api/web_request/web_request_event_details_unittest.cc",
"../browser/extensions/api/web_request/web_request_permissions_unittest.cc",
"../browser/extensions/api/webstore_private/extension_install_status_unittest.cc",
"../browser/extensions/api/webstore_private/webstore_private_unittest.cc",
"../browser/extensions/app_data_migrator_unittest.cc",
"../browser/extensions/blacklist_check_unittest.cc",
"../browser/extensions/blacklist_state_fetcher_unittest.cc",
......
......@@ -1472,6 +1472,7 @@ enum HistogramValue {
AUTOTESTPRIVATE_MOUSEPRESS = 1409,
AUTOTESTPRIVATE_MOUSERELEASE = 1410,
AUTOTESTPRIVATE_MOUSEMOVE = 1411,
WEBSTOREPRIVATE_GETEXTENSIONSTATUS = 1412,
// Last entry: Add new entries above, then run:
// python tools/metrics/histograms/update_extension_histograms.py
ENUM_BOUNDARY
......
......@@ -21306,6 +21306,7 @@ Called by update_net_error_codes.py.-->
<int value="1409" label="AUTOTESTPRIVATE_MOUSEPRESS"/>
<int value="1410" label="AUTOTESTPRIVATE_MOUSERELEASE"/>
<int value="1411" label="AUTOTESTPRIVATE_MOUSEMOVE"/>
<int value="1412" label="WEBSTOREPRIVATE_GETEXTENSIONSTATUS"/>
</enum>
<enum name="ExtensionIconState">
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