158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file.
458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/error_console/error_console.h"
658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/files/file_path.h"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/prefs/pref_service.h"
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/string16.h"
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/stringprintf.h"
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/extensions/extension_browsertest.h"
1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/common/pref_names.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/url_constants.h"
1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/browser/extension_error.h"
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/constants.h"
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/error_utils.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/extension_urls.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/feature_switch.h"
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "extensions/common/manifest_constants.h"
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h"
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "url/gurl.h"
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::string16;
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using base::UTF8ToUTF16;
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace extensions {
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kTestingPage[] = "/extensions/test_file.html";
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kAnonymousFunction[] = "(anonymous function)";
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char* kBackgroundPageName =
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    extensions::kGeneratedBackgroundPageFilename;
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const int kNoFlags = 0;
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const StackTrace& GetStackTraceFromError(const ExtensionError* error) {
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CHECK(error->type() == ExtensionError::RUNTIME_ERROR);
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return (static_cast<const RuntimeError*>(error))->stack_trace();
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Verify that a given |frame| has the proper source and function name.
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckStackFrame(const StackFrame& frame,
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     const std::string& source,
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     const std::string& function) {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::UTF8ToUTF16(source), frame.source);
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::UTF8ToUTF16(function), frame.function);
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Verify that all properties of a given |frame| are correct. Overloaded because
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// we commonly do not check line/column numbers, as they are too likely
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// to change.
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckStackFrame(const StackFrame& frame,
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     const std::string& source,
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     const std::string& function,
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     size_t line_number,
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     size_t column_number) {
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckStackFrame(frame, source, function);
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(line_number, frame.line_number);
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(column_number, frame.column_number);
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Verify that all properties of a given |error| are correct.
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckError(const ExtensionError* error,
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                ExtensionError::Type type,
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                const std::string& id,
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                const std::string& source,
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                bool from_incognito,
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                const std::string& message) {
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(error);
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(type, error->type());
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(id, error->extension_id());
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::UTF8ToUTF16(source), error->source());
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(from_incognito, error->from_incognito());
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::UTF8ToUTF16(message), error->message());
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Verify that all properties of a JS runtime error are correct.
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckRuntimeError(const ExtensionError* error,
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       const std::string& id,
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       const std::string& source,
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       bool from_incognito,
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       const std::string& message,
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       logging::LogSeverity level,
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       const GURL& context,
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       size_t expected_stack_size) {
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckError(error,
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             ExtensionError::RUNTIME_ERROR,
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             id,
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             source,
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             from_incognito,
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             message);
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const RuntimeError* runtime_error = static_cast<const RuntimeError*>(error);
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(level, runtime_error->level());
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(context, runtime_error->context_url());
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(expected_stack_size, runtime_error->stack_trace().size());
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckManifestError(const ExtensionError* error,
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        const std::string& id,
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        const std::string& message,
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        const std::string& manifest_key,
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        const std::string& manifest_specific) {
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckError(error,
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             ExtensionError::MANIFEST_ERROR,
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             id,
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             // source is always the manifest for ManifestErrors.
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             base::FilePath(kManifestFilename).AsUTF8Unsafe(),
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             false,  // manifest errors are never from incognito.
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             message);
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const ManifestError* manifest_error =
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      static_cast<const ManifestError*>(error);
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::UTF8ToUTF16(manifest_key), manifest_error->manifest_key());
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::UTF8ToUTF16(manifest_specific),
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            manifest_error->manifest_specific());
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class ErrorConsoleBrowserTest : public ExtensionBrowserTest {
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ErrorConsoleBrowserTest() : error_console_(NULL) { }
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual ~ErrorConsoleBrowserTest() { }
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) protected:
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // A helper class in order to wait for the proper number of errors to be
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // caught by the ErrorConsole. This will run the MessageLoop until a given
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // number of errors are observed.
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Usage:
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //   ...
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //   ErrorObserver observer(3, error_console);
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //   <Cause three errors...>
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //   observer.WaitForErrors();
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //   <Perform any additional checks...>
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  class ErrorObserver : public ErrorConsole::Observer {
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)   public:
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ErrorObserver(size_t errors_expected, ErrorConsole* error_console)
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        : errors_observed_(0),
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          errors_expected_(errors_expected),
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          waiting_(false),
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          error_console_(error_console) {
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_console_->AddObserver(this);
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    virtual ~ErrorObserver() {
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (error_console_)
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        error_console_->RemoveObserver(this);
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // ErrorConsole::Observer implementation.
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    virtual void OnErrorAdded(const ExtensionError* error) OVERRIDE {
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ++errors_observed_;
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (errors_observed_ >= errors_expected_) {
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (waiting_)
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          base::MessageLoopForUI::current()->Quit();
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    virtual void OnErrorConsoleDestroyed() OVERRIDE {
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_console_ = NULL;
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Spin until the appropriate number of errors have been observed.
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void WaitForErrors() {
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (errors_observed_ < errors_expected_) {
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        waiting_ = true;
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        content::RunMessageLoop();
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        waiting_ = false;
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)   private:
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    size_t errors_observed_;
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    size_t errors_expected_;
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bool waiting_;
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ErrorConsole* error_console_;
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(ErrorObserver);
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  };
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The type of action which we take after we load an extension in order to
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // cause any errors.
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  enum Action {
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Navigate to a (non-chrome) page to allow a content script to run.
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ACTION_NAVIGATE,
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Simulate a browser action click.
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ACTION_BROWSER_ACTION,
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Navigate to the new tab page.
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ACTION_NEW_TAB,
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Do nothing (errors will be caused by a background script,
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // or by a manifest/loading warning).
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ACTION_NONE
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  };
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // We need to enable the ErrorConsole FeatureSwitch in order to collect
206e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // errors. This should be enabled on any channel <= Dev, but let's make
207e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // sure (in case a test is running on, e.g., a beta channel).
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    FeatureSwitch::error_console()->SetOverrideValue(
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        FeatureSwitch::OVERRIDE_ENABLED);
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void SetUpOnMainThread() OVERRIDE {
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ExtensionBrowserTest::SetUpOnMainThread();
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Errors are only kept if we have Developer Mode enabled.
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    error_console_ = ErrorConsole::Get(profile());
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    CHECK(error_console_);
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    test_data_dir_ = test_data_dir_.AppendASCII("error_console");
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const GURL& GetTestURL() {
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (test_url_.is_empty()) {
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CHECK(embedded_test_server()->InitializeAndWaitUntilReady());
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      test_url_ = embedded_test_server()->GetURL(kTestingPage);
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return test_url_;
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Load the extension at |path|, take the specified |action|, and wait for
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |expected_errors| errors. Populate |extension| with a pointer to the loaded
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // extension.
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void LoadExtensionAndCheckErrors(
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const std::string& path,
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      int flags,
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      size_t errors_expected,
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      Action action,
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const Extension** extension) {
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ErrorObserver observer(errors_expected, error_console_);
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    *extension =
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        LoadExtensionWithFlags(test_data_dir_.AppendASCII(path), flags);
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ASSERT_TRUE(*extension);
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    switch (action) {
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case ACTION_NAVIGATE: {
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        ui_test_utils::NavigateToURL(browser(), GetTestURL());
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break;
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case ACTION_BROWSER_ACTION: {
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ExtensionActionAPI::Get(profile())->ExecuteExtensionAction(
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            *extension, browser(), true);
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break;
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ACTION_NEW_TAB: {
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui_test_utils::NavigateToURL(browser(),
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     GURL(chrome::kChromeUINewTabURL));
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case ACTION_NONE:
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break;
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      default:
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        NOTREACHED();
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    observer.WaitForErrors();
26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // We should only have errors for a single extension, or should have no
27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // entries, if no errors were expected.
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_EQ(errors_expected > 0 ? 1u : 0u,
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              error_console()->get_num_entries_for_test());
27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ASSERT_EQ(
27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        errors_expected,
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        error_console()->GetErrorsForExtension((*extension)->id()).size());
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ErrorConsole* error_console() { return error_console_; }
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The URL used in testing for simple page navigations.
28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  GURL test_url_;
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Weak reference to the ErrorConsole.
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ErrorConsole* error_console_;
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Test to ensure that we are successfully reporting manifest errors as an
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// extension is installed.
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, ReportManifestErrors) {
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Extension* extension = NULL;
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // We expect two errors - one for an invalid permission, and a second for
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // an unknown key.
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LoadExtensionAndCheckErrors("manifest_warnings",
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              ExtensionBrowserTest::kFlagIgnoreManifestWarnings,
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              2,
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              ACTION_NONE,
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              &extension);
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const ErrorList& errors =
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_console()->GetErrorsForExtension(extension->id());
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Unfortunately, there's not always a hard guarantee of order in parsing the
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // manifest, so there's not a definitive order in which these errors may
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // occur. As such, we need to determine which error corresponds to which
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // expected error.
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const ExtensionError* permissions_error = NULL;
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const ExtensionError* unknown_key_error = NULL;
30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const char kFakeKey[] = "not_a_real_key";
30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < errors.size(); ++i) {
31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ASSERT_EQ(ExtensionError::MANIFEST_ERROR, errors[i]->type());
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string utf8_key = base::UTF16ToUTF8(
31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (static_cast<const ManifestError*>(errors[i]))->manifest_key());
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (utf8_key == manifest_keys::kPermissions)
31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      permissions_error = errors[i];
31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    else if (utf8_key == kFakeKey)
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      unknown_key_error = errors[i];
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(permissions_error);
31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(unknown_key_error);
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const char kFakePermission[] = "not_a_real_permission";
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckManifestError(permissions_error,
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     extension->id(),
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     ErrorUtils::FormatErrorMessage(
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         manifest_errors::kPermissionUnknownOrMalformed,
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         kFakePermission),
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     manifest_keys::kPermissions,
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     kFakePermission);
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckManifestError(unknown_key_error,
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     extension->id(),
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     ErrorUtils::FormatErrorMessage(
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         manifest_errors::kUnrecognizedManifestKey,
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         kFakeKey),
33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     kFakeKey,
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     std::string());
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Test that we do not store any errors unless the Developer Mode switch is
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// toggled on the profile.
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest,
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       DontStoreErrorsWithoutDeveloperMode) {
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, false);
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Extension* extension = NULL;
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Same test as ReportManifestErrors, except we don't expect any errors since
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // we disable Developer Mode.
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LoadExtensionAndCheckErrors("manifest_warnings",
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              ExtensionBrowserTest::kFlagIgnoreManifestWarnings,
35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              0,
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              ACTION_NONE,
35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              &extension);
35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Now if we enable developer mode, the errors should be reported...
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);
35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(2u, error_console()->GetErrorsForExtension(extension->id()).size());
35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // ... and if we disable it again, all errors which we were holding should be
35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // removed.
36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, false);
36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(0u, error_console()->GetErrorsForExtension(extension->id()).size());
36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Load an extension which, upon visiting any page, first sends out a console
36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// log, and then crashes with a JS TypeError.
36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest,
367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                       ContentScriptLogAndRuntimeError) {
36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Extension* extension = NULL;
36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LoadExtensionAndCheckErrors(
37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      "content_script_log_and_runtime_error",
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      kNoFlags,
37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      2u,  // Two errors: A log message and a JS type error.
37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ACTION_NAVIGATE,
37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &extension);
37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string script_url = extension->url().Resolve("content_script.js").spec();
37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const ErrorList& errors =
37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_console()->GetErrorsForExtension(extension->id());
38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The first error should be a console log.
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckRuntimeError(errors[0],
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    extension->id(),
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    script_url,  // The source should be the content script url.
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    false,  // Not from incognito.
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    "Hello, World!",  // The error message is the log.
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    logging::LOG_INFO,
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    GetTestURL(),  // Content scripts run in the web page.
38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    2u);
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const StackTrace& stack_trace1 = GetStackTraceFromError(errors[0]);
39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckStackFrame(stack_trace1[0],
39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  script_url,
39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  "logHelloWorld",  // function name
39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  6u,  // line number
39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  11u /* column number */ );
39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckStackFrame(stack_trace1[1],
39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  script_url,
40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  kAnonymousFunction,
40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  9u,
40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  1u);
40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The second error should be a runtime error.
40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckRuntimeError(errors[1],
40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    extension->id(),
40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    script_url,
40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    false,  // not from incognito
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    "Uncaught TypeError: "
41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        "Cannot set property 'foo' of undefined",
41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    logging::LOG_ERROR,  // JS errors are always ERROR level.
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    GetTestURL(),
41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    1u);
41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const StackTrace& stack_trace2 = GetStackTraceFromError(errors[1]);
41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckStackFrame(stack_trace2[0],
41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  script_url,
41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  kAnonymousFunction,
41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  12u,
42058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  1u);
42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Catch an error from a BrowserAction; this is more complex than a content
42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// script error, since browser actions are routed through our own code.
42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BrowserActionRuntimeError) {
42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Extension* extension = NULL;
42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LoadExtensionAndCheckErrors(
42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      "browser_action_runtime_error",
42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      kNoFlags,
43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      1u,  // One error: A reference error from within the browser action.
43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ACTION_BROWSER_ACTION,
43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &extension);
43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string script_url = extension->url().Resolve("browser_action.js").spec();
43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const ErrorList& errors =
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_console()->GetErrorsForExtension(extension->id());
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string event_bindings_str =
44058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::StringPrintf("extensions::%s", kEventBindings);
44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string event_dispatch_to_listener_str =
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::StringPrintf("Event.publicClass.%s [as dispatchToListener]",
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         kAnonymousFunction);
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
44658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckRuntimeError(
44758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      errors[0],
44858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      extension->id(),
44958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      script_url,
45058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      false,  // not incognito
45103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "Error in event handler for browserAction.onClicked: ReferenceError: "
45203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          "baz is not defined",
45358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      logging::LOG_ERROR,
45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      extension->url().Resolve(kBackgroundPageName),
45503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      1u);
45658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
45758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const StackTrace& stack_trace = GetStackTraceFromError(errors[0]);
45803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Note: This test used to have a stack trace of length 6 that contains stack
45903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // frames in the extension code, but since crbug.com/404406 was fixed only
46003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // stack frames within user-defined extension code are printed.
46158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
46258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckStackFrame(stack_trace[0], script_url, kAnonymousFunction);
46358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
46458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
46558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Test that we can catch an error for calling an API with improper arguments.
46658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BadAPIArgumentsRuntimeError) {
46758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Extension* extension = NULL;
46858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LoadExtensionAndCheckErrors(
46958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      "bad_api_arguments_runtime_error",
47058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      kNoFlags,
47158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      1,  // One error: call an API with improper arguments.
47258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ACTION_NONE,
47358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &extension);
47458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const ErrorList& errors =
47658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_console()->GetErrorsForExtension(extension->id());
47758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string schema_utils_str =
47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::StringPrintf("extensions::%s", kSchemaUtils);
48058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
48158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckRuntimeError(
48258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      errors[0],
48358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      extension->id(),
48458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      schema_utils_str,  // API calls are checked in schemaUtils.js.
48558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      false,  // not incognito
48658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      "Uncaught Error: Invocation of form "
48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          "tabs.get(string, function) doesn't match definition "
48858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          "tabs.get(integer tabId, function callback)",
48958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      logging::LOG_ERROR,
49058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      extension->url().Resolve(kBackgroundPageName),
49158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      1u);
49258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
49358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const StackTrace& stack_trace = GetStackTraceFromError(errors[0]);
49458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_EQ(1u, stack_trace.size());
49558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckStackFrame(stack_trace[0],
49658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  schema_utils_str,
49758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  kAnonymousFunction);
49858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
49958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
50058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Test that we catch an error when we try to call an API method without
50158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// permission.
50258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BadAPIPermissionsRuntimeError) {
50358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Extension* extension = NULL;
50458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LoadExtensionAndCheckErrors(
50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      "bad_api_permissions_runtime_error",
50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      kNoFlags,
50758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      1,  // One error: we try to call addUrl() on chrome.history without
50858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          // permission, which results in a TypeError.
50958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ACTION_NONE,
51058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &extension);
51158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
51258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string script_url = extension->url().Resolve("background.js").spec();
51358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const ErrorList& errors =
51558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      error_console()->GetErrorsForExtension(extension->id());
51658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
51758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckRuntimeError(
51858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      errors[0],
51958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      extension->id(),
52058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      script_url,
52158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      false,  // not incognito
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "Uncaught TypeError: Cannot read property 'addUrl' of undefined",
52358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      logging::LOG_ERROR,
52458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      extension->url().Resolve(kBackgroundPageName),
52558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      1u);
52658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
52758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const StackTrace& stack_trace = GetStackTraceFromError(errors[0]);
52858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_EQ(1u, stack_trace.size());
52958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckStackFrame(stack_trace[0],
53058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  script_url,
53158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  kAnonymousFunction,
53258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  5u, 1u);
53358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
53458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Test that if there is an error in an HTML page loaded by an extension (most
5360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// common with apps), it is caught and reported by the ErrorConsole.
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, BadExtensionPage) {
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Extension* extension = NULL;
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LoadExtensionAndCheckErrors(
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "bad_extension_page",
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      kNoFlags,
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      1,  // One error: the page will load JS which has a reference error.
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ACTION_NEW_TAB,
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      &extension);
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Test that extension errors that go to chrome.runtime.lastError are caught
5480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// and reported by the ErrorConsole.
5490529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochIN_PROC_BROWSER_TEST_F(ErrorConsoleBrowserTest, CatchesLastError) {
5500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const Extension* extension = NULL;
5510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  LoadExtensionAndCheckErrors(
5520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      "trigger_last_error",
5530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      kNoFlags,
5540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      1,  // One error, which is sent through last error when trying to remove
5550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // a non-existent permisison.
5560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ACTION_NONE,
5570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      &extension);
5580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ErrorList& errors =
5600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      error_console()->GetErrorsForExtension(extension->id());
5610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ASSERT_EQ(1u, errors.size());
5620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  std::string script_url = extension->url().Resolve("background.js").spec();
5640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  CheckRuntimeError(
5660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      errors[0],
5670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      extension->id(),
5680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      script_url,
5690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      false,  // not incognito
5700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      "Unchecked runtime.lastError while running permissions.remove: "
5710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          "'foobar' is not a recognized permission.",
5720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      logging::LOG_ERROR,
5730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      extension->url().Resolve(kBackgroundPageName),
5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      1u);
5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const StackTrace& stack_trace = GetStackTraceFromError(errors[0]);
5770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ASSERT_EQ(1u, stack_trace.size());
5780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  CheckStackFrame(stack_trace[0],
5790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                  script_url,
5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                  kAnonymousFunction,
5810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                  12u, 20u);
5820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
58458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace extensions
585