// Copyright 2013 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 "base/files/file_path.h"
#include "chrome/common/extensions/api/plugins/plugins_handler.h"
#include "chrome/common/extensions/sync_helper.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace extensions {

namespace keys = manifest_keys;
namespace errors = manifest_errors;

class ExtensionSyncTypeTest : public testing::Test {
 protected:
  enum SyncTestExtensionType {
    EXTENSION,
    APP,
    USER_SCRIPT,
    THEME
  };

  static scoped_refptr<Extension> MakeSyncTestExtensionWithPluginPermission(
      SyncTestExtensionType type,
      const GURL& update_url,
      const GURL& launch_url,
      Manifest::Location location,
      const base::FilePath& extension_path,
      int creation_flags,
      int num_plugins,
      bool has_plugin_permission,
      const std::string& expected_error) {
    base::DictionaryValue source;
    source.SetString(keys::kName, "PossiblySyncableExtension");
    source.SetString(keys::kVersion, "0.0.0.0");
    if (type == APP)
      source.SetString(keys::kApp, "true");
    if (type == THEME)
      source.Set(keys::kTheme, new base::DictionaryValue());
    if (!update_url.is_empty()) {
      source.SetString(keys::kUpdateURL, update_url.spec());
    }
    if (!launch_url.is_empty()) {
      source.SetString(keys::kLaunchWebURL, launch_url.spec());
    }
    if (type != THEME) {
      source.SetBoolean(keys::kConvertedFromUserScript, type == USER_SCRIPT);
      if (num_plugins >= 0) {
        base::ListValue* plugins = new base::ListValue();
        for (int i = 0; i < num_plugins; ++i) {
          base::DictionaryValue* plugin = new base::DictionaryValue();
          plugin->SetString(keys::kPluginsPath, std::string());
          plugins->Set(i, plugin);
        }
        source.Set(keys::kPlugins, plugins);
      }
    }
    if (has_plugin_permission) {
      ListValue* plugins = new ListValue();
      plugins->Set(0, new StringValue("plugin"));
      source.Set(keys::kPermissions, plugins);
    }

    std::string error;
    scoped_refptr<Extension> extension = Extension::Create(
        extension_path, location, source, creation_flags, &error);
    if (expected_error == "")
      EXPECT_TRUE(extension.get());
    else
      EXPECT_FALSE(extension.get());
    EXPECT_EQ(expected_error, error);
    return extension;
  }

  static scoped_refptr<Extension> MakeSyncTestExtension(
      SyncTestExtensionType type,
      const GURL& update_url,
      const GURL& launch_url,
      Manifest::Location location,
      const base::FilePath& extension_path,
      int creation_flags) {
    return MakeSyncTestExtensionWithPluginPermission(
        type, update_url, launch_url, location, extension_path,
        creation_flags, -1, false, "");
  }

  static const char kValidUpdateUrl1[];
  static const char kValidUpdateUrl2[];
};

const char ExtensionSyncTypeTest::kValidUpdateUrl1[] =
    "http://clients2.google.com/service/update2/crx";
const char ExtensionSyncTypeTest::kValidUpdateUrl2[] =
    "https://clients2.google.com/service/update2/crx";

TEST_F(ExtensionSyncTypeTest, NormalExtensionNoUpdateUrl) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, UserScriptValidUpdateUrl) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(USER_SCRIPT, GURL(kValidUpdateUrl1), GURL(),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, UserScriptNoUpdateUrl) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(USER_SCRIPT, GURL(), GURL(),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, ThemeNoUpdateUrl) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(THEME, GURL(), GURL(),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
  EXPECT_FALSE(sync_helper::IsSyncableApp(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, AppWithLaunchUrl) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(EXTENSION, GURL(), GURL("http://www.google.com"),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_TRUE(sync_helper::IsSyncableApp(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, ExtensionExternal) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
                            Manifest::EXTERNAL_PREF, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, UserScriptThirdPartyUpdateUrl) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(
          USER_SCRIPT, GURL("http://third-party.update_url.com"), GURL(),
          Manifest::INTERNAL, base::FilePath(), Extension::NO_FLAGS));
  EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, OnlyDisplayAppsInLauncher) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));

  EXPECT_FALSE(extension->ShouldDisplayInAppLauncher());
  EXPECT_FALSE(extension->ShouldDisplayInNewTabPage());

  scoped_refptr<Extension> app(
      MakeSyncTestExtension(APP, GURL(), GURL("http://www.google.com"),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
  EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
}

TEST_F(ExtensionSyncTypeTest, DisplayInXManifestProperties) {
  base::DictionaryValue manifest;
  manifest.SetString(keys::kName, "TestComponentApp");
  manifest.SetString(keys::kVersion, "0.0.0.0");
  manifest.SetString(keys::kApp, "true");
  manifest.SetString(keys::kPlatformAppBackgroundPage, std::string());

  std::string error;
  scoped_refptr<Extension> app;

  // Default to true.
  app = Extension::Create(
      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
  EXPECT_EQ(error, std::string());
  EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
  EXPECT_TRUE(app->ShouldDisplayInNewTabPage());

  // Value display_in_NTP defaults to display_in_launcher.
  manifest.SetBoolean(keys::kDisplayInLauncher, false);
  app = Extension::Create(
      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
  EXPECT_EQ(error, std::string());
  EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
  EXPECT_FALSE(app->ShouldDisplayInNewTabPage());

  // Value display_in_NTP = true overriding display_in_launcher = false.
  manifest.SetBoolean(keys::kDisplayInNewTabPage, true);
  app = Extension::Create(
      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
  EXPECT_EQ(error, std::string());
  EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
  EXPECT_TRUE(app->ShouldDisplayInNewTabPage());

  // Value display_in_NTP = false only, overrides default = true.
  manifest.Remove(keys::kDisplayInLauncher, NULL);
  manifest.SetBoolean(keys::kDisplayInNewTabPage, false);
  app = Extension::Create(
      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
  EXPECT_EQ(error, std::string());
  EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
  EXPECT_FALSE(app->ShouldDisplayInNewTabPage());

  // Error checking.
  manifest.SetString(keys::kDisplayInNewTabPage, "invalid");
  app = Extension::Create(
      base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
  EXPECT_EQ(error, std::string(errors::kInvalidDisplayInNewTabPage));
}

TEST_F(ExtensionSyncTypeTest, OnlySyncInternal) {
  scoped_refptr<Extension> extension_internal(
      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_TRUE(sync_helper::IsSyncable(extension_internal.get()));

  scoped_refptr<Extension> extension_noninternal(
      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
                            Manifest::COMPONENT, base::FilePath(),
                            Extension::NO_FLAGS));
  EXPECT_FALSE(sync_helper::IsSyncable(extension_noninternal.get()));
}

TEST_F(ExtensionSyncTypeTest, DontSyncDefault) {
  scoped_refptr<Extension> extension_default(
      MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
                            Manifest::INTERNAL, base::FilePath(),
                            Extension::WAS_INSTALLED_BY_DEFAULT));
  EXPECT_FALSE(sync_helper::IsSyncable(extension_default.get()));
}

// These plugin tests don't make sense on Chrome OS, where extension plugins
// are not allowed.
#if !defined(OS_CHROMEOS)
TEST_F(ExtensionSyncTypeTest, ExtensionWithEmptyPlugins) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtensionWithPluginPermission(
          EXTENSION, GURL(), GURL(),
          Manifest::INTERNAL, base::FilePath(),
          Extension::NO_FLAGS, 0, false, ""));
  if (extension.get())
    EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, ExtensionWithPlugin) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtensionWithPluginPermission(
          EXTENSION, GURL(), GURL(),
          Manifest::INTERNAL, base::FilePath(),
          Extension::NO_FLAGS, 1, false, ""));
  if (extension.get())
    EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, ExtensionWithTwoPlugins) {
  scoped_refptr<Extension> extension(
      MakeSyncTestExtensionWithPluginPermission(
          EXTENSION, GURL(), GURL(),
          Manifest::INTERNAL, base::FilePath(),
          Extension::NO_FLAGS, 2, false, ""));
  if (extension.get())
    EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
}

TEST_F(ExtensionSyncTypeTest, ExtensionWithPluginPermission) {
  // Specifying the "plugin" permission in the manifest is an error.
  scoped_refptr<Extension> extension(
      MakeSyncTestExtensionWithPluginPermission(
          EXTENSION, GURL(), GURL(),
          Manifest::INTERNAL, base::FilePath(),
          Extension::NO_FLAGS, 0, true,
          ErrorUtils::FormatErrorMessage(
              errors::kPermissionNotAllowedInManifest, "plugin")));
}

#endif // !defined(OS_CHROMEOS)

}  // namespace extensions
