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