// 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 <vector>

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/prefs/chrome_pref_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/feature_switch.h"
#include "net/base/filename_util.h"

using extensions::FeatureSwitch;

// This file contains high-level startup tests for the extensions system. We've
// had many silly bugs where command line flags did not get propagated correctly
// into the services, so we didn't start correctly.

class ExtensionStartupTestBase : public InProcessBrowserTest {
 public:
  ExtensionStartupTestBase() : unauthenticated_load_allowed_(true) {
    num_expected_extensions_ = 3;
  }

 protected:
  // InProcessBrowserTest
  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    if (load_extensions_.empty()) {
      // If no |load_extensions_| were specified, allow unauthenticated
      // extension settings to be loaded from Preferences as if they had been
      // authenticated correctly before they were handed to the ExtensionSystem.
      command_line->AppendSwitchASCII(
          switches::kForceFieldTrials,
          base::StringPrintf(
              "%s/%s/",
              chrome_prefs::internals::kSettingsEnforcementTrialName,
              chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement));
#if defined(OFFICIAL_BUILD) && defined(OS_WIN)
      // In Windows official builds, it is not possible to disable settings
      // authentication.
      unauthenticated_load_allowed_ = false;
#endif
    } else {
      base::FilePath::StringType paths = JoinString(load_extensions_, ',');
      command_line->AppendSwitchNative(switches::kLoadExtension,
                                       paths);
      command_line->AppendSwitch(switches::kDisableExtensionsFileAccessCheck);
    }
  }

  virtual bool SetUpUserDataDirectory() OVERRIDE {
    base::FilePath profile_dir;
    PathService::Get(chrome::DIR_USER_DATA, &profile_dir);
    profile_dir = profile_dir.AppendASCII(TestingProfile::kTestUserProfileDir);
    base::CreateDirectory(profile_dir);

    preferences_file_ = profile_dir.Append(chrome::kPreferencesFilename);
    user_scripts_dir_ = profile_dir.AppendASCII("User Scripts");
    extensions_dir_ = profile_dir.AppendASCII("Extensions");

    if (load_extensions_.empty()) {
      base::FilePath src_dir;
      PathService::Get(chrome::DIR_TEST_DATA, &src_dir);
      src_dir = src_dir.AppendASCII("extensions").AppendASCII("good");

      base::CopyFile(src_dir.Append(chrome::kPreferencesFilename),
                     preferences_file_);
      base::CopyDirectory(src_dir.AppendASCII("Extensions"),
                          profile_dir, true);  // recursive
    }
    return true;
  }

  virtual void TearDown() {
    EXPECT_TRUE(base::DeleteFile(preferences_file_, false));

    // TODO(phajdan.jr): Check return values of the functions below, carefully.
    base::DeleteFile(user_scripts_dir_, true);
    base::DeleteFile(extensions_dir_, true);

    InProcessBrowserTest::TearDown();
  }

  void WaitForServicesToStart(int num_expected_extensions,
                              bool expect_extensions_enabled) {
    ExtensionService* service = extensions::ExtensionSystem::Get(
        browser()->profile())->extension_service();

    // Count the number of non-component extensions.
    int found_extensions = 0;
    for (extensions::ExtensionSet::const_iterator it =
             service->extensions()->begin();
         it != service->extensions()->end(); ++it) {
      if ((*it)->location() != extensions::Manifest::COMPONENT)
        found_extensions++;
    }

    if (!unauthenticated_load_allowed_)
      num_expected_extensions = 0;

    ASSERT_EQ(static_cast<uint32>(num_expected_extensions),
              static_cast<uint32>(found_extensions));
    ASSERT_EQ(expect_extensions_enabled, service->extensions_enabled());

    content::WindowedNotificationObserver user_scripts_observer(
        chrome::NOTIFICATION_USER_SCRIPTS_UPDATED,
        content::NotificationService::AllSources());
    extensions::UserScriptMaster* master =
        extensions::ExtensionSystem::Get(browser()->profile())->
            user_script_master();
    if (!master->ScriptsReady())
      user_scripts_observer.Wait();
    ASSERT_TRUE(master->ScriptsReady());
  }

  void TestInjection(bool expect_css, bool expect_script) {
    if (!unauthenticated_load_allowed_) {
      expect_css = false;
      expect_script = false;
    }

    // Load a page affected by the content script and test to see the effect.
    base::FilePath test_file;
    PathService::Get(chrome::DIR_TEST_DATA, &test_file);
    test_file = test_file.AppendASCII("extensions")
                         .AppendASCII("test_file.html");

    ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_file));

    bool result = false;
    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
        browser()->tab_strip_model()->GetActiveWebContents(),
        "window.domAutomationController.send("
        "    document.defaultView.getComputedStyle(document.body, null)."
        "    getPropertyValue('background-color') == 'rgb(245, 245, 220)')",
        &result));
    EXPECT_EQ(expect_css, result);

    result = false;
    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
        browser()->tab_strip_model()->GetActiveWebContents(),
        "window.domAutomationController.send(document.title == 'Modified')",
        &result));
    EXPECT_EQ(expect_script, result);
  }

  base::FilePath preferences_file_;
  base::FilePath extensions_dir_;
  base::FilePath user_scripts_dir_;
  // True unless unauthenticated extension settings are not allowed to be
  // loaded in this configuration.
  bool unauthenticated_load_allowed_;
  // Extensions to load from the command line.
  std::vector<base::FilePath::StringType> load_extensions_;

  int num_expected_extensions_;
};


// ExtensionsStartupTest
// Ensures that we can startup the browser with --enable-extensions and some
// extensions installed and see them run and do basic things.
typedef ExtensionStartupTestBase ExtensionsStartupTest;

IN_PROC_BROWSER_TEST_F(ExtensionsStartupTest, Test) {
  WaitForServicesToStart(num_expected_extensions_, true);
  TestInjection(true, true);
}

// Sometimes times out on Mac.  http://crbug.com/48151
#if defined(OS_MACOSX)
#define MAYBE_NoFileAccess DISABLED_NoFileAccess
#else
#define MAYBE_NoFileAccess NoFileAccess
#endif
// Tests that disallowing file access on an extension prevents it from injecting
// script into a page with a file URL.
IN_PROC_BROWSER_TEST_F(ExtensionsStartupTest, MAYBE_NoFileAccess) {
  WaitForServicesToStart(num_expected_extensions_, true);

  // Keep a separate list of extensions for which to disable file access, since
  // doing so reloads them.
  std::vector<const extensions::Extension*> extension_list;

  extensions::ExtensionRegistry* registry =
      extensions::ExtensionRegistry::Get(browser()->profile());
  for (extensions::ExtensionSet::const_iterator it =
           registry->enabled_extensions().begin();
       it != registry->enabled_extensions().end(); ++it) {
    if ((*it)->location() == extensions::Manifest::COMPONENT)
      continue;
    if (extensions::util::AllowFileAccess((*it)->id(), browser()->profile()))
      extension_list.push_back(it->get());
  }

  for (size_t i = 0; i < extension_list.size(); ++i) {
    content::WindowedNotificationObserver user_scripts_observer(
        chrome::NOTIFICATION_USER_SCRIPTS_UPDATED,
        content::NotificationService::AllSources());
    extensions::util::SetAllowFileAccess(
        extension_list[i]->id(), browser()->profile(), false);
    user_scripts_observer.Wait();
  }

  TestInjection(false, false);
}

// ExtensionsLoadTest
// Ensures that we can startup the browser with --load-extension and see them
// run.
class ExtensionsLoadTest : public ExtensionStartupTestBase {
 public:
  ExtensionsLoadTest() {
    base::FilePath one_extension_path;
    PathService::Get(chrome::DIR_TEST_DATA, &one_extension_path);
    one_extension_path = one_extension_path
        .AppendASCII("extensions")
        .AppendASCII("good")
        .AppendASCII("Extensions")
        .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
        .AppendASCII("1.0.0.0");
    load_extensions_.push_back(one_extension_path.value());
  }
};

// Fails inconsistently on Linux x64. http://crbug.com/80961
// TODO(dpapad): Has not failed since October 2011, let's reenable, monitor
// and act accordingly.
IN_PROC_BROWSER_TEST_F(ExtensionsLoadTest, Test) {
  WaitForServicesToStart(1, true);
  TestInjection(true, true);
}

// ExtensionsLoadMultipleTest
// Ensures that we can startup the browser with multiple extensions
// via --load-extension=X1,X2,X3.
class ExtensionsLoadMultipleTest : public ExtensionStartupTestBase {
 public:
  ExtensionsLoadMultipleTest() {
    base::FilePath one_extension_path;
    PathService::Get(chrome::DIR_TEST_DATA, &one_extension_path);
    one_extension_path = one_extension_path
        .AppendASCII("extensions")
        .AppendASCII("good")
        .AppendASCII("Extensions")
        .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
        .AppendASCII("1.0.0.0");
    load_extensions_.push_back(one_extension_path.value());

    base::FilePath second_extension_path;
    PathService::Get(chrome::DIR_TEST_DATA, &second_extension_path);
    second_extension_path = second_extension_path
        .AppendASCII("extensions")
        .AppendASCII("app");
    load_extensions_.push_back(second_extension_path.value());

    base::FilePath third_extension_path;
    PathService::Get(chrome::DIR_TEST_DATA, &third_extension_path);
    third_extension_path = third_extension_path
        .AppendASCII("extensions")
        .AppendASCII("app1");
    load_extensions_.push_back(third_extension_path.value());

    base::FilePath fourth_extension_path;
    PathService::Get(chrome::DIR_TEST_DATA, &fourth_extension_path);
    fourth_extension_path = fourth_extension_path
        .AppendASCII("extensions")
        .AppendASCII("app2");
    load_extensions_.push_back(fourth_extension_path.value());
  }
};

IN_PROC_BROWSER_TEST_F(ExtensionsLoadMultipleTest, Test) {
  WaitForServicesToStart(4, true);
  TestInjection(true, true);
}
