| Index: extensions/renderer/api_last_error_unittest.cc
|
| diff --git a/extensions/renderer/api_last_error_unittest.cc b/extensions/renderer/api_last_error_unittest.cc
|
| deleted file mode 100644
|
| index dbe8ff2ce7e92c463c33630a8a73c4c01182972d..0000000000000000000000000000000000000000
|
| --- a/extensions/renderer/api_last_error_unittest.cc
|
| +++ /dev/null
|
| @@ -1,225 +0,0 @@
|
| -// Copyright 2017 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "extensions/renderer/api_last_error.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/callback_helpers.h"
|
| -#include "base/optional.h"
|
| -#include "extensions/renderer/api_binding_test.h"
|
| -#include "extensions/renderer/api_binding_test_util.h"
|
| -#include "gin/converter.h"
|
| -#include "gin/public/context_holder.h"
|
| -
|
| -namespace extensions {
|
| -
|
| -namespace {
|
| -
|
| -void DoNothingWithError(v8::Local<v8::Context> context,
|
| - const std::string& error) {}
|
| -
|
| -// Returns the v8 object for the lastError.
|
| -v8::Local<v8::Value> GetLastError(v8::Local<v8::Object> parent,
|
| - v8::Local<v8::Context> context) {
|
| - return GetPropertyFromObject(parent, context, "lastError");
|
| -}
|
| -
|
| -// Returns a stringified version of the lastError message, if one exists, and
|
| -// otherwise a stringified version of whatever the lastError property is (e.g.
|
| -// undefined).
|
| -std::string GetLastErrorMessage(v8::Local<v8::Object> parent,
|
| - v8::Local<v8::Context> context) {
|
| - v8::Local<v8::Value> last_error = GetLastError(parent, context);
|
| - if (last_error.IsEmpty() || !last_error->IsObject())
|
| - return V8ToString(last_error, context);
|
| - v8::Local<v8::Value> message =
|
| - GetPropertyFromObject(last_error.As<v8::Object>(), context, "message");
|
| - return V8ToString(message, context);
|
| -}
|
| -
|
| -using ParentList =
|
| - std::vector<std::pair<v8::Local<v8::Context>, v8::Local<v8::Object>>>;
|
| -v8::Local<v8::Object> GetParent(const ParentList& parents,
|
| - v8::Local<v8::Context> context) {
|
| - // This would be simpler with a map<context, object>, but Local<> doesn't
|
| - // define an operator<.
|
| - for (const auto& parent : parents) {
|
| - if (parent.first == context)
|
| - return parent.second;
|
| - }
|
| - return v8::Local<v8::Object>();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -using APILastErrorTest = APIBindingTest;
|
| -
|
| -// Test basic functionality of the lastError object.
|
| -TEST_F(APILastErrorTest, TestLastError) {
|
| - v8::HandleScope handle_scope(isolate());
|
| - v8::Local<v8::Context> context = MainContext();
|
| - v8::Local<v8::Object> parent_object = v8::Object::New(isolate());
|
| -
|
| - ParentList parents = {{context, parent_object}};
|
| - APILastError last_error(base::Bind(&GetParent, parents),
|
| - base::Bind(&DoNothingWithError));
|
| -
|
| - EXPECT_FALSE(last_error.HasError(context));
|
| - EXPECT_EQ("undefined", GetLastErrorMessage(parent_object, context));
|
| - // Check that the key isn't present on the object (as opposed to simply being
|
| - // undefined).
|
| - EXPECT_FALSE(
|
| - parent_object->Has(context, gin::StringToV8(isolate(), "lastError"))
|
| - .ToChecked());
|
| -
|
| - last_error.SetError(context, "Some last error");
|
| - EXPECT_TRUE(last_error.HasError(context));
|
| - EXPECT_EQ("\"Some last error\"", GetLastErrorMessage(parent_object, context));
|
| -
|
| - last_error.ClearError(context, false);
|
| - EXPECT_FALSE(last_error.HasError(context));
|
| - EXPECT_EQ("undefined", GetLastErrorMessage(parent_object, context));
|
| - EXPECT_FALSE(
|
| - parent_object->Has(context, gin::StringToV8(isolate(), "lastError"))
|
| - .ToChecked());
|
| -}
|
| -
|
| -// Test throwing an error if the last error wasn't checked.
|
| -TEST_F(APILastErrorTest, ReportIfUnchecked) {
|
| - v8::HandleScope handle_scope(isolate());
|
| - v8::Local<v8::Context> context = MainContext();
|
| - v8::Local<v8::Object> parent_object = v8::Object::New(isolate());
|
| -
|
| - base::Optional<std::string> console_error;
|
| - auto log_error = [](base::Optional<std::string>* console_error,
|
| - v8::Local<v8::Context> context,
|
| - const std::string& error) { *console_error = error; };
|
| -
|
| - ParentList parents = {{context, parent_object}};
|
| - APILastError last_error(base::Bind(&GetParent, parents),
|
| - base::Bind(log_error, &console_error));
|
| -
|
| - {
|
| - v8::TryCatch try_catch(isolate());
|
| - last_error.SetError(context, "foo");
|
| - // GetLastErrorMessage() will count as accessing the error property, so we
|
| - // shouldn't throw an exception.
|
| - EXPECT_EQ("\"foo\"", GetLastErrorMessage(parent_object, context));
|
| - last_error.ClearError(context, true);
|
| - EXPECT_FALSE(console_error);
|
| - EXPECT_FALSE(try_catch.HasCaught());
|
| - }
|
| -
|
| - {
|
| - v8::TryCatch try_catch(isolate());
|
| - last_error.SetError(context, "foo");
|
| - // GetLastError() only accesses the error object, and not the message
|
| - // directly (e.g. chrome.runtime.lastError vs
|
| - // chrome.runtime.lastError.message), but should still count as access and
|
| - // shouldn't throw an exception.
|
| - v8::Local<v8::Value> v8_error = GetLastError(parent_object, context);
|
| - ASSERT_FALSE(v8_error.IsEmpty());
|
| - EXPECT_TRUE(v8_error->IsObject());
|
| - last_error.ClearError(context, true);
|
| - EXPECT_FALSE(console_error);
|
| - EXPECT_FALSE(try_catch.HasCaught());
|
| - }
|
| -
|
| - {
|
| - v8::TryCatch try_catch(isolate());
|
| - // This time, we should log an error.
|
| - last_error.SetError(context, "A last error");
|
| - last_error.ClearError(context, true);
|
| - ASSERT_TRUE(console_error);
|
| - EXPECT_EQ("Unchecked runtime.lastError: A last error", *console_error);
|
| - // We shouldn't have thrown an exception in order to prevent disrupting
|
| - // JS execution.
|
| - EXPECT_FALSE(try_catch.HasCaught());
|
| - }
|
| -
|
| - {
|
| - v8::TryCatch try_catch(isolate());
|
| - last_error.SetError(context, "A last error");
|
| - // Access through the internal HasError() should not count as access.
|
| - EXPECT_TRUE(last_error.HasError(context));
|
| - last_error.ClearError(context, true);
|
| - ASSERT_TRUE(console_error);
|
| - EXPECT_EQ("Unchecked runtime.lastError: A last error", *console_error);
|
| - EXPECT_FALSE(try_catch.HasCaught());
|
| - }
|
| -}
|
| -
|
| -// Test behavior when something else sets a lastError property on the parent
|
| -// object.
|
| -TEST_F(APILastErrorTest, NonLastErrorObject) {
|
| - v8::HandleScope handle_scope(isolate());
|
| - v8::Local<v8::Context> context = MainContext();
|
| - v8::Local<v8::Object> parent_object = v8::Object::New(isolate());
|
| -
|
| - ParentList parents = {{context, parent_object}};
|
| - APILastError last_error(base::Bind(&GetParent, parents),
|
| - base::Bind(&DoNothingWithError));
|
| -
|
| - auto checked_set = [context](v8::Local<v8::Object> object,
|
| - base::StringPiece key,
|
| - v8::Local<v8::Value> value) {
|
| - v8::Maybe<bool> success = object->Set(
|
| - context, gin::StringToSymbol(context->GetIsolate(), key), value);
|
| - ASSERT_TRUE(success.IsJust());
|
| - ASSERT_TRUE(success.FromJust());
|
| - };
|
| -
|
| - // Set a "fake" lastError property on the parent.
|
| - v8::Local<v8::Object> fake_last_error = v8::Object::New(isolate());
|
| - checked_set(fake_last_error, "message",
|
| - gin::StringToV8(isolate(), "fake error"));
|
| - checked_set(parent_object, "lastError", fake_last_error);
|
| -
|
| - EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
|
| -
|
| - // The bindings shouldn't mangle an existing property (or maybe we should -
|
| - // see the TODO in api_last_error.cc).
|
| - last_error.SetError(context, "Real last error");
|
| - EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
|
| - last_error.ClearError(context, false);
|
| - EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
|
| -
|
| - checked_set(parent_object, "lastError", v8::Undefined(isolate()));
|
| - EXPECT_EQ("undefined", GetLastErrorMessage(parent_object, context));
|
| - last_error.SetError(context, "a last error");
|
| - EXPECT_EQ("\"a last error\"", GetLastErrorMessage(parent_object, context));
|
| - checked_set(parent_object, "lastError", fake_last_error);
|
| - EXPECT_EQ("\"fake error\"", GetLastErrorMessage(parent_object, context));
|
| -}
|
| -
|
| -// Test lastError in multiple different contexts.
|
| -TEST_F(APILastErrorTest, MultipleContexts) {
|
| - v8::HandleScope handle_scope(isolate());
|
| - v8::Local<v8::Context> context_a = MainContext();
|
| - v8::Local<v8::Context> context_b = AddContext();
|
| -
|
| - v8::Local<v8::Object> parent_a = v8::Object::New(isolate());
|
| - v8::Local<v8::Object> parent_b = v8::Object::New(isolate());
|
| - ParentList parents = {{context_a, parent_a}, {context_b, parent_b}};
|
| - APILastError last_error(base::Bind(&GetParent, parents),
|
| - base::Bind(&DoNothingWithError));
|
| -
|
| - last_error.SetError(context_a, "Last error a");
|
| - EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a));
|
| - EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b));
|
| -
|
| - last_error.SetError(context_b, "Last error b");
|
| - EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a));
|
| - EXPECT_EQ("\"Last error b\"", GetLastErrorMessage(parent_b, context_b));
|
| -
|
| - last_error.ClearError(context_b, false);
|
| - EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a));
|
| - EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b));
|
| -
|
| - last_error.ClearError(context_a, false);
|
| - EXPECT_EQ("undefined", GetLastErrorMessage(parent_a, context_a));
|
| - EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b));
|
| -}
|
| -
|
| -} // namespace extensions
|
|
|