1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/apps/drive/drive_app_converter.h"
6
7#include <utility>
8
9#include "base/bind.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/path_service.h"
12#include "base/version.h"
13#include "chrome/browser/extensions/extension_browsertest.h"
14#include "chrome/browser/extensions/extension_service.h"
15#include "chrome/browser/extensions/extension_util.h"
16#include "chrome/common/chrome_paths.h"
17#include "chrome/common/extensions/extension_constants.h"
18#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
19#include "content/public/test/test_utils.h"
20#include "extensions/browser/extension_system.h"
21#include "extensions/common/extension.h"
22#include "extensions/common/manifest_handlers/icons_handler.h"
23#include "extensions/common/permissions/permission_set.h"
24#include "extensions/common/permissions/permissions_data.h"
25#include "net/test/embedded_test_server/embedded_test_server.h"
26#include "testing/gtest/include/gtest/gtest.h"
27
28using extensions::AppLaunchInfo;
29using extensions::Extension;
30using extensions::ExtensionRegistry;
31
32namespace {
33
34const char kAppName[] = "Test drive app";
35const char kAppUrl[] = "http://foobar.com/drive_app";
36
37}  // namespace
38
39class DriveAppConverterTest : public ExtensionBrowserTest {
40 public:
41  DriveAppConverterTest() {}
42  virtual ~DriveAppConverterTest() {}
43
44  // ExtensionBrowserTest:
45  virtual void SetUpOnMainThread() OVERRIDE {
46    ExtensionBrowserTest::SetUpOnMainThread();
47
48    base::FilePath test_data_dir;
49    PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
50    embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
51    ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
52  }
53
54  void InstallAndWaitFinish(const drive::DriveAppInfo& drive_app) {
55    runner_ = new content::MessageLoopRunner;
56
57    converter_.reset(new DriveAppConverter(
58        profile(),
59        drive_app,
60        base::Bind(&DriveAppConverterTest::ConverterFinished,
61                   base::Unretained(this))));
62    converter_->Start();
63
64    runner_->Run();
65  }
66
67  GURL GetTestUrl(const std::string& path) {
68    return embedded_test_server()->base_url().Resolve(path);
69  }
70
71  drive::DriveAppInfo GetTestDriveApp() {
72    // Define four icons. icon1.png is 16x16 and good to use. icon2.png is
73    // 16x16 but claims to be 32x32 and should be dropped. icon3.png is 66x66
74    // and not a valid extension icon size and should be dropped too. The forth
75    // one is icon2.png with 16x16 but should be ignored because 16x16 already
76    // has icon1.png as its resource.
77    drive::DriveAppInfo::IconList app_icons;
78    app_icons.push_back(std::make_pair(16, GetTestUrl("extensions/icon1.png")));
79    app_icons.push_back(std::make_pair(32, GetTestUrl("extensions/icon2.png")));
80    app_icons.push_back(std::make_pair(66, GetTestUrl("extensions/icon3.png")));
81    app_icons.push_back(std::make_pair(16, GetTestUrl("extensions/icon2.png")));
82
83    drive::DriveAppInfo::IconList document_icons;
84
85    return drive::DriveAppInfo("fake_drive_app_id",
86                               "fake_product_id",
87                               app_icons,
88                               document_icons,
89                               kAppName,
90                               GURL(kAppUrl),
91                               true);
92  }
93
94  const DriveAppConverter* converter() const { return converter_.get(); }
95
96 private:
97  void ConverterFinished(const DriveAppConverter* converter, bool success) {
98    if (runner_.get())
99      runner_->Quit();
100  }
101
102  scoped_ptr<DriveAppConverter> converter_;
103  scoped_refptr<content::MessageLoopRunner> runner_;
104
105  DISALLOW_COPY_AND_ASSIGN(DriveAppConverterTest);
106};
107
108IN_PROC_BROWSER_TEST_F(DriveAppConverterTest, GoodApp) {
109  InstallAndWaitFinish(GetTestDriveApp());
110
111  const Extension* app = converter()->extension();
112  ASSERT_TRUE(app != NULL);
113  EXPECT_EQ(kAppName, app->name());
114  EXPECT_TRUE(app->is_hosted_app());
115  EXPECT_TRUE(app->from_bookmark());
116  EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(app));
117  EXPECT_EQ(extensions::LAUNCH_CONTAINER_TAB,
118            AppLaunchInfo::GetLaunchContainer(app));
119  EXPECT_EQ(0u, app->permissions_data()->active_permissions()->apis().size());
120  EXPECT_EQ(1u, extensions::IconsInfo::GetIcons(app).map().size());
121
122  const Extension* installed = extensions::ExtensionSystem::Get(profile())
123                                   ->extension_service()
124                                   ->GetInstalledExtension(app->id());
125  EXPECT_EQ(app, installed);
126  EXPECT_FALSE(extensions::util::ShouldSyncApp(app, profile()));
127}
128
129IN_PROC_BROWSER_TEST_F(DriveAppConverterTest, BadApp) {
130  drive::DriveAppInfo no_name = GetTestDriveApp();
131  no_name.app_name.clear();
132  InstallAndWaitFinish(no_name);
133  EXPECT_TRUE(converter()->extension() == NULL);
134
135  drive::DriveAppInfo no_url = GetTestDriveApp();
136  no_url.create_url = GURL();
137  InstallAndWaitFinish(no_url);
138  EXPECT_TRUE(converter()->extension() == NULL);
139}
140
141IN_PROC_BROWSER_TEST_F(DriveAppConverterTest, InstallTwice) {
142  InstallAndWaitFinish(GetTestDriveApp());
143  const Extension* first_install = converter()->extension();
144  ASSERT_TRUE(first_install != NULL);
145  EXPECT_TRUE(converter()->is_new_install());
146  const std::string first_install_id = first_install->id();
147  const base::Version first_install_version(first_install->VersionString());
148  ASSERT_TRUE(first_install_version.IsValid());
149
150  InstallAndWaitFinish(GetTestDriveApp());
151  const Extension* second_install = converter()->extension();
152  ASSERT_TRUE(second_install != NULL);
153  EXPECT_FALSE(converter()->is_new_install());
154
155  // Two different app instances.
156  ASSERT_NE(first_install, second_install);
157  EXPECT_EQ(first_install_id, second_install->id());
158  EXPECT_GE(second_install->version()->CompareTo(first_install_version), 0);
159}
160