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