// 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 "chrome/browser/extensions/error_console/error_console.h"

#include <stddef.h>

#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_action_runner.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/prefs/pref_service.h"
#include "extensions/browser/extension_error.h"
#include "extensions/common/constants.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/manifest_constants.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

using base::string16;
using base::UTF8ToUTF16;

namespace extensions {

namespace {

const char kTestingPage[] = "/extensions/test_file.html";
const char kAnonymousFunction[] = "(anonymous function)";
const char* const kBackgroundPageName =
    extensions::kGeneratedBackgroundPageFilename;
const int kNoFlags = 0;

const StackTrace& GetStackTraceFromError(const ExtensionError* error) {
  CHECK(error->type() == ExtensionError::RUNTIME_ERROR);
  return (static_cast<const RuntimeError*>(error))->stack_trace();
}

// Verify that a given |frame| has the proper source and function name.
void CheckStackFrame(const StackFrame& frame,
                     const std::string& source,
                     const std::string& function) {
  EXPECT_EQ(base::UTF8ToUTF16(source), frame.source);
  EXPECT_EQ(base::UTF8ToUTF16(function), frame.function);
}

// Verify that all properties of a given |frame| are correct. Overloaded because
// we commonly do not check line/column numbers, as they are too likely
// to change.
void CheckStackFrame(const StackFrame& frame,
                     const std::string& source,
                     const std::string& function,
                     size_t line_number,
                     size_t column_number) {
  CheckStackFrame(frame, source, function);
  EXPECT_EQ(line_number, frame.line_number);
  EXPECT_EQ(column_number, frame.column_number);
}

// Verify that all properties of a given |error| are correct.
void CheckError(const ExtensionError* error,
                ExtensionError::Type type,
                const std::string& id,
                const std::string& source,
                bool from_incognito,
                const std::string& message) {
  ASSERT_TRUE(error);
  EXPECT_EQ(type, error->type());
  EXPECT_EQ(id, error->extension_id());
  EXPECT_EQ(base::UTF8ToUTF16(source), error->source());
  EXPECT_EQ(from_incognito, error->from_incognito());
  EXPECT_EQ(base::UTF8ToUTF16(message), error->message());
}

// Verify that all properties of a JS runtime error are correct.
void CheckRuntimeError(const ExtensionError* error,
                       const std::string& id,
                       const std::string& source,
                       bool from_incognito,
                       const std::string& message,
                       logging::LogSeverity level,
                       const GURL& context,
                       size_t expected_stack_size) {
  CheckError(error,
             ExtensionError::RUNTIME_ERROR,
             id,
             source,
             from_incognito,
             message);

  const RuntimeError* runtime_error = static_cast<const RuntimeError*>(error);
  EXPECT_EQ(level, runtime_error->level());
  EXPECT_EQ(context, runtime_error->context_url());
  EXPECT_EQ(expected_stack_size, runtime_error->stack_trace().size());
}

void CheckManifestError(const ExtensionError* error,
                        const std::string& id,
                        const std::string& message,
                        const std::string& manifest_key,
                        const std::string& manifest_specific) {
  CheckError(error,
             ExtensionError::MANIFEST_ERROR,
             id,
             // source is always the manifest for ManifestErrors.
             base::FilePath(kManifestFilename).AsUTF8Unsafe(),
             false,  // manifest errors are never from incognito.
             message);

  const ManifestError* manifest_error =
      static_cast<const ManifestError*>(error);
  EXPECT_EQ(base::UTF8ToUTF16(manifest_key), manifest_error->manifest_key());
  EXPECT_EQ(base::UTF8ToUTF16(manifest_specific),
            manifest_error->manifest_specific());
}

}  // namespace

class ErrorConsoleBrowserTest : public ExtensionBrowserTest {
 public:
  ErrorConsoleBrowserTest() : error_console_(NULL) { }
  ~ErrorConsoleBrowserTest() override {}

 protected:
  // A helper class in order to wait for the proper number of errors to be
  // caught by the ErrorConsole. This will run the MessageLoop until a given
  // number of errors are observed.
  // Usage:
  //   ...
  //   ErrorObserver observer(3, error_console);
  //   <Cause three errors...>
  //   observer.WaitForErrors();
  //   <Perform any additional checks...>
  class ErrorObserver : public ErrorConsole::Observer {
   public:
    ErrorObserver(size_t errors_expected, ErrorConsole* error_console)
        : errors_observed_(0),
          errors_expected_(errors_expected),
          waiting_(false),
          error_console_(error_console) {
      error_console_->AddObserver(this);
    }
    virtual ~ErrorObserver() {
      if (error_console_)
        error_console_->RemoveObserver(this);
    }

    // ErrorConsole::Observer implementation.
    void OnErrorAdded(const ExtensionError* error) override {
      ++errors_observed_;
      if (errors_observed_ >= errors_expected_) {
        if (waiting_)
          base::RunLoop::QuitCurrentWhenIdleDeprecated();
      }
    }

    void OnErrorConsoleDestroyed() override { error_console_ = NULL; }

    // Spin until the appropriate number of errors have been observed.
    void WaitForErrors() {
      if (errors_observed_ < errors_expected_) {
        waiting_ = true;
        content::RunMessageLoop();
        waiting_ = false;
      }
    }

   private:
    size_t errors_observed_;
    size_t errors_expected_;
    bool waiting_;

    ErrorConsole* error_console_;

    DISALLOW_COPY_AND_ASSIGN(ErrorObserver);
  };

  // The type of action which we take after we load an extension in order to
  // cause any errors.
  enum Action {
    // Navigate to a (non-chrome) page to allow a content script to run.
    ACTION_NAVIGATE,
    // Simulate a browser action click.
    ACTION_BROWSER_ACTION,
    // Navigate to the new tab page.
    ACTION_NEW_TAB,
    // Do nothing (errors will be caused by a background script,
    // or by a manifest/loading warning).
    ACTION_NONE
  };

  void SetUpInProcessBrowserTestFixture() override {
    ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();

    // We need to enable the ErrorConsole FeatureSwitch in order to collect
    // errors. This should be enabled on any channel <= Dev, but let's make
    // sure (in case a test is running on, e.g., a beta channel).
    FeatureSwitch::error_console()->SetOverrideValue(
        FeatureSwitch::OVERRIDE_ENABLED);
  }

  void SetUpOnMainThread() override {
    ExtensionBrowserTest::SetUpOnMainThread();

    // Errors are only kept if we have Developer Mode enabled.
    profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);

    error_console_ = ErrorConsole::Get(profile());
    CHECK(error_console_);

    test_data_dir_ = test_data_dir_.AppendASCII("error_console");
  }

  const GURL& GetTestURL() {
    if (test_url_.is_empty()) {
      CHECK(embedded_test_server()->Start());
      test_url_ = embedded_test_server()->GetURL(kTestingPage);
    }
    return test_url_;
  }

  // Load the extension at |path|, take the specified |action|, and wait for
  // |expected_errors| errors. Populate |extension| with a pointer to the loaded
  // extension.
  void LoadExtensionAndCheckErrors(
      const std::string& path,
      int flags,
      size_t errors_expected,
      Action action,
      const Extension** extension) {
    ErrorObserver observer(errors_expected, error_console_);
    *extension =
        LoadExtensionWithFlags(test_data_dir_.AppendASCII(path), flags);
    ASSERT_TRUE(*extension);

    switch (action) {
      case ACTION_NAVIGATE: {
        ui_test_utils::NavigateToURL(browser(), GetTestURL());
        break;
      }
      case ACTION_BROWSER_ACTION: {
        ExtensionActionRunner::GetForWebContents(
            browser()->tab_strip_model()->GetActiveWebContents())
            ->RunAction(*extension, true);
        break;
      }
      case ACTION_NEW_TAB: {
        ui_test_utils::NavigateToURL(browser(),
                                     GURL(chrome::kChromeUINewTabURL));
        break;
      }
      case ACTION_NONE:
        break;
      default:
        NOTREACHED();
    }

    observer.WaitForErrors();

    // We should only have errors for a single extension, or should have no
    // entries, if no errors were expected.
    ASSERT_EQ(errors_expected > 0 ? 1u : 0u,
              error_console()->get_num_entries_for_test());
    ASSERT_EQ(
        errors_expected,
        error_console()->GetErrorsForExtension((*extension)->id()).size());
  }

  ErrorConsole* error_console() { return error_console_; }

 private:
  // The URL used in testing for simple page navigations.
  GURL test_url_;

  // Weak reference to the ErrorConsole.
  ErrorConsole* error_console_;
};

// Test to ensure that we are successfully reporting manifest errors as an
// extension is installed.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, ReportManifestErrors) {
  const Extension* extension = NULL;
  // We expect two errors - one for an invalid permission, and a second for
  // an unknown key.
  LoadExtensionAndCheckErrors("manifest_warnings",
                              ExtensionBrowserTest::kFlagIgnoreManifestWarnings,
                              2,
                              ACTION_NONE,
                              &extension);

  const ErrorList& errors =
      error_console()->GetErrorsForExtension(extension->id());

  // Unfortunately, there's not always a hard guarantee of order in parsing the
  // manifest, so there's not a definitive order in which these errors may
  // occur. As such, we need to determine which error corresponds to which
  // expected error.
  const ExtensionError* permissions_error = NULL;
  const ExtensionError* unknown_key_error = NULL;
  const char kFakeKey[] = "not_a_real_key";
  for (const auto& error : errors) {
    ASSERT_EQ(ExtensionError::MANIFEST_ERROR, error->type());
    std::string utf8_key = base::UTF16ToUTF8(
        (static_cast<const ManifestError*>(error.get()))->manifest_key());
    if (utf8_key == manifest_keys::kPermissions)
      permissions_error = error.get();
    else if (utf8_key == kFakeKey)
      unknown_key_error = error.get();
  }
  ASSERT_TRUE(permissions_error);
  ASSERT_TRUE(unknown_key_error);

  const char kFakePermission[] = "not_a_real_permission";
  CheckManifestError(permissions_error,
                     extension->id(),
                     ErrorUtils::FormatErrorMessage(
                         manifest_errors::kPermissionUnknownOrMalformed,
                         kFakePermission),
                     manifest_keys::kPermissions,
                     kFakePermission);

  CheckManifestError(unknown_key_error,
                     extension->id(),
                     ErrorUtils::FormatErrorMessage(
                         manifest_errors::kUnrecognizedManifestKey,
                         kFakeKey),
                     kFakeKey,
                     std::string());
}

// Test that we do not store any errors unless the Developer Mode switch is
// toggled on the profile.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest,
                       DontStoreErrorsWithoutDeveloperMode) {
  profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, false);

  const Extension* extension = NULL;
  // Same test as ReportManifestErrors, except we don't expect any errors since
  // we disable Developer Mode.
  LoadExtensionAndCheckErrors("manifest_warnings",
                              ExtensionBrowserTest::kFlagIgnoreManifestWarnings,
                              0,
                              ACTION_NONE,
                              &extension);

  // Now if we enable developer mode, the errors should be reported...
  profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);
  EXPECT_EQ(2u, error_console()->GetErrorsForExtension(extension->id()).size());

  // ... and if we disable it again, all errors which we were holding should be
  // removed.
  profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, false);
  EXPECT_EQ(0u, error_console()->GetErrorsForExtension(extension->id()).size());
}

// Load an extension which, upon visiting any page, first sends out a console
// log, and then crashes with a JS TypeError.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest,
                       ContentScriptLogAndRuntimeError) {
  const Extension* extension = NULL;
  LoadExtensionAndCheckErrors(
      "content_script_log_and_runtime_error",
      kNoFlags,
      2u,  // Two errors: A log message and a JS type error.
      ACTION_NAVIGATE,
      &extension);

  std::string script_url =
      extension->GetResourceURL("content_script.js").spec();

  const ErrorList& errors =
      error_console()->GetErrorsForExtension(extension->id());

  // The extension logs a message with console.log(), then another with
  // console.warn(), and then triggers a TypeError.
  // There should be exactly two errors (the warning and the TypeError). The
  // error console ignores logs - this would tend to be too noisy, and doesn't
  // jive with the big `ERRORS` button in the UI.
  // See https://crbug.com/837401.
  ASSERT_EQ(2u, errors.size());

  // The first error should be a console log.
  CheckRuntimeError(errors[0].get(), extension->id(),
                    script_url,  // The source should be the content script url.
                    false,       // Not from incognito.
                    "warned message",  // The error message is the log.
                    logging::LOG_WARNING,
                    GetTestURL(),  // Content scripts run in the web page.
                    2u);

  const StackTrace& stack_trace1 = GetStackTraceFromError(errors[0].get());
  CheckStackFrame(stack_trace1[0], script_url,
                  "warnMessage",  // function name
                  10u,            // line number
                  11u /* column number */);

  CheckStackFrame(stack_trace1[1], script_url, kAnonymousFunction, 14u, 1u);

  // The second error should be a runtime error.
  CheckRuntimeError(errors[1].get(), extension->id(), script_url,
                    false,  // not from incognito
                    "Uncaught TypeError: "
                    "Cannot set property 'foo' of undefined",
                    logging::LOG_ERROR,  // JS errors are always ERROR level.
                    GetTestURL(), 1u);

  const StackTrace& stack_trace2 = GetStackTraceFromError(errors[1].get());
  CheckStackFrame(stack_trace2[0], script_url, kAnonymousFunction, 17u, 1u);
}

// Catch an error from a BrowserAction; this is more complex than a content
// script error, since browser actions are routed through our own code.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BrowserActionRuntimeError) {
  const Extension* extension = NULL;
  LoadExtensionAndCheckErrors(
      "browser_action_runtime_error",
      kNoFlags,
      1u,  // One error: A reference error from within the browser action.
      ACTION_BROWSER_ACTION,
      &extension);

  std::string script_url =
      extension->GetResourceURL("browser_action.js").spec();

  const ErrorList& errors =
      error_console()->GetErrorsForExtension(extension->id());

  std::string message;
  bool use_native_bindings =
      base::FeatureList::IsEnabled(features::kNativeCrxBindings);
  if (use_native_bindings) {
    // TODO(devlin): The specific event name (here, 'browserAction.onClicked')
    // may or may not be worth preserving. In most cases, it's unnecessary with
    // the line number, but it could be useful in some cases.
    message =
        "Error in event handler: ReferenceError: "
        "baz is not defined";
  } else {
    message =
        "Error in event handler for browserAction.onClicked: "
        "ReferenceError: baz is not defined";
  }

  CheckRuntimeError(errors[0].get(), extension->id(), script_url,
                    false,  // not incognito
                    message, logging::LOG_ERROR,
                    extension->GetResourceURL(kBackgroundPageName), 1u);

  const StackTrace& stack_trace = GetStackTraceFromError(errors[0].get());
  // Note: This test used to have a stack trace of length 6 that contains stack
  // frames in the extension code, but since crbug.com/404406 was fixed only
  // stack frames within user-defined extension code are printed.

  CheckStackFrame(stack_trace[0], script_url, kAnonymousFunction);
}

// Test that we can catch an error for calling an API with improper arguments.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BadAPIArgumentsRuntimeError) {
  const Extension* extension = NULL;
  LoadExtensionAndCheckErrors(
      "bad_api_arguments_runtime_error",
      kNoFlags,
      1,  // One error: call an API with improper arguments.
      ACTION_NONE,
      &extension);

  const ErrorList& errors =
      error_console()->GetErrorsForExtension(extension->id());

  std::string source;
  std::string message;
  bool use_native_bindings =
      base::FeatureList::IsEnabled(features::kNativeCrxBindings);
  if (use_native_bindings) {
    source = extension->GetResourceURL("background.js").spec();
    message =
        "Uncaught TypeError: Error in invocation of "
        "tabs.get(integer tabId, function callback): "
        "No matching signature.";
  } else {
    // API calls are checked in schemaUtils.js with JS bindings.
    source = "extensions::" + std::string(kSchemaUtils);
    message =
        "Uncaught Error: Invocation of form "
        "tabs.get(string, function) doesn't match definition "
        "tabs.get(integer tabId, function callback)";
  }

  CheckRuntimeError(errors[0].get(), extension->id(), source,
                    false,  // not incognito
                    message, logging::LOG_ERROR,
                    extension->GetResourceURL(kBackgroundPageName), 1u);

  const StackTrace& stack_trace = GetStackTraceFromError(errors[0].get());
  ASSERT_EQ(1u, stack_trace.size());
  CheckStackFrame(stack_trace[0], source, kAnonymousFunction);
}

// Test that we catch an error when we try to call an API method without
// permission.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BadAPIPermissionsRuntimeError) {
  const Extension* extension = NULL;
  LoadExtensionAndCheckErrors(
      "bad_api_permissions_runtime_error",
      kNoFlags,
      1,  // One error: we try to call addUrl() on chrome.history without
          // permission, which results in a TypeError.
      ACTION_NONE,
      &extension);

  std::string script_url = extension->GetResourceURL("background.js").spec();

  const ErrorList& errors =
      error_console()->GetErrorsForExtension(extension->id());

  CheckRuntimeError(
      errors[0].get(), extension->id(), script_url,
      false,  // not incognito
      "Uncaught TypeError: Cannot read property 'addUrl' of undefined",
      logging::LOG_ERROR, extension->GetResourceURL(kBackgroundPageName), 1u);

  const StackTrace& stack_trace = GetStackTraceFromError(errors[0].get());
  ASSERT_EQ(1u, stack_trace.size());
  CheckStackFrame(stack_trace[0],
                  script_url,
                  kAnonymousFunction,
                  5u, 1u);
}

// Test that if there is an error in an HTML page loaded by an extension (most
// common with apps), it is caught and reported by the ErrorConsole.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BadExtensionPage) {
  const Extension* extension = NULL;
  LoadExtensionAndCheckErrors(
      "bad_extension_page",
      kNoFlags,
      1,  // One error: the page will load JS which has a reference error.
      ACTION_NEW_TAB,
      &extension);
}

// Test that extension errors that go to chrome.runtime.lastError are caught
// and reported by the ErrorConsole.
IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, CatchesLastError) {
  const Extension* extension = NULL;
  LoadExtensionAndCheckErrors(
      "trigger_last_error",
      kNoFlags,
      1,  // One error, which is sent through last error when trying to remove
          // a non-existent permisison.
      ACTION_NONE,
      &extension);

  const ErrorList& errors =
      error_console()->GetErrorsForExtension(extension->id());
  ASSERT_EQ(1u, errors.size());

  std::string source;
  std::string message;
  size_t line_number = 0;
  size_t column_number = 0;
  if (base::FeatureList::IsEnabled(features::kNativeCrxBindings)) {
    // TODO(devlin): This is unfortunate. We lose a lot of context by using
    // RenderFrame::AddMessageToConsole() instead of console.error(). This could
    // be expanded; blink::SourceLocation knows how to capture an inspector
    // stack trace.
    source = extension->GetResourceURL(kGeneratedBackgroundPageFilename).spec();
    // Line number '0' comes from errors that are logged to the render frame
    // directly (e.g. background_age.html (0)).
    line_number = 0;
    // Column number remains at the default specified in StackFrame (1).
    column_number = 1;
    message =
        "Unchecked runtime.lastError: "
        "'foobar' is not a recognized permission.";
  } else {
    source = extension->GetResourceURL("background.js").spec();
    line_number = 12;
    column_number = 20;
    message =
        "Unchecked runtime.lastError while running permissions.remove: "
        "'foobar' is not a recognized permission.";
  }

  CheckRuntimeError(errors[0].get(), extension->id(), source,
                    false,  // not incognito
                    message, logging::LOG_ERROR,
                    extension->GetResourceURL(kBackgroundPageName), 1u);

  const StackTrace& stack_trace = GetStackTraceFromError(errors[0].get());
  ASSERT_EQ(1u, stack_trace.size());
  CheckStackFrame(stack_trace[0], source, kAnonymousFunction, line_number,
                  column_number);
}

}  // namespace extensions
