| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "extensions/renderer/bindings/api_last_error.h" | 5 #include "extensions/renderer/bindings/api_last_error.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/optional.h" | 9 #include "base/optional.h" |
| 10 #include "extensions/renderer/bindings/api_binding_test.h" | 10 #include "extensions/renderer/bindings/api_binding_test.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 if (last_error.IsEmpty() || !last_error->IsObject()) | 34 if (last_error.IsEmpty() || !last_error->IsObject()) |
| 35 return V8ToString(last_error, context); | 35 return V8ToString(last_error, context); |
| 36 v8::Local<v8::Value> message = | 36 v8::Local<v8::Value> message = |
| 37 GetPropertyFromObject(last_error.As<v8::Object>(), context, "message"); | 37 GetPropertyFromObject(last_error.As<v8::Object>(), context, "message"); |
| 38 return V8ToString(message, context); | 38 return V8ToString(message, context); |
| 39 } | 39 } |
| 40 | 40 |
| 41 using ParentList = | 41 using ParentList = |
| 42 std::vector<std::pair<v8::Local<v8::Context>, v8::Local<v8::Object>>>; | 42 std::vector<std::pair<v8::Local<v8::Context>, v8::Local<v8::Object>>>; |
| 43 v8::Local<v8::Object> GetParent(const ParentList& parents, | 43 v8::Local<v8::Object> GetParent(const ParentList& parents, |
| 44 v8::Local<v8::Context> context) { | 44 v8::Local<v8::Context> context, |
| 45 v8::Local<v8::Object>* secondary_parent) { |
| 45 // This would be simpler with a map<context, object>, but Local<> doesn't | 46 // This would be simpler with a map<context, object>, but Local<> doesn't |
| 46 // define an operator<. | 47 // define an operator<. |
| 47 for (const auto& parent : parents) { | 48 for (const auto& parent : parents) { |
| 48 if (parent.first == context) | 49 if (parent.first == context) |
| 49 return parent.second; | 50 return parent.second; |
| 50 } | 51 } |
| 51 return v8::Local<v8::Object>(); | 52 return v8::Local<v8::Object>(); |
| 52 } | 53 } |
| 53 | 54 |
| 54 } // namespace | 55 } // namespace |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 | 216 |
| 216 last_error.ClearError(context_b, false); | 217 last_error.ClearError(context_b, false); |
| 217 EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a)); | 218 EXPECT_EQ("\"Last error a\"", GetLastErrorMessage(parent_a, context_a)); |
| 218 EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b)); | 219 EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b)); |
| 219 | 220 |
| 220 last_error.ClearError(context_a, false); | 221 last_error.ClearError(context_a, false); |
| 221 EXPECT_EQ("undefined", GetLastErrorMessage(parent_a, context_a)); | 222 EXPECT_EQ("undefined", GetLastErrorMessage(parent_a, context_a)); |
| 222 EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b)); | 223 EXPECT_EQ("undefined", GetLastErrorMessage(parent_b, context_b)); |
| 223 } | 224 } |
| 224 | 225 |
| 226 TEST_F(APILastErrorTest, SecondaryParent) { |
| 227 auto get_parents = [](v8::Local<v8::Object> primary_parent, |
| 228 v8::Local<v8::Object> secondary_parent, |
| 229 v8::Local<v8::Context> context, |
| 230 v8::Local<v8::Object>* secondary_parent_out) { |
| 231 if (secondary_parent_out) |
| 232 *secondary_parent_out = secondary_parent; |
| 233 return primary_parent; |
| 234 }; |
| 235 |
| 236 base::Optional<std::string> console_error; |
| 237 auto log_error = [](base::Optional<std::string>* console_error, |
| 238 v8::Local<v8::Context> context, |
| 239 const std::string& error) { *console_error = error; }; |
| 240 |
| 241 v8::HandleScope handle_scope(isolate()); |
| 242 v8::Local<v8::Context> context = MainContext(); |
| 243 v8::Local<v8::Object> primary_parent = v8::Object::New(isolate()); |
| 244 v8::Local<v8::Object> secondary_parent = v8::Object::New(isolate()); |
| 245 |
| 246 APILastError last_error( |
| 247 base::Bind(get_parents, primary_parent, secondary_parent), |
| 248 base::Bind(log_error, &console_error)); |
| 249 |
| 250 last_error.SetError(context, "error"); |
| 251 EXPECT_TRUE(last_error.HasError(context)); |
| 252 EXPECT_EQ("\"error\"", GetLastErrorMessage(primary_parent, context)); |
| 253 EXPECT_EQ("\"error\"", GetLastErrorMessage(secondary_parent, context)); |
| 254 EXPECT_FALSE(console_error); |
| 255 |
| 256 last_error.ClearError(context, true); |
| 257 EXPECT_FALSE(console_error); |
| 258 EXPECT_EQ("undefined", GetLastErrorMessage(primary_parent, context)); |
| 259 EXPECT_EQ("undefined", GetLastErrorMessage(secondary_parent, context)); |
| 260 |
| 261 // Accessing the primary parent's error should be sufficient to not log the |
| 262 // error in the console. |
| 263 last_error.SetError(context, "error"); |
| 264 EXPECT_EQ("\"error\"", GetLastErrorMessage(primary_parent, context)); |
| 265 last_error.ClearError(context, true); |
| 266 EXPECT_FALSE(console_error); |
| 267 |
| 268 // Accessing only the secondary parent's error shouldn't count as access on |
| 269 // the main error, and we should log it. |
| 270 last_error.SetError(context, "error"); |
| 271 EXPECT_EQ("\"error\"", GetLastErrorMessage(secondary_parent, context)); |
| 272 last_error.ClearError(context, true); |
| 273 ASSERT_TRUE(console_error); |
| 274 EXPECT_EQ("Unchecked runtime.lastError: error", *console_error); |
| 275 } |
| 276 |
| 225 } // namespace extensions | 277 } // namespace extensions |
| OLD | NEW |