1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
// Copyright 2014 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/extensions/webstore_reinstaller.h"
#include "base/functional/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "chrome/browser/extensions/webstore_data_fetcher.h"
#include "chrome/browser/extensions/webstore_installer_test.h"
#include "chrome/common/extensions/webstore_install_result.h"
#include "content/public/test/browser_test.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_features.h"
namespace extensions {
namespace {
constexpr char kWebstoreDomain[] = "cws.com";
constexpr char kAppDomain[] = "app.com";
constexpr char kNonAppDomain[] = "nonapp.com";
constexpr char kTestExtensionId[] = "ecglahbcnmdpdciemllbhojghbkagdje";
constexpr char kTestDataPath[] = "extensions/api_test/webstore_inline_install";
constexpr char kCrxFilename[] = "extension.crx";
// The following values are used to mock a protobuf response to the item
// snippets API and should match the values for the test extension stored in
// "chrome/test/data/extensions/api_test/webstore_inline_install/extension".
constexpr char kMockTitle[] = "Inline Install Test Extension";
constexpr char kMockUserCountString[] = "371,674";
constexpr double kMockAverageRating = 4.36;
constexpr int kMockRatingCount = 788;
constexpr char kMockRatingCountString[] = "788";
constexpr char kMockLogoUri[] = "webstore_inline_install/extension/icon.png";
constexpr char kMockManifest[] = R"({
"name": "Inline Install Test Extension",
"version": "0.1",
"manifest_version": 2,
"icons": {"128": "icon.png"},
"permissions":["tabs"]
})";
std::unique_ptr<FetchItemSnippetResponse> CreateMockResponse(
const ExtensionId& id) {
auto mock_response = std::make_unique<FetchItemSnippetResponse>();
mock_response->set_item_id(id);
mock_response->set_title(kMockTitle);
mock_response->set_manifest(kMockManifest);
mock_response->set_logo_uri(kMockLogoUri);
mock_response->set_user_count_string(kMockUserCountString);
mock_response->set_rating_count_string(kMockRatingCountString);
mock_response->set_rating_count(kMockRatingCount);
mock_response->set_average_rating(kMockAverageRating);
return mock_response;
}
} // namespace
class WebstoreReinstallerBrowserTest : public WebstoreInstallerTest {
public:
WebstoreReinstallerBrowserTest()
: WebstoreInstallerTest(kWebstoreDomain,
kTestDataPath,
kCrxFilename,
kAppDomain,
kNonAppDomain) {}
~WebstoreReinstallerBrowserTest() override = default;
void OnInstallCompletion(base::OnceClosure quit_closure,
bool success,
const std::string& error,
webstore_install::Result result);
bool last_install_result() const { return last_install_result_; }
private:
bool last_install_result_ = false;
};
void WebstoreReinstallerBrowserTest::OnInstallCompletion(
base::OnceClosure quit_closure,
bool success,
const std::string& error,
webstore_install::Result result) {
last_install_result_ = success;
std::move(quit_closure).Run();
}
// Tests that reinstalls for corrupted extensions work when using the item
// snippets API, which returns a protobuf object for web store data (the API
// return is mocked for this test).
IN_PROC_BROWSER_TEST_F(WebstoreReinstallerBrowserTest, TestWebstoreReinstall) {
// Build an extension with the same id as our test extension and add it.
const std::string kExtensionName("ReinstallerExtension");
scoped_refptr<const Extension> extension =
ExtensionBuilder()
.SetLocation(mojom::ManifestLocation::kInternal)
.SetID(kTestExtensionId)
.SetManifest(
base::Value::Dict()
.Set("name", kExtensionName)
.Set("description", "Foo")
.Set("manifest_version", 2)
.Set("version", "1.0")
.Set("update_url",
"https://clients2.google.com/service/update2/crx"))
.Build();
extension_registrar()->AddExtension(extension.get());
auto mock_response = CreateMockResponse(kTestExtensionId);
WebstoreDataFetcher::SetMockItemSnippetReponseForTesting(mock_response.get());
ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
ASSERT_TRUE(registry->enabled_extensions().GetByID(kTestExtensionId));
// WebstoreReinstaller expects corrupted extension.
extension_registrar()->DisableExtension(kTestExtensionId,
{disable_reason::DISABLE_CORRUPTED});
content::WebContents* active_web_contents = GetActiveWebContents();
ASSERT_TRUE(active_web_contents);
// Start by canceling the repair prompt.
AutoCancelInstall();
// Create and run a WebstoreReinstaller.
base::RunLoop run_loop;
auto reinstaller = base::MakeRefCounted<WebstoreReinstaller>(
active_web_contents, kTestExtensionId,
base::BindOnce(&WebstoreReinstallerBrowserTest::OnInstallCompletion,
base::Unretained(this), run_loop.QuitClosure()));
reinstaller->BeginReinstall();
run_loop.Run();
// We should have failed, and the old extension should still be present.
EXPECT_FALSE(last_install_result());
extension = registry->disabled_extensions().GetByID(kTestExtensionId);
ASSERT_TRUE(extension.get());
EXPECT_EQ(kExtensionName, extension->name());
// Now accept the repair prompt.
AutoAcceptInstall();
base::RunLoop run_loop2;
reinstaller = base::MakeRefCounted<WebstoreReinstaller>(
active_web_contents, kTestExtensionId,
base::BindOnce(&WebstoreReinstallerBrowserTest::OnInstallCompletion,
base::Unretained(this), run_loop2.QuitClosure()));
reinstaller->BeginReinstall();
run_loop2.Run();
// The reinstall should have succeeded, and the extension should have been
// "updated" (which in this case means that it should have been replaced with
// the inline install test extension, since that's the id we used).
EXPECT_TRUE(last_install_result());
extension = registry->enabled_extensions().GetByID(kTestExtensionId);
ASSERT_TRUE(extension.get());
// The name should not match, since the extension changed.
EXPECT_NE(kExtensionName, extension->name());
}
} // namespace extensions
|