OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/renderer/extensions/automation_internal_custom_bindings.h" | 5 #include "chrome/renderer/extensions/automation_internal_custom_bindings.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/macros.h" | 13 #include "base/macros.h" |
14 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
15 #include "base/values.h" | 15 #include "base/values.h" |
16 #include "chrome/common/extensions/api/automation_api_constants.h" | 16 #include "chrome/common/extensions/api/automation_api_constants.h" |
17 #include "chrome/common/extensions/chrome_extension_messages.h" | 17 #include "chrome/common/extensions/chrome_extension_messages.h" |
18 #include "chrome/common/extensions/manifest_handlers/automation.h" | 18 #include "chrome/common/extensions/manifest_handlers/automation.h" |
19 #include "content/public/renderer/render_frame.h" | 19 #include "content/public/renderer/render_frame.h" |
20 #include "content/public/renderer/render_thread.h" | 20 #include "content/public/renderer/render_thread.h" |
21 #include "content/public/renderer/render_view.h" | 21 #include "content/public/renderer/render_view.h" |
22 #include "extensions/common/extension.h" | 22 #include "extensions/common/extension.h" |
23 #include "extensions/common/manifest.h" | 23 #include "extensions/common/manifest.h" |
24 #include "extensions/common/manifest_handlers/background_info.h" | 24 #include "extensions/common/manifest_handlers/background_info.h" |
25 #include "extensions/renderer/extension_bindings_system.h" | 25 #include "extensions/renderer/extension_bindings_system.h" |
26 #include "extensions/renderer/script_context.h" | 26 #include "extensions/renderer/script_context.h" |
| 27 #include "gin/converter.h" |
27 #include "ipc/message_filter.h" | 28 #include "ipc/message_filter.h" |
28 #include "ui/accessibility/ax_enums.h" | 29 #include "ui/accessibility/ax_enums.h" |
29 #include "ui/accessibility/ax_node.h" | 30 #include "ui/accessibility/ax_node.h" |
30 #include "ui/gfx/geometry/rect_conversions.h" | 31 #include "ui/gfx/geometry/rect_conversions.h" |
31 | 32 |
32 namespace extensions { | 33 namespace extensions { |
33 | 34 |
34 namespace { | 35 namespace { |
35 | 36 |
36 void ThrowInvalidArgumentsException( | 37 void ThrowInvalidArgumentsException( |
37 AutomationInternalCustomBindings* automation_bindings) { | 38 AutomationInternalCustomBindings* automation_bindings) { |
38 v8::Isolate* isolate = automation_bindings->GetIsolate(); | 39 v8::Isolate* isolate = automation_bindings->GetIsolate(); |
39 automation_bindings->GetIsolate()->ThrowException( | 40 automation_bindings->GetIsolate()->ThrowException( |
40 v8::String::NewFromUtf8( | 41 v8::String::NewFromUtf8( |
41 isolate, | 42 isolate, |
42 "Invalid arguments to AutomationInternalCustomBindings function", | 43 "Invalid arguments to AutomationInternalCustomBindings function", |
43 v8::NewStringType::kNormal) | 44 v8::NewStringType::kNormal) |
44 .ToLocalChecked()); | 45 .ToLocalChecked()); |
45 | 46 |
46 LOG(FATAL) << "Invalid arguments to AutomationInternalCustomBindings function" | 47 LOG(FATAL) << "Invalid arguments to AutomationInternalCustomBindings function" |
47 << automation_bindings->context()->GetStackTraceAsString(); | 48 << automation_bindings->context()->GetStackTraceAsString(); |
48 } | 49 } |
49 | 50 |
50 v8::Local<v8::Value> CreateV8String(v8::Isolate* isolate, const char* str) { | 51 v8::Local<v8::String> CreateV8String(v8::Isolate* isolate, |
51 return v8::String::NewFromUtf8(isolate, str, v8::String::kNormalString, | 52 base::StringPiece str) { |
52 strlen(str)); | 53 return gin::StringToSymbol(isolate, str); |
53 } | 54 } |
54 | 55 |
55 v8::Local<v8::Value> CreateV8String(v8::Isolate* isolate, | 56 // Note: when building up an object to return from one of the |
56 const std::string& str) { | 57 // automation API bindings like a rect ({left: 0, top: 0, ...}) or |
57 return v8::String::NewFromUtf8(isolate, str.c_str(), | 58 // something like that, we should use this function instead of |
58 v8::String::kNormalString, str.length()); | 59 // v8::Object::Set, because a malicious extension author could use |
| 60 // Object.defineProperty to override a setter and trigger all sorts of |
| 61 // things to happen in the middle of one of our functions below. |
| 62 // |
| 63 // This is only safe when we're creating the object to return and |
| 64 // we're setting properties on it before it's been exposed to |
| 65 // untrusted scripts. |
| 66 void SafeSetV8Property(v8::Isolate* isolate, |
| 67 v8::Local<v8::Object> object, |
| 68 base::StringPiece key, |
| 69 v8::Local<v8::Value> value) { |
| 70 v8::Maybe<bool> maybe = object->CreateDataProperty( |
| 71 isolate->GetCurrentContext(), CreateV8String(isolate, key), value); |
| 72 |
| 73 // There's no legit reason CreateDataProperty should fail. |
| 74 CHECK(maybe.IsJust() && maybe.FromJust()); |
59 } | 75 } |
60 | 76 |
61 v8::Local<v8::Object> RectToV8Object(v8::Isolate* isolate, | 77 v8::Local<v8::Object> RectToV8Object(v8::Isolate* isolate, |
62 const gfx::Rect& rect) { | 78 const gfx::Rect& rect) { |
63 v8::Local<v8::Object> result(v8::Object::New(isolate)); | 79 v8::Local<v8::Object> result(v8::Object::New(isolate)); |
64 result->Set(CreateV8String(isolate, "left"), | 80 SafeSetV8Property(isolate, result, "left", |
65 v8::Integer::New(isolate, rect.x())); | 81 v8::Integer::New(isolate, rect.x())); |
66 result->Set(CreateV8String(isolate, "top"), | 82 SafeSetV8Property(isolate, result, "top", |
67 v8::Integer::New(isolate, rect.y())); | 83 v8::Integer::New(isolate, rect.y())); |
68 result->Set(CreateV8String(isolate, "width"), | 84 SafeSetV8Property(isolate, result, "width", |
69 v8::Integer::New(isolate, rect.width())); | 85 v8::Integer::New(isolate, rect.width())); |
70 result->Set(CreateV8String(isolate, "height"), | 86 SafeSetV8Property(isolate, result, "height", |
71 v8::Integer::New(isolate, rect.height())); | 87 v8::Integer::New(isolate, rect.height())); |
72 return result; | 88 return result; |
73 } | 89 } |
74 | 90 |
75 // Compute the bounding box of a node, fixing nodes with empty bounds by | 91 // Compute the bounding box of a node, fixing nodes with empty bounds by |
76 // unioning the bounds of their children. | 92 // unioning the bounds of their children. |
77 static gfx::RectF ComputeLocalNodeBounds(TreeCache* cache, ui::AXNode* node) { | 93 static gfx::RectF ComputeLocalNodeBounds(TreeCache* cache, ui::AXNode* node) { |
78 gfx::RectF bounds = node->data().location; | 94 gfx::RectF bounds = node->data().location; |
79 if (bounds.width() > 0 && bounds.height() > 0) | 95 if (bounds.width() > 0 && bounds.height() > 0) |
80 return bounds; | 96 return bounds; |
81 | 97 |
(...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 if (!cache) | 954 if (!cache) |
939 return; | 955 return; |
940 | 956 |
941 TreeCache* focused_tree_cache = nullptr; | 957 TreeCache* focused_tree_cache = nullptr; |
942 ui::AXNode* focused_node = nullptr; | 958 ui::AXNode* focused_node = nullptr; |
943 if (!GetFocusInternal(cache, &focused_tree_cache, &focused_node)) | 959 if (!GetFocusInternal(cache, &focused_tree_cache, &focused_node)) |
944 return; | 960 return; |
945 | 961 |
946 v8::Isolate* isolate = GetIsolate(); | 962 v8::Isolate* isolate = GetIsolate(); |
947 v8::Local<v8::Object> result(v8::Object::New(isolate)); | 963 v8::Local<v8::Object> result(v8::Object::New(isolate)); |
948 result->Set(CreateV8String(isolate, "treeId"), | 964 SafeSetV8Property(isolate, result, "treeId", |
949 v8::Integer::New(isolate, focused_tree_cache->tree_id)); | 965 v8::Integer::New(isolate, focused_tree_cache->tree_id)); |
950 result->Set(CreateV8String(isolate, "nodeId"), | 966 SafeSetV8Property(isolate, result, "nodeId", |
951 v8::Integer::New(isolate, focused_node->id())); | 967 v8::Integer::New(isolate, focused_node->id())); |
952 args.GetReturnValue().Set(result); | 968 args.GetReturnValue().Set(result); |
953 } | 969 } |
954 | 970 |
955 void AutomationInternalCustomBindings::GetHtmlAttributes( | 971 void AutomationInternalCustomBindings::GetHtmlAttributes( |
956 const v8::FunctionCallbackInfo<v8::Value>& args) { | 972 const v8::FunctionCallbackInfo<v8::Value>& args) { |
957 v8::Isolate* isolate = GetIsolate(); | 973 v8::Isolate* isolate = GetIsolate(); |
958 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) | 974 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) |
959 ThrowInvalidArgumentsException(this); | 975 ThrowInvalidArgumentsException(this); |
960 | 976 |
961 int tree_id = args[0]->Int32Value(); | 977 int tree_id = args[0]->Int32Value(); |
962 int node_id = args[1]->Int32Value(); | 978 int node_id = args[1]->Int32Value(); |
963 | 979 |
964 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); | 980 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); |
965 if (!cache) | 981 if (!cache) |
966 return; | 982 return; |
967 | 983 |
968 ui::AXNode* node = cache->tree.GetFromId(node_id); | 984 ui::AXNode* node = cache->tree.GetFromId(node_id); |
969 if (!node) | 985 if (!node) |
970 return; | 986 return; |
971 | 987 |
972 v8::Local<v8::Object> dst(v8::Object::New(isolate)); | 988 v8::Local<v8::Object> dst(v8::Object::New(isolate)); |
973 base::StringPairs src = node->data().html_attributes; | 989 base::StringPairs src = node->data().html_attributes; |
974 for (size_t i = 0; i < src.size(); i++) { | 990 for (size_t i = 0; i < src.size(); i++) { |
975 std::string& key = src[i].first; | 991 std::string& key = src[i].first; |
976 std::string& value = src[i].second; | 992 std::string& value = src[i].second; |
977 dst->Set(CreateV8String(isolate, key), CreateV8String(isolate, value)); | 993 SafeSetV8Property(isolate, dst, key, CreateV8String(isolate, value)); |
978 } | 994 } |
979 args.GetReturnValue().Set(dst); | 995 args.GetReturnValue().Set(dst); |
980 } | 996 } |
981 | 997 |
982 void AutomationInternalCustomBindings::GetState( | 998 void AutomationInternalCustomBindings::GetState( |
983 const v8::FunctionCallbackInfo<v8::Value>& args) { | 999 const v8::FunctionCallbackInfo<v8::Value>& args) { |
984 v8::Isolate* isolate = GetIsolate(); | 1000 v8::Isolate* isolate = GetIsolate(); |
985 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) | 1001 if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) |
986 ThrowInvalidArgumentsException(this); | 1002 ThrowInvalidArgumentsException(this); |
987 | 1003 |
988 int tree_id = args[0]->Int32Value(); | 1004 int tree_id = args[0]->Int32Value(); |
989 int node_id = args[1]->Int32Value(); | 1005 int node_id = args[1]->Int32Value(); |
990 | 1006 |
991 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); | 1007 TreeCache* cache = GetTreeCacheFromTreeID(tree_id); |
992 if (!cache) | 1008 if (!cache) |
993 return; | 1009 return; |
994 | 1010 |
995 ui::AXNode* node = cache->tree.GetFromId(node_id); | 1011 ui::AXNode* node = cache->tree.GetFromId(node_id); |
996 if (!node) | 1012 if (!node) |
997 return; | 1013 return; |
998 | 1014 |
999 v8::Local<v8::Object> state(v8::Object::New(isolate)); | 1015 v8::Local<v8::Object> state(v8::Object::New(isolate)); |
1000 uint32_t state_pos = 0, state_shifter = node->data().state; | 1016 uint32_t state_pos = 0, state_shifter = node->data().state; |
1001 while (state_shifter) { | 1017 while (state_shifter) { |
1002 if (state_shifter & 1) { | 1018 if (state_shifter & 1) { |
1003 std::string key = ToString(static_cast<ui::AXState>(state_pos)); | 1019 std::string key = ToString(static_cast<ui::AXState>(state_pos)); |
1004 state->Set(CreateV8String(isolate, key), v8::Boolean::New(isolate, true)); | 1020 SafeSetV8Property(isolate, state, key, v8::Boolean::New(isolate, true)); |
1005 } | 1021 } |
1006 state_shifter = state_shifter >> 1; | 1022 state_shifter = state_shifter >> 1; |
1007 state_pos++; | 1023 state_pos++; |
1008 } | 1024 } |
1009 | 1025 |
1010 TreeCache* top_cache = GetTreeCacheFromTreeID(0); | 1026 TreeCache* top_cache = GetTreeCacheFromTreeID(0); |
1011 if (!top_cache) | 1027 if (!top_cache) |
1012 top_cache = cache; | 1028 top_cache = cache; |
1013 TreeCache* focused_cache = nullptr; | 1029 TreeCache* focused_cache = nullptr; |
1014 ui::AXNode* focused_node = nullptr; | 1030 ui::AXNode* focused_node = nullptr; |
1015 if (GetFocusInternal(top_cache, &focused_cache, &focused_node)) { | 1031 if (GetFocusInternal(top_cache, &focused_cache, &focused_node)) { |
1016 if (focused_cache == cache && focused_node == node) { | 1032 if (focused_cache == cache && focused_node == node) { |
1017 state->Set(CreateV8String(isolate, "focused"), | 1033 SafeSetV8Property(isolate, state, "focused", |
1018 v8::Boolean::New(isolate, true)); | 1034 v8::Boolean::New(isolate, true)); |
1019 } | 1035 } |
1020 } | 1036 } |
1021 if (cache->tree.data().focus_id == node->id()) { | 1037 if (cache->tree.data().focus_id == node->id()) { |
1022 state->Set(CreateV8String(isolate, "focused"), | 1038 SafeSetV8Property(isolate, state, "focused", |
1023 v8::Boolean::New(isolate, true)); | 1039 v8::Boolean::New(isolate, true)); |
1024 } | 1040 } |
1025 | 1041 |
1026 args.GetReturnValue().Set(state); | 1042 args.GetReturnValue().Set(state); |
1027 } | 1043 } |
1028 | 1044 |
1029 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { | 1045 void AutomationInternalCustomBindings::UpdateOverallTreeChangeObserverFilter() { |
1030 tree_change_observer_overall_filter_ = 0; | 1046 tree_change_observer_overall_filter_ = 0; |
1031 for (const auto& observer : tree_change_observers_) | 1047 for (const auto& observer : tree_change_observers_) |
1032 tree_change_observer_overall_filter_ |= 1 << observer.filter; | 1048 tree_change_observer_overall_filter_ |= 1 << observer.filter; |
1033 } | 1049 } |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 for (auto id : ids) | 1429 for (auto id : ids) |
1414 nodes->AppendInteger(id); | 1430 nodes->AppendInteger(id); |
1415 args.Append(std::move(nodes)); | 1431 args.Append(std::move(nodes)); |
1416 } | 1432 } |
1417 | 1433 |
1418 bindings_system_->DispatchEventInContext("automationInternal.onNodesRemoved", | 1434 bindings_system_->DispatchEventInContext("automationInternal.onNodesRemoved", |
1419 &args, nullptr, context()); | 1435 &args, nullptr, context()); |
1420 } | 1436 } |
1421 | 1437 |
1422 } // namespace extensions | 1438 } // namespace extensions |
OLD | NEW |