extension_loading_browsertest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This file contains tests for extension loading, reloading, and
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// unloading behavior.
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/json/json_writer.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/run_loop.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/safe_numerics.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/test/values_test_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/extension_browsertest.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/extension_creator.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace extensions {
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Provides a temporary directory to build an extension into.  This lets all of
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// an extension's code live inside the test instead of in a separate directory.
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class TestExtensionDir {
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TestExtensionDir() {
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_TRUE(dir_.CreateUniqueTempDir());
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_TRUE(crx_dir_.CreateUniqueTempDir());
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Writes |contents| to path()/filename, overwriting anything that was already
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // there.
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void WriteFile(base::FilePath::StringType filename,
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 base::StringPiece contents) {
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::checked_numeric_cast<int>(contents.size()),
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        file_util::WriteFile(
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            dir_.path().Append(filename), contents.data(), contents.size()));
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Converts |value| to JSON, and then writes it to path()/filename with
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // WriteFile().
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void WriteJson(base::FilePath::StringType filename, const Value& value) {
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string json;
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::JSONWriter::Write(&value, &json);
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    WriteFile(filename, json);
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This function packs the extension into a .crx, and returns the path to that
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // .crx. Multiple calls to Pack() will produce extensions with the same ID.
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FilePath Pack() {
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ExtensionCreator creator;
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::FilePath crx_path =
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        crx_dir_.path().Append(FILE_PATH_LITERAL("ext.crx"));
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::FilePath pem_path =
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        crx_dir_.path().Append(FILE_PATH_LITERAL("ext.pem"));
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::FilePath pem_in_path, pem_out_path;
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (file_util::PathExists(pem_path))
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pem_in_path = pem_path;
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    else
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pem_out_path = pem_path;
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!creator.Run(dir_.path(),
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     crx_path,
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pem_in_path,
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     pem_out_path,
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     ExtensionCreator::kOverwriteCRX)) {
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ADD_FAILURE()
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          << "ExtensionCreator::Run() failed: " << creator.error_message();
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return base::FilePath();
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!file_util::PathExists(crx_path)) {
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ADD_FAILURE() << crx_path.value() << " was not created.";
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return base::FilePath();
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return crx_path;
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Stores files that make up the extension.
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::ScopedTempDir dir_;
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Stores the generated .crx and .pem.
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::ScopedTempDir crx_dir_;
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ExtensionLoadingTest : public ExtensionBrowserTest {
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Check the fix for http://crbug.com/178542.
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionLoadingTest,
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       UpgradeAfterNavigatingFromOverriddenNewTabPage) {
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  embedded_test_server()->ServeFilesFromDirectory(
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TestExtensionDir extension_dir;
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::Value> manifest =
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::test::ParseJson("{"
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  \"name\": \"Overrides New Tab\","
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  \"version\": \"1\","
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  \"description\": \"Overrides New Tab\","
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  \"manifest_version\": 2,"
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  \"background\": {"
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "    \"persistent\": false,"
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "    \"scripts\": [\"event.js\"]"
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  },"
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  \"chrome_url_overrides\": {"
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "    \"newtab\": \"newtab.html\""
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "  }"
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            "}");
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extension_dir.WriteJson(FILE_PATH_LITERAL("manifest.json"), *manifest);
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extension_dir.WriteFile(FILE_PATH_LITERAL("event.js"), "");
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extension_dir.WriteFile(FILE_PATH_LITERAL("newtab.html"),
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          "<h1>Overridden New Tab Page</h1>");
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const Extension* new_tab_extension =
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      InstallExtension(extension_dir.Pack(), 1 /*new install*/);
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(new_tab_extension);
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Visit the New Tab Page to get a renderer using the extension into history.
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab"));
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Navigate that tab to a non-extension URL to swap out the extension's
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // renderer.
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const GURL test_link_from_NTP =
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      embedded_test_server()->GetURL("/README.chromium");
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_THAT(test_link_from_NTP.spec(), testing::EndsWith("/README.chromium"))
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      << "Check that the test server started.";
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NavigateInRenderer(browser()->tab_strip_model()->GetActiveWebContents(),
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     test_link_from_NTP);
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Increase the extension's version.
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static_cast<base::DictionaryValue&>(*manifest).SetString("version", "2");
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  extension_dir.WriteJson(FILE_PATH_LITERAL("manifest.json"), *manifest);
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Upgrade the extension.
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  new_tab_extension = UpdateExtension(
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new_tab_extension->id(), extension_dir.Pack(), 0 /*expected upgrade*/);
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_THAT(new_tab_extension->version()->components(),
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              testing::ElementsAre(2));
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The extension takes a couple round-trips to the renderer in order
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // to crash, so open a new tab to wait long enough.
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddTabAtIndex(browser()->tab_strip_model()->count(),
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                GURL("http://www.google.com/"),
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                content::PAGE_TRANSITION_TYPED);
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Check that the extension hasn't crashed.
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionService* service =
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ExtensionSystem::Get(profile())->extension_service();
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(0U, service->terminated_extensions()->size());
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(service->extensions()->Contains(new_tab_extension->id()));
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace extensions
159