1// Copyright (c) 2012 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 "base/bind.h"
6#include "base/files/file_util.h"
7#include "base/memory/ref_counted.h"
8#include "base/message_loop/message_loop.h"
9#include "base/path_service.h"
10#include "base/run_loop.h"
11#include "base/strings/string_util.h"
12#include "base/values.h"
13#include "chrome/browser/extensions/sandboxed_unpacker.h"
14#include "chrome/common/chrome_paths.h"
15#include "content/public/test/test_browser_thread_bundle.h"
16#include "content/public/test/test_utils.h"
17#include "extensions/common/constants.h"
18#include "extensions/common/extension.h"
19#include "testing/gtest/include/gtest/gtest.h"
20#include "third_party/skia/include/core/SkBitmap.h"
21
22namespace extensions {
23
24class MockSandboxedUnpackerClient : public SandboxedUnpackerClient {
25 public:
26
27  void WaitForUnpack() {
28    scoped_refptr<content::MessageLoopRunner> runner =
29        new content::MessageLoopRunner;
30    quit_closure_ = runner->QuitClosure();
31    runner->Run();
32  }
33
34  base::FilePath temp_dir() const { return temp_dir_; }
35
36 private:
37  virtual ~MockSandboxedUnpackerClient() {}
38
39  virtual void OnUnpackSuccess(const base::FilePath& temp_dir,
40                               const base::FilePath& extension_root,
41                               const base::DictionaryValue* original_manifest,
42                               const Extension* extension,
43                               const SkBitmap& install_icon) OVERRIDE {
44    temp_dir_ = temp_dir;
45    quit_closure_.Run();
46
47  }
48
49  virtual void OnUnpackFailure(const base::string16& error) OVERRIDE {
50    ASSERT_TRUE(false);
51  }
52
53  base::Closure quit_closure_;
54  base::FilePath temp_dir_;
55};
56
57class SandboxedUnpackerTest : public testing::Test {
58 public:
59  virtual void SetUp() {
60   ASSERT_TRUE(extensions_dir_.CreateUniqueTempDir());
61    browser_threads_.reset(new content::TestBrowserThreadBundle(
62        content::TestBrowserThreadBundle::IO_MAINLOOP));
63    in_process_utility_thread_helper_.reset(
64        new content::InProcessUtilityThreadHelper);
65    // It will delete itself.
66    client_ = new MockSandboxedUnpackerClient;
67  }
68
69  virtual void TearDown() {
70    // Need to destruct SandboxedUnpacker before the message loop since
71    // it posts a task to it.
72    sandboxed_unpacker_ = NULL;
73    base::RunLoop().RunUntilIdle();
74  }
75
76  void SetupUnpacker(const std::string& crx_name) {
77    base::FilePath original_path;
78    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &original_path));
79    original_path = original_path.AppendASCII("extensions")
80        .AppendASCII("unpacker")
81        .AppendASCII(crx_name);
82    ASSERT_TRUE(base::PathExists(original_path)) << original_path.value();
83
84    sandboxed_unpacker_ = new SandboxedUnpacker(
85        original_path,
86        Manifest::INTERNAL,
87        Extension::NO_FLAGS,
88        extensions_dir_.path(),
89        base::MessageLoopProxy::current(),
90        client_);
91
92    base::MessageLoopProxy::current()->PostTask(
93        FROM_HERE,
94        base::Bind(&SandboxedUnpacker::Start, sandboxed_unpacker_.get()));
95    client_->WaitForUnpack();
96  }
97
98  base::FilePath GetInstallPath() {
99    return client_->temp_dir().AppendASCII(kTempExtensionName);
100  }
101
102 protected:
103  base::ScopedTempDir extensions_dir_;
104  MockSandboxedUnpackerClient* client_;
105  scoped_refptr<SandboxedUnpacker> sandboxed_unpacker_;
106  scoped_ptr<content::TestBrowserThreadBundle> browser_threads_;
107  scoped_ptr<content::InProcessUtilityThreadHelper>
108      in_process_utility_thread_helper_;
109};
110
111TEST_F(SandboxedUnpackerTest, NoCatalogsSuccess) {
112  SetupUnpacker("no_l10n.crx");
113  // Check that there is no _locales folder.
114  base::FilePath install_path =
115      GetInstallPath().Append(kLocaleFolder);
116  EXPECT_FALSE(base::PathExists(install_path));
117}
118
119TEST_F(SandboxedUnpackerTest, WithCatalogsSuccess) {
120  SetupUnpacker("good_l10n.crx");
121  // Check that there is _locales folder.
122  base::FilePath install_path =
123      GetInstallPath().Append(kLocaleFolder);
124  EXPECT_TRUE(base::PathExists(install_path));
125}
126
127}  // namespace extensions
128