Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp

Issue 1902993002: [DevTools] Introduce provisional blackboxing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "platform/v8_inspector/V8DebuggerAgentImpl.h" 5 #include "platform/v8_inspector/V8DebuggerAgentImpl.h"
6 6
7 #include "platform/inspector_protocol/String16.h" 7 #include "platform/inspector_protocol/String16.h"
8 #include "platform/inspector_protocol/Values.h" 8 #include "platform/inspector_protocol/Values.h"
9 #include "platform/v8_inspector/InjectedScript.h" 9 #include "platform/v8_inspector/InjectedScript.h"
10 #include "platform/v8_inspector/InspectedContext.h" 10 #include "platform/v8_inspector/InspectedContext.h"
(...skipping 27 matching lines...) Expand all
38 static const char v8AsyncTaskEventWillHandle[] = "willHandle"; 38 static const char v8AsyncTaskEventWillHandle[] = "willHandle";
39 static const char v8AsyncTaskEventDidHandle[] = "didHandle"; 39 static const char v8AsyncTaskEventDidHandle[] = "didHandle";
40 } 40 }
41 41
42 namespace blink { 42 namespace blink {
43 43
44 namespace DebuggerAgentState { 44 namespace DebuggerAgentState {
45 static const char javaScriptBreakpoints[] = "javaScriptBreakopints"; 45 static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
46 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState"; 46 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState";
47 static const char asyncCallStackDepth[] = "asyncCallStackDepth"; 47 static const char asyncCallStackDepth[] = "asyncCallStackDepth";
48 static const char blackboxPatterns[] = "blackboxPatterns";
49 static const char blackboxRangesByURL[] = "blackboxRangesByURL";
50 static const char blackboxRangesByHash[] = "blackboxRangesByHash";
51 static const char blackboxScriptsByURL[] = "blackboxScriptsByURL";
52 static const char blackboxScriptsByHash[] = "blackboxScriptsByHash";
48 53
49 // Breakpoint properties. 54 // Breakpoint properties.
50 static const char url[] = "url"; 55 static const char url[] = "url";
51 static const char isRegex[] = "isRegex"; 56 static const char isRegex[] = "isRegex";
52 static const char lineNumber[] = "lineNumber"; 57 static const char lineNumber[] = "lineNumber";
53 static const char columnNumber[] = "columnNumber"; 58 static const char columnNumber[] = "columnNumber";
54 static const char condition[] = "condition"; 59 static const char condition[] = "condition";
55 static const char skipAllPauses[] = "skipAllPauses"; 60 static const char skipAllPauses[] = "skipAllPauses";
56 61
57 } // namespace DebuggerAgentState; 62 } // namespace DebuggerAgentState;
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 m_state->setNumber(DebuggerAgentState::pauseOnExceptionsState, V8DebuggerImp l::DontPauseOnExceptions); 234 m_state->setNumber(DebuggerAgentState::pauseOnExceptionsState, V8DebuggerImp l::DontPauseOnExceptions);
230 m_state->setNumber(DebuggerAgentState::asyncCallStackDepth, 0); 235 m_state->setNumber(DebuggerAgentState::asyncCallStackDepth, 0);
231 236
232 if (!m_pausedContext.IsEmpty()) 237 if (!m_pausedContext.IsEmpty())
233 debugger().continueProgram(); 238 debugger().continueProgram();
234 debugger().debuggerAgentDisabled(); 239 debugger().debuggerAgentDisabled();
235 m_pausedContext.Reset(); 240 m_pausedContext.Reset();
236 JavaScriptCallFrames emptyCallFrames; 241 JavaScriptCallFrames emptyCallFrames;
237 m_pausedCallFrames.swap(emptyCallFrames); 242 m_pausedCallFrames.swap(emptyCallFrames);
238 m_scripts.clear(); 243 m_scripts.clear();
239 m_blackboxedPositions.clear();
240 m_breakpointIdToDebuggerBreakpointIds.clear(); 244 m_breakpointIdToDebuggerBreakpointIds.clear();
241 internalSetAsyncCallStackDepth(0); 245 internalSetAsyncCallStackDepth(0);
242 m_continueToLocationBreakpointId = String16(); 246 m_continueToLocationBreakpointId = String16();
243 clearBreakDetails(); 247 clearBreakDetails();
244 m_scheduledDebuggerStep = NoStep; 248 m_scheduledDebuggerStep = NoStep;
245 m_skipNextDebuggerStepOut = false; 249 m_skipNextDebuggerStepOut = false;
246 m_javaScriptPauseScheduled = false; 250 m_javaScriptPauseScheduled = false;
247 m_steppingFromFramework = false; 251 m_steppingFromFramework = false;
248 m_pausingOnNativeEvent = false; 252 m_pausingOnNativeEvent = false;
249 m_skippedStepFrameCount = 0; 253 m_skippedStepFrameCount = 0;
250 m_recursionLevelForStepFrame = 0; 254 m_recursionLevelForStepFrame = 0;
251 m_skipAllPauses = false; 255 m_skipAllPauses = false;
252 m_enabled = false; 256 m_enabled = false;
257
258 m_blackboxPattern = nullptr;
259 m_blackboxRangesByHash.clear();
260 m_blackboxRangesByURL.clear();
253 } 261 }
254 262
255 void V8DebuggerAgentImpl::internalSetAsyncCallStackDepth(int depth) 263 void V8DebuggerAgentImpl::internalSetAsyncCallStackDepth(int depth)
256 { 264 {
257 if (depth <= 0) { 265 if (depth <= 0) {
258 m_maxAsyncCallStackDepth = 0; 266 m_maxAsyncCallStackDepth = 0;
259 allAsyncTasksCanceled(); 267 allAsyncTasksCanceled();
260 } else { 268 } else {
261 m_maxAsyncCallStackDepth = depth; 269 m_maxAsyncCallStackDepth = depth;
262 } 270 }
(...skipping 14 matching lines...) Expand all
277 285
278 void V8DebuggerAgentImpl::restore() 286 void V8DebuggerAgentImpl::restore()
279 { 287 {
280 ASSERT(!m_enabled); 288 ASSERT(!m_enabled);
281 enable(); 289 enable();
282 ErrorString error; 290 ErrorString error;
283 291
284 int pauseState = V8DebuggerImpl::DontPauseOnExceptions; 292 int pauseState = V8DebuggerImpl::DontPauseOnExceptions;
285 m_state->getNumber(DebuggerAgentState::pauseOnExceptionsState, &pauseState); 293 m_state->getNumber(DebuggerAgentState::pauseOnExceptionsState, &pauseState);
286 setPauseOnExceptionsImpl(&error, pauseState); 294 setPauseOnExceptionsImpl(&error, pauseState);
295 ASSERT(error.isEmpty());
287 296
288 m_skipAllPauses = m_state->booleanProperty(DebuggerAgentState::skipAllPauses , false); 297 m_skipAllPauses = m_state->booleanProperty(DebuggerAgentState::skipAllPauses , false);
289 298
290 int asyncCallStackDepth = 0; 299 int asyncCallStackDepth = 0;
291 m_state->getNumber(DebuggerAgentState::asyncCallStackDepth, &asyncCallStackD epth); 300 m_state->getNumber(DebuggerAgentState::asyncCallStackDepth, &asyncCallStackD epth);
292 internalSetAsyncCallStackDepth(asyncCallStackDepth); 301 internalSetAsyncCallStackDepth(asyncCallStackDepth);
302
303 protocol::ListValue* blackboxPatternsValue = m_state->getArray(DebuggerAgent State::blackboxPatterns);
304 if (blackboxPatternsValue) {
305 protocol::ErrorSupport errors;
306 OwnPtr<protocol::Array<String16>> blackboxPatterns = protocol::Array<Str ing16>::parse(blackboxPatternsValue, &errors);
307 if (blackboxPatterns)
308 setBlackboxPatterns(&error, blackboxPatterns.release());
309 ASSERT(!errors.hasErrors() && error.isEmpty());
310 }
311 restoreBlackboxScripts(DebuggerAgentState::blackboxScriptsByHash, m_blackbox RangesByHash);
dgozman 2016/04/20 02:06:40 Can we use empty ranges as a meaning for "fully bl
312 restoreBlackboxScripts(DebuggerAgentState::blackboxScriptsByURL, m_blackboxR angesByURL);
313 restoreBlackboxRanges(DebuggerAgentState::blackboxRangesByHash, m_blackboxRa ngesByHash);
314 restoreBlackboxRanges(DebuggerAgentState::blackboxRangesByURL, m_blackboxRan gesByURL);
315 }
316
317 void V8DebuggerAgentImpl::restoreBlackboxScripts(const String16& key, BlackboxRa ngesByString& map)
318 {
319 protocol::ListValue* list = m_state->getArray(key);
320 if (!list)
321 return;
322 Vector<std::pair<int, int>> blackboxedRanges(1);
323 for (size_t i = 0; i < list->size(); ++i) {
324 protocol::Value* val = list->at(i);
325 String16 id;
326 bool success = val->asString(&id);
327 ASSERT_UNUSED(success, success);
328 map.set(id, blackboxedRanges);
329 }
330 }
331
332 void V8DebuggerAgentImpl::restoreBlackboxRanges(const String16& key, BlackboxRan gesByString& map)
333 {
334 using protocol::Runtime::SourceRange;
335
336 protocol::DictionaryValue* storedMap = m_state->getObject(key);
337 if (!storedMap)
338 return;
339 protocol::ErrorSupport errorSupport;
340 for (size_t i = 0; i < storedMap->size(); ++i) {
341 auto value = storedMap->at(i);
342 OwnPtr<protocol::Array<SourceRange>> ranges = protocol::Array<SourceRang e>::parse(value.second, &errorSupport);
343 ASSERT(!errorSupport.hasErrors());
344 Vector<std::pair<int, int>> blackboxedRanges(ranges->length() * 2);
345 for (size_t i = 0; i < ranges->length(); ++i) {
346 SourceRange* range = ranges->get(i);
347 blackboxedRanges[i * 2] = std::make_pair(range->getStartLine(), rang e->getStartColumn());
348 blackboxedRanges[i * 2 + 1] = std::make_pair(range->getEndLine(), ra nge->getEndColumn());
349 }
350 map.set(value.first, blackboxedRanges);
351 }
293 } 352 }
294 353
295 void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, bool ac tive) 354 void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, bool ac tive)
296 { 355 {
297 if (!checkEnabled(errorString)) 356 if (!checkEnabled(errorString))
298 return; 357 return;
299 debugger().setBreakpointsActivated(active); 358 debugger().setBreakpointsActivated(active);
300 } 359 }
301 360
302 void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skipped) 361 void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skipped)
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 557
499 bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCal lFrame* frame) 558 bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCal lFrame* frame)
500 { 559 {
501 if (!frame) 560 if (!frame)
502 return true; 561 return true;
503 ScriptsMap::iterator it = m_scripts.find(String16::number(frame->sourceID()) ); 562 ScriptsMap::iterator it = m_scripts.find(String16::number(frame->sourceID()) );
504 if (it == m_scripts.end()) { 563 if (it == m_scripts.end()) {
505 // Unknown scripts are blackboxed. 564 // Unknown scripts are blackboxed.
506 return true; 565 return true;
507 } 566 }
508 auto itBlackboxedPositions = m_blackboxedPositions.find(String16::number(fra me->sourceID())); 567 V8DebuggerScript* script = it->second;
509 if (itBlackboxedPositions == m_blackboxedPositions.end()) 568 if (m_blackboxPattern) {
569 String16 scriptSourceURL = script->sourceURL();
570 if (!scriptSourceURL.isEmpty() && m_blackboxPattern->match(scriptSourceU RL) != -1)
571 return true;
572 }
573 auto itBlackboxedRangesByHash = m_blackboxRangesByHash.find(script->hash());
574 const Vector<std::pair<int, int>>* ranges = nullptr;
575 if (itBlackboxedRangesByHash != m_blackboxRangesByHash.end()) {
576 ranges = itBlackboxedRangesByHash->second;
577 } else {
578 auto itBlackboxedRangesByURL = m_blackboxRangesByURL.find(script->source URL());
579 if (itBlackboxedRangesByURL != m_blackboxRangesByURL.end())
580 ranges = itBlackboxedRangesByURL->second;
581 }
582 if (!ranges)
510 return false; 583 return false;
511
512 protocol::Vector<std::pair<int, int>>* ranges = itBlackboxedPositions->secon d;
513 auto itRange = std::lower_bound(ranges->begin(), ranges->end(), std::make_pa ir(frame->line(), frame->column()), positionComparator); 584 auto itRange = std::lower_bound(ranges->begin(), ranges->end(), std::make_pa ir(frame->line(), frame->column()), positionComparator);
514 // Ranges array contains positions in script where blackbox state is changed . 585 // Ranges array contains positions in script where blackbox state is changed .
515 // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is blac kboxed... 586 // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is blac kboxed...
516 return std::distance(ranges->begin(), itRange) % 2; 587 return std::distance(ranges->begin(), itRange) % 2;
517 } 588 }
518 589
519 V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipExceptionPa use(JavaScriptCallFrame* topCallFrame) 590 V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipExceptionPa use(JavaScriptCallFrame* topCallFrame)
520 { 591 {
521 if (m_steppingFromFramework) 592 if (m_steppingFromFramework)
522 return RequestNoSkip; 593 return RequestNoSkip;
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 { 1114 {
1044 m_asyncTaskStacks.clear(); 1115 m_asyncTaskStacks.clear();
1045 m_recurringTasks.clear(); 1116 m_recurringTasks.clear();
1046 m_currentStacks.clear(); 1117 m_currentStacks.clear();
1047 1118
1048 #if ENABLE(ASSERT) 1119 #if ENABLE(ASSERT)
1049 m_currentTasks.clear(); 1120 m_currentTasks.clear();
1050 #endif 1121 #endif
1051 } 1122 }
1052 1123
1053 void V8DebuggerAgentImpl::setBlackboxedRanges(ErrorString* error, const String16 & scriptId, PassOwnPtr<protocol::Array<protocol::Debugger::ScriptPosition>> inPo sitions) 1124 void V8DebuggerAgentImpl::setBlackboxPatterns(ErrorString* errorString, PassOwnP tr<protocol::Array<String16>> patterns)
1054 { 1125 {
1055 if (!m_scripts.contains(scriptId)) { 1126 if (!patterns->length()) {
1056 *error = "No script with passed id."; 1127 m_blackboxPattern = nullptr;
1128 m_state->setArray(DebuggerAgentState::blackboxPatterns, patterns->serial ize());
1057 return; 1129 return;
1058 } 1130 }
1059 1131
1060 if (!inPositions->length()) { 1132 String16 pattern;
1061 m_blackboxedPositions.remove(scriptId); 1133 for (size_t i = 0; i < patterns->length() - 1; ++i)
1134 pattern = pattern + patterns->get(i) + "|";
1135 pattern = "(" + pattern + patterns->get(patterns->length() - 1) + ")";
1136
1137 OwnPtr<V8Regex> regex = adoptPtr(new V8Regex(m_debugger, pattern, true /** c aseSensitive */, false /** multiline */));
1138 if (!regex->isValid()) {
1139 *errorString = "Pattern parser error: " + regex->errorMessage();
1062 return; 1140 return;
1063 } 1141 }
1064 1142
1065 protocol::Vector<std::pair<int, int>> positions(inPositions->length()); 1143 m_blackboxPattern = regex.release();
1066 for (size_t i = 0; i < positions.size(); ++i) { 1144 m_state->setArray(DebuggerAgentState::blackboxPatterns, patterns->serialize( ));
1067 protocol::Debugger::ScriptPosition* position = inPositions->get(i); 1145 }
1068 if (position->getLine() < 0) { 1146
1069 *error = "Position missing 'line' or 'line' < 0."; 1147 void V8DebuggerAgentImpl::setScriptBlackboxed(ErrorString* errorString, const Ma ybe<String16>& hash, const Maybe<String16>& url, const Maybe<protocol::Array<pro tocol::Runtime::SourceRange>>& optRanges)
1070 return; 1148 {
1149 using protocol::Runtime::SourceRange;
1150
1151 if (!hash.isJust() && !url.isJust()) {
1152 *errorString = "Hash or URL should be set";
1153 return;
1154 }
1155 BlackboxRangesByString& idToBlackboxRanges = hash.isJust() ? m_blackboxRange sByHash : m_blackboxRangesByURL;
1156 String16 id = hash.isJust() ? hash.fromJust() : url.fromJust();
1157
1158 if (!optRanges.isJust()) {
1159 const String16& stateKey = hash.isJust() ? DebuggerAgentState::blackboxS criptsByHash : DebuggerAgentState::blackboxScriptsByURL;
1160 protocol::ListValue* stateBlackboxedScripts = m_state->getArray(stateKey );
1161 if (!stateBlackboxedScripts) {
1162 m_state->setArray(stateKey, protocol::ListValue::create());
1163 stateBlackboxedScripts = m_state->getArray(stateKey);
1071 } 1164 }
1072 if (position->getColumn() < 0) {
1073 *error = "Position missing 'column' or 'column' < 0.";
1074 return;
1075 }
1076 positions[i] = std::make_pair(position->getLine(), position->getColumn() );
1077 }
1078 1165
1079 for (size_t i = 1; i < positions.size(); ++i) { 1166 Vector<std::pair<int, int>> blackboxedRanges(1);
1080 if (positions[i - 1].first < positions[i].first) 1167 idToBlackboxRanges.set(id, blackboxedRanges);
1081 continue; 1168 stateBlackboxedScripts->pushValue(protocol::StringValue::create(id));
1082 if (positions[i - 1].first == positions[i].first && positions[i - 1].sec ond < positions[i].second)
1083 continue;
1084 *error = "Input positions array is not sorted or contains duplicate valu es.";
1085 return; 1169 return;
1086 } 1170 }
1087 1171
1088 m_blackboxedPositions.set(scriptId, positions); 1172 const String16& stateKey = hash.isJust() ? DebuggerAgentState::blackboxRange sByHash : DebuggerAgentState::blackboxRangesByURL;
1173 protocol::DictionaryValue* stateMap = m_state->getObject(stateKey);
1174 if (!stateMap) {
1175 m_state->setObject(stateKey, protocol::DictionaryValue::create());
1176 stateMap = m_state->getObject(stateKey);
1177 }
1178 protocol::Array<SourceRange>* ranges = optRanges.fromJust();
1179 if (!ranges->length()) {
1180 idToBlackboxRanges.remove(id);
1181 stateMap->remove(id);
1182 return;
1183 }
1184
1185 String16 errors;
dgozman 2016/04/20 02:06:40 Let's extract validation into a helper function.
1186 for (size_t i = 0; i < ranges->length(); ++i) {
1187 SourceRange* range = ranges->get(i);
1188 if (range->getStartLine() > range->getEndLine())
1189 errors = errors + " 'startLine' should be not more then 'endLine' in (" + String16::number(i + 1) + ").";
1190 if (range->getStartLine() == range->getEndLine() && range->getStartColum n() >= range->getEndColumn())
1191 errors = errors + " 'startColumn' should be less then 'endColumn' if 'startLine' == 'endLine' in (" + String16::number(i + 1) + ").";
1192 if (i > 0) {
1193 SourceRange* prevRange = ranges->get(i - 1);
1194 if (prevRange->getEndLine() > range->getStartLine() || (prevRange->g etEndLine() == range->getStartLine() && prevRange->getEndColumn() > range->getSt artColumn()))
1195 errors = errors + " Records in ranges array should be sorted and disjoint.";
1196 }
1197 }
1198 if (!errors.isEmpty()) {
1199 *errorString = errors;
1200 return;
1201 }
1202 Vector<std::pair<int, int>> blackboxedRanges(ranges->length() * 2);
1203 for (size_t i = 0; i < ranges->length(); ++i) {
1204 SourceRange* range = ranges->get(i);
1205 blackboxedRanges[i * 2] = std::make_pair(range->getStartLine(), range->g etStartColumn());
1206 blackboxedRanges[i * 2 + 1] = std::make_pair(range->getEndLine(), range- >getEndColumn());
1207 }
1208 idToBlackboxRanges.set(id, blackboxedRanges);
1209 stateMap->setArray(id, ranges->serialize());
1089 } 1210 }
1090 1211
1091 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) 1212 void V8DebuggerAgentImpl::willExecuteScript(int scriptId)
1092 { 1213 {
1093 changeJavaScriptRecursionLevel(+1); 1214 changeJavaScriptRecursionLevel(+1);
1094 // Fast return. 1215 // Fast return.
1095 if (m_scheduledDebuggerStep != StepInto) 1216 if (m_scheduledDebuggerStep != StepInto)
1096 return; 1217 return;
1097 // Skip unknown scripts (e.g. InjectedScript). 1218 // Skip unknown scripts (e.g. InjectedScript).
1098 if (!m_scripts.contains(String16::number(scriptId))) 1219 if (!m_scripts.contains(String16::number(scriptId)))
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 { 1529 {
1409 removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, so urce)); 1530 removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, so urce));
1410 } 1531 }
1411 1532
1412 void V8DebuggerAgentImpl::reset() 1533 void V8DebuggerAgentImpl::reset()
1413 { 1534 {
1414 if (!enabled()) 1535 if (!enabled())
1415 return; 1536 return;
1416 m_scheduledDebuggerStep = NoStep; 1537 m_scheduledDebuggerStep = NoStep;
1417 m_scripts.clear(); 1538 m_scripts.clear();
1418 m_blackboxedPositions.clear();
1419 m_breakpointIdToDebuggerBreakpointIds.clear(); 1539 m_breakpointIdToDebuggerBreakpointIds.clear();
1420 allAsyncTasksCanceled(); 1540 allAsyncTasksCanceled();
1421 } 1541 }
1422 1542
1423 } // namespace blink 1543 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698