// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>

#include "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_paths.h"
#include "extensions/common/extension_resource.h"
#include "extensions/common/id_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"

namespace extensions {

TEST(ExtensionResourceTest, CreateEmptyResource) {
  ExtensionResource resource;

  EXPECT_TRUE(resource.extension_root().empty());
  EXPECT_TRUE(resource.relative_path().empty());
  EXPECT_TRUE(resource.GetFilePath().empty());
}

const base::FilePath::StringType ToLower(
    const base::FilePath::StringType& in_str) {
  base::FilePath::StringType str(in_str);
  std::transform(str.begin(), str.end(), str.begin(), tolower);
  return str;
}

TEST(ExtensionResourceTest, CreateWithMissingResourceOnDisk) {
  base::FilePath root_path;
  ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &root_path));
  base::FilePath relative_path;
  relative_path = relative_path.AppendASCII("cira.js");
  std::string extension_id = id_util::GenerateId("test");
  ExtensionResource resource(extension_id, root_path, relative_path);

  // The path doesn't exist on disk, we will be returned an empty path.
  EXPECT_EQ(root_path.value(), resource.extension_root().value());
  EXPECT_EQ(relative_path.value(), resource.relative_path().value());
  EXPECT_TRUE(resource.GetFilePath().empty());
}

TEST(ExtensionResourceTest, ResourcesOutsideOfPath) {
  base::ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  base::FilePath inner_dir = temp.path().AppendASCII("directory");
  ASSERT_TRUE(base::CreateDirectory(inner_dir));
  base::FilePath sub_dir = inner_dir.AppendASCII("subdir");
  ASSERT_TRUE(base::CreateDirectory(sub_dir));
  base::FilePath inner_file = inner_dir.AppendASCII("inner");
  base::FilePath outer_file = temp.path().AppendASCII("outer");
  ASSERT_TRUE(base::WriteFile(outer_file, "X", 1));
  ASSERT_TRUE(base::WriteFile(inner_file, "X", 1));
  std::string extension_id = id_util::GenerateId("test");

#if defined(OS_POSIX)
  base::FilePath symlink_file = inner_dir.AppendASCII("symlink");
  base::CreateSymbolicLink(
      base::FilePath().AppendASCII("..").AppendASCII("outer"),
      symlink_file);
#endif

  // A non-packing extension should be able to access the file within the
  // directory.
  ExtensionResource r1(extension_id, inner_dir,
                       base::FilePath().AppendASCII("inner"));
  EXPECT_FALSE(r1.GetFilePath().empty());

  // ... but not a relative path that walks out of |inner_dir|.
  ExtensionResource r2(extension_id, inner_dir,
                       base::FilePath().AppendASCII("..").AppendASCII("outer"));
  EXPECT_TRUE(r2.GetFilePath().empty());

  // A packing extension should also be able to access the file within the
  // directory.
  ExtensionResource r3(extension_id, inner_dir,
                       base::FilePath().AppendASCII("inner"));
  r3.set_follow_symlinks_anywhere();
  EXPECT_FALSE(r3.GetFilePath().empty());

  // ... but, again, not a relative path that walks out of |inner_dir|.
  ExtensionResource r4(extension_id, inner_dir,
                       base::FilePath().AppendASCII("..").AppendASCII("outer"));
  r4.set_follow_symlinks_anywhere();
  EXPECT_TRUE(r4.GetFilePath().empty());

  // ... and not even when clever current-directory syntax is present. Note
  // that the path for this test case can't start with the current directory
  // component due to quirks in FilePath::Append(), and the path must exist.
  ExtensionResource r4a(
      extension_id, inner_dir,
      base::FilePath().AppendASCII("subdir").AppendASCII(".").AppendASCII("..").
      AppendASCII("..").AppendASCII("outer"));
  r4a.set_follow_symlinks_anywhere();
  EXPECT_TRUE(r4a.GetFilePath().empty());

#if defined(OS_POSIX)
  // The non-packing extension should also not be able to access a resource that
  // symlinks out of the directory.
  ExtensionResource r5(extension_id, inner_dir,
                       base::FilePath().AppendASCII("symlink"));
  EXPECT_TRUE(r5.GetFilePath().empty());

  // ... but a packing extension can.
  ExtensionResource r6(extension_id, inner_dir,
                       base::FilePath().AppendASCII("symlink"));
  r6.set_follow_symlinks_anywhere();
  EXPECT_FALSE(r6.GetFilePath().empty());
#endif
}

TEST(ExtensionResourceTest, CreateWithAllResourcesOnDisk) {
  base::ScopedTempDir temp;
  ASSERT_TRUE(temp.CreateUniqueTempDir());

  // Create resource in the extension root.
  const char* filename = "res.ico";
  base::FilePath root_resource = temp.path().AppendASCII(filename);
  std::string data = "some foo";
  ASSERT_TRUE(base::WriteFile(root_resource, data.c_str(), data.length()));

  // Create l10n resources (for current locale and its parents).
  base::FilePath l10n_path =
      temp.path().Append(kLocaleFolder);
  ASSERT_TRUE(base::CreateDirectory(l10n_path));

  std::vector<std::string> locales;
  l10n_util::GetParentLocales(l10n_util::GetApplicationLocale(std::string()),
                              &locales);
  ASSERT_FALSE(locales.empty());
  for (size_t i = 0; i < locales.size(); i++) {
    base::FilePath make_path;
    make_path = l10n_path.AppendASCII(locales[i]);
    ASSERT_TRUE(base::CreateDirectory(make_path));
    ASSERT_TRUE(base::WriteFile(make_path.AppendASCII(filename),
        data.c_str(), data.length()));
  }

  base::FilePath path;
  std::string extension_id = id_util::GenerateId("test");
  ExtensionResource resource(extension_id, temp.path(),
                             base::FilePath().AppendASCII(filename));
  base::FilePath resolved_path = resource.GetFilePath();

  base::FilePath expected_path;
  // Expect default path only, since fallback logic is disabled.
  // See http://crbug.com/27359.
  expected_path = base::MakeAbsoluteFilePath(root_resource);
  ASSERT_FALSE(expected_path.empty());

  EXPECT_EQ(ToLower(expected_path.value()), ToLower(resolved_path.value()));
  EXPECT_EQ(ToLower(temp.path().value()),
            ToLower(resource.extension_root().value()));
  EXPECT_EQ(ToLower(base::FilePath().AppendASCII(filename).value()),
            ToLower(resource.relative_path().value()));
}

}  // namespace extensions
