| Index: extensions/renderer/api_last_error.cc
|
| diff --git a/extensions/renderer/api_last_error.cc b/extensions/renderer/api_last_error.cc
|
| deleted file mode 100644
|
| index fbf516b564331e6eb71cedab574b2c33302a92bb..0000000000000000000000000000000000000000
|
| --- a/extensions/renderer/api_last_error.cc
|
| +++ /dev/null
|
| @@ -1,249 +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 "gin/converter.h"
|
| -#include "gin/handle.h"
|
| -#include "gin/object_template_builder.h"
|
| -#include "gin/wrappable.h"
|
| -
|
| -namespace extensions {
|
| -
|
| -namespace {
|
| -
|
| -const char kLastErrorProperty[] = "lastError";
|
| -const char kScriptSuppliedValueKey[] = "script_supplied_value";
|
| -
|
| -// The object corresponding to the lastError property, containing a single
|
| -// property ('message') with the last error. This object is stored on the parent
|
| -// (chrome.runtime in production) as a private property, and is returned via an
|
| -// accessor which marks the error as accessed.
|
| -class LastErrorObject final : public gin::Wrappable<LastErrorObject> {
|
| - public:
|
| - explicit LastErrorObject(const std::string& error) : error_(error) {}
|
| -
|
| - static gin::WrapperInfo kWrapperInfo;
|
| -
|
| - // gin::Wrappable:
|
| - gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
| - v8::Isolate* isolate) override {
|
| - DCHECK(isolate);
|
| - return Wrappable<LastErrorObject>::GetObjectTemplateBuilder(isolate)
|
| - .SetProperty("message", &LastErrorObject::error);
|
| - }
|
| -
|
| - void Reset(const std::string& error) {
|
| - error_ = error;
|
| - accessed_ = false;
|
| - }
|
| -
|
| - const std::string& error() const { return error_; }
|
| - bool accessed() const { return accessed_; }
|
| - void set_accessed() { accessed_ = true; }
|
| -
|
| - private:
|
| - std::string error_;
|
| - bool accessed_ = false;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(LastErrorObject);
|
| -};
|
| -
|
| -gin::WrapperInfo LastErrorObject::kWrapperInfo = {gin::kEmbedderNativeGin};
|
| -
|
| -// An accessor to retrieve the last error property (curried in through data),
|
| -// and mark it as accessed.
|
| -void LastErrorGetter(v8::Local<v8::Name> property,
|
| - const v8::PropertyCallbackInfo<v8::Value>& info) {
|
| - v8::Isolate* isolate = info.GetIsolate();
|
| - v8::HandleScope handle_scope(isolate);
|
| - v8::Local<v8::Object> holder = info.Holder();
|
| - v8::Local<v8::Context> context = holder->CreationContext();
|
| -
|
| - v8::Local<v8::Value> last_error;
|
| - v8::Local<v8::Private> last_error_key = v8::Private::ForApi(
|
| - isolate, gin::StringToSymbol(isolate, kLastErrorProperty));
|
| - if (!holder->GetPrivate(context, last_error_key).ToLocal(&last_error) ||
|
| - last_error != info.Data()) {
|
| - // Something funny happened - our private properties aren't set right.
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - v8::Local<v8::Value> return_value;
|
| -
|
| - // It's possible that some script has set their own value for the last error
|
| - // property. If so, return that. Otherwise, return the real last error.
|
| - v8::Local<v8::Private> script_value_key = v8::Private::ForApi(
|
| - isolate, gin::StringToSymbol(isolate, kScriptSuppliedValueKey));
|
| - v8::Local<v8::Value> script_value;
|
| - if (holder->GetPrivate(context, script_value_key).ToLocal(&script_value) &&
|
| - !script_value->IsUndefined()) {
|
| - return_value = script_value;
|
| - } else {
|
| - LastErrorObject* last_error_obj = nullptr;
|
| - CHECK(gin::Converter<LastErrorObject*>::FromV8(isolate, last_error,
|
| - &last_error_obj));
|
| - last_error_obj->set_accessed();
|
| - return_value = last_error;
|
| - }
|
| -
|
| - info.GetReturnValue().Set(return_value);
|
| -}
|
| -
|
| -// Allow script to set the last error property.
|
| -void LastErrorSetter(v8::Local<v8::Name> property,
|
| - v8::Local<v8::Value> value,
|
| - const v8::PropertyCallbackInfo<void>& info) {
|
| - v8::Isolate* isolate = info.GetIsolate();
|
| - v8::HandleScope handle_scope(isolate);
|
| - v8::Local<v8::Object> holder = info.Holder();
|
| - v8::Local<v8::Context> context = holder->CreationContext();
|
| -
|
| - v8::Local<v8::Private> script_value_key = v8::Private::ForApi(
|
| - isolate, gin::StringToSymbol(isolate, kScriptSuppliedValueKey));
|
| - v8::Maybe<bool> set_private =
|
| - holder->SetPrivate(context, script_value_key, value);
|
| - if (!set_private.IsJust() || !set_private.FromJust())
|
| - NOTREACHED();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -APILastError::APILastError(const GetParent& get_parent,
|
| - const AddConsoleError& add_console_error)
|
| - : get_parent_(get_parent), add_console_error_(add_console_error) {}
|
| -APILastError::APILastError(APILastError&& other) = default;
|
| -APILastError::~APILastError() = default;
|
| -
|
| -void APILastError::SetError(v8::Local<v8::Context> context,
|
| - const std::string& error) {
|
| - v8::Isolate* isolate = context->GetIsolate();
|
| - DCHECK(isolate);
|
| - v8::HandleScope handle_scope(isolate);
|
| -
|
| - // The various accesses/sets on an object could potentially fail if script has
|
| - // set any crazy interceptors. For the most part, we don't care about behaving
|
| - // perfectly in these circumstances, but we eat the exception so callers don't
|
| - // have to worry about it. We also SetVerbose() so that developers will have a
|
| - // clue what happened if this does arise.
|
| - // TODO(devlin): Whether or not this needs to be verbose is debatable.
|
| - v8::TryCatch try_catch(isolate);
|
| - try_catch.SetVerbose(true);
|
| -
|
| - v8::Local<v8::Object> parent = get_parent_.Run(context);
|
| - if (parent.IsEmpty())
|
| - return;
|
| - v8::Local<v8::String> key = gin::StringToSymbol(isolate, kLastErrorProperty);
|
| - v8::Local<v8::Value> v8_error;
|
| - // Two notes: this Get() is visible to external script, and this will actually
|
| - // mark the lastError as accessed, if one exists. These shouldn't be a
|
| - // problem (lastError is meant to be helpful, but isn't designed to handle
|
| - // crazy chaining, etc). However, if we decide we needed to be fancier, we
|
| - // could detect the presence of a current error through a GetPrivate(), and
|
| - // optionally throw it if one exists.
|
| - if (!parent->Get(context, key).ToLocal(&v8_error))
|
| - return;
|
| -
|
| - if (!v8_error->IsUndefined()) {
|
| - // There may be an existing last error to overwrite.
|
| - LastErrorObject* last_error = nullptr;
|
| - if (!gin::Converter<LastErrorObject*>::FromV8(isolate, v8_error,
|
| - &last_error)) {
|
| - // If it's not a real lastError (e.g. if a script manually set it), don't
|
| - // do anything. We shouldn't mangle a property set by other script.
|
| - // TODO(devlin): Or should we? If someone sets chrome.runtime.lastError,
|
| - // it might be the right course of action to overwrite it.
|
| - return;
|
| - }
|
| - last_error->Reset(error);
|
| - } else {
|
| - v8::Local<v8::Value> last_error =
|
| - gin::CreateHandle(isolate, new LastErrorObject(error)).ToV8();
|
| - v8::Maybe<bool> set_private = parent->SetPrivate(
|
| - context, v8::Private::ForApi(isolate, key), last_error);
|
| - if (!set_private.IsJust() || !set_private.FromJust()) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| - DCHECK(!last_error.IsEmpty());
|
| - // This Set() can fail, but there's nothing to do if it does (the exception
|
| - // will be caught by the TryCatch above).
|
| - ignore_result(parent->SetAccessor(context, key, &LastErrorGetter,
|
| - &LastErrorSetter, last_error));
|
| - }
|
| -}
|
| -
|
| -void APILastError::ClearError(v8::Local<v8::Context> context,
|
| - bool report_if_unchecked) {
|
| - v8::Isolate* isolate = context->GetIsolate();
|
| - v8::HandleScope handle_scope(isolate);
|
| -
|
| - v8::Local<v8::Object> parent;
|
| - LastErrorObject* last_error = nullptr;
|
| - v8::Local<v8::String> key;
|
| - v8::Local<v8::Private> private_key;
|
| - {
|
| - // See comment in SetError().
|
| - v8::TryCatch try_catch(isolate);
|
| - try_catch.SetVerbose(true);
|
| -
|
| - parent = get_parent_.Run(context);
|
| - if (parent.IsEmpty())
|
| - return;
|
| - key = gin::StringToSymbol(isolate, kLastErrorProperty);
|
| - private_key = v8::Private::ForApi(isolate, key);
|
| - v8::Local<v8::Value> error;
|
| - // Access through GetPrivate() so that we don't trigger accessed().
|
| - if (!parent->GetPrivate(context, private_key).ToLocal(&error))
|
| - return;
|
| - if (!gin::Converter<LastErrorObject*>::FromV8(context->GetIsolate(), error,
|
| - &last_error)) {
|
| - return;
|
| - }
|
| - }
|
| -
|
| - if (report_if_unchecked && !last_error->accessed()) {
|
| - add_console_error_.Run(
|
| - context, "Unchecked runtime.lastError: " + last_error->error());
|
| - }
|
| -
|
| - // See comment in SetError().
|
| - v8::TryCatch try_catch(isolate);
|
| - try_catch.SetVerbose(true);
|
| -
|
| - v8::Maybe<bool> delete_private = parent->DeletePrivate(context, private_key);
|
| - if (!delete_private.IsJust() || !delete_private.FromJust()) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| - // This Delete() can fail, but there's nothing to do if it does (the exception
|
| - // will be caught by the TryCatch above).
|
| - ignore_result(parent->Delete(context, key));
|
| -}
|
| -
|
| -bool APILastError::HasError(v8::Local<v8::Context> context) {
|
| - v8::Isolate* isolate = context->GetIsolate();
|
| - v8::HandleScope handle_scope(isolate);
|
| -
|
| - // See comment in SetError().
|
| - v8::TryCatch try_catch(isolate);
|
| - try_catch.SetVerbose(true);
|
| -
|
| - v8::Local<v8::Object> parent = get_parent_.Run(context);
|
| - if (parent.IsEmpty())
|
| - return false;
|
| - v8::Local<v8::Value> error;
|
| - v8::Local<v8::Private> key = v8::Private::ForApi(
|
| - isolate, gin::StringToSymbol(isolate, kLastErrorProperty));
|
| - // Access through GetPrivate() so we don't trigger accessed().
|
| - if (!parent->GetPrivate(context, key).ToLocal(&error))
|
| - return false;
|
| -
|
| - LastErrorObject* last_error = nullptr;
|
| - return gin::Converter<LastErrorObject*>::FromV8(context->GetIsolate(), error,
|
| - &last_error);
|
| -}
|
| -
|
| -} // namespace extensions
|
|
|