Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / InspectorDebuggerAgent.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2013 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "core/inspector/InspectorDebuggerAgent.h"
32 #include "core/inspector/JavaScriptCallFrame.h"
33
34 #include "bindings/v8/ScriptDebugServer.h"
35 #include "bindings/v8/ScriptObject.h"
36 #include "bindings/v8/ScriptRegexp.h"
37 #include "bindings/v8/ScriptSourceCode.h"
38 #include "core/dom/Document.h"
39 #include "core/fetch/Resource.h"
40 #include "core/inspector/ContentSearchUtils.h"
41 #include "core/inspector/InjectedScriptManager.h"
42 #include "core/inspector/InspectorPageAgent.h"
43 #include "core/inspector/InspectorState.h"
44 #include "core/inspector/InstrumentingAgents.h"
45 #include "core/inspector/ScriptArguments.h"
46 #include "core/inspector/ScriptCallStack.h"
47 #include "platform/JSONValues.h"
48 #include "wtf/text/WTFString.h"
49
50 using WebCore::TypeBuilder::Array;
51 using WebCore::TypeBuilder::Debugger::BreakpointId;
52 using WebCore::TypeBuilder::Debugger::CallFrame;
53 using WebCore::TypeBuilder::Debugger::FunctionDetails;
54 using WebCore::TypeBuilder::Debugger::ScriptId;
55 using WebCore::TypeBuilder::Debugger::StackTrace;
56 using WebCore::TypeBuilder::Runtime::RemoteObject;
57
58 namespace WebCore {
59
60 namespace DebuggerAgentState {
61 static const char debuggerEnabled[] = "debuggerEnabled";
62 static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
63 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState";
64 static const char asyncCallStackDepth[] = "asyncCallStackDepth";
65
66 // Breakpoint properties.
67 static const char url[] = "url";
68 static const char isRegex[] = "isRegex";
69 static const char lineNumber[] = "lineNumber";
70 static const char columnNumber[] = "columnNumber";
71 static const char condition[] = "condition";
72 static const char isAnti[] = "isAnti";
73 static const char skipStackPattern[] = "skipStackPattern";
74 static const char skipAllPauses[] = "skipAllPauses";
75 static const char skipAllPausesExpiresOnReload[] = "skipAllPausesExpiresOnReload";
76
77 };
78
79 static const int numberOfStepsBeforeStepOut = 20;
80
81 const char InspectorDebuggerAgent::backtraceObjectGroup[] = "backtrace";
82
83 static String breakpointIdSuffix(InspectorDebuggerAgent::BreakpointSource source)
84 {
85     switch (source) {
86     case InspectorDebuggerAgent::UserBreakpointSource:
87         break;
88     case InspectorDebuggerAgent::DebugCommandBreakpointSource:
89         return ":debug";
90     case InspectorDebuggerAgent::MonitorCommandBreakpointSource:
91         return ":monitor";
92     }
93     return String();
94 }
95
96 static String generateBreakpointId(const String& scriptId, int lineNumber, int columnNumber, InspectorDebuggerAgent::BreakpointSource source)
97 {
98     return scriptId + ':' + String::number(lineNumber) + ':' + String::number(columnNumber) + breakpointIdSuffix(source);
99 }
100
101 InspectorDebuggerAgent::InspectorDebuggerAgent(InjectedScriptManager* injectedScriptManager)
102     : InspectorBaseAgent<InspectorDebuggerAgent>("Debugger")
103     , m_injectedScriptManager(injectedScriptManager)
104     , m_frontend(0)
105     , m_pausedScriptState(nullptr)
106     , m_javaScriptPauseScheduled(false)
107     , m_listener(0)
108     , m_skipStepInCount(numberOfStepsBeforeStepOut)
109     , m_skipAllPauses(false)
110 {
111 }
112
113 InspectorDebuggerAgent::~InspectorDebuggerAgent()
114 {
115     ASSERT(!m_instrumentingAgents->inspectorDebuggerAgent());
116 }
117
118 void InspectorDebuggerAgent::init()
119 {
120     // FIXME: make breakReason optional so that there was no need to init it with "other".
121     clearBreakDetails();
122     m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
123 }
124
125 void InspectorDebuggerAgent::enable()
126 {
127     m_instrumentingAgents->setInspectorDebuggerAgent(this);
128
129     // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
130     scriptDebugServer().setBreakpointsActivated(true);
131     startListeningScriptDebugServer();
132
133     if (m_listener)
134         m_listener->debuggerWasEnabled();
135 }
136
137 void InspectorDebuggerAgent::disable()
138 {
139     m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, JSONObject::create());
140     m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
141     m_state->setString(DebuggerAgentState::skipStackPattern, "");
142     m_state->setLong(DebuggerAgentState::asyncCallStackDepth, 0);
143     m_instrumentingAgents->setInspectorDebuggerAgent(0);
144
145     stopListeningScriptDebugServer();
146     scriptDebugServer().clearBreakpoints();
147     scriptDebugServer().clearCompiledScripts();
148     clear();
149
150     if (m_listener)
151         m_listener->debuggerWasDisabled();
152
153     m_skipAllPauses = false;
154 }
155
156 bool InspectorDebuggerAgent::enabled()
157 {
158     return m_state->getBoolean(DebuggerAgentState::debuggerEnabled);
159 }
160
161 void InspectorDebuggerAgent::enable(ErrorString*)
162 {
163     if (enabled())
164         return;
165
166     enable();
167     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
168
169     ASSERT(m_frontend);
170 }
171
172 void InspectorDebuggerAgent::disable(ErrorString*)
173 {
174     if (!enabled())
175         return;
176
177     disable();
178     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
179 }
180
181 static PassOwnPtr<ScriptRegexp> compileSkipCallFramePattern(String patternText)
182 {
183     if (patternText.isEmpty())
184         return nullptr;
185     OwnPtr<ScriptRegexp> result = adoptPtr(new ScriptRegexp(patternText, TextCaseSensitive));
186     if (!result->isValid())
187         result.clear();
188     return result.release();
189 }
190
191 void InspectorDebuggerAgent::restore()
192 {
193     if (enabled()) {
194         m_frontend->globalObjectCleared();
195         enable();
196         long pauseState = m_state->getLong(DebuggerAgentState::pauseOnExceptionsState);
197         String error;
198         setPauseOnExceptionsImpl(&error, pauseState);
199         m_cachedSkipStackRegExp = compileSkipCallFramePattern(m_state->getString(DebuggerAgentState::skipStackPattern));
200         m_skipAllPauses = m_state->getBoolean(DebuggerAgentState::skipAllPauses);
201         if (m_skipAllPauses && m_state->getBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload)) {
202             m_skipAllPauses = false;
203             m_state->setBoolean(DebuggerAgentState::skipAllPauses, false);
204         }
205         m_asyncCallStackTracker.setAsyncCallStackDepth(m_state->getLong(DebuggerAgentState::asyncCallStackDepth));
206     }
207 }
208
209 void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
210 {
211     m_frontend = frontend->debugger();
212 }
213
214 void InspectorDebuggerAgent::clearFrontend()
215 {
216     m_frontend = 0;
217
218     if (!enabled())
219         return;
220
221     disable();
222
223     // FIXME: due to m_state->mute() hack in InspectorController, debuggerEnabled is actually set to false only
224     // in InspectorState, but not in cookie. That's why after navigation debuggerEnabled will be true,
225     // but after front-end re-open it will still be false.
226     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
227 }
228
229 void InspectorDebuggerAgent::setBreakpointsActive(ErrorString*, bool active)
230 {
231     scriptDebugServer().setBreakpointsActivated(active);
232 }
233
234 void InspectorDebuggerAgent::setSkipAllPauses(ErrorString*, bool skipped, const bool* untilReload)
235 {
236     m_skipAllPauses = skipped;
237     bool untilReloadValue = untilReload && *untilReload;
238     m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
239     m_state->setBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload, untilReloadValue);
240 }
241
242 void InspectorDebuggerAgent::pageDidCommitLoad()
243 {
244     if (m_state->getBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload)) {
245         m_skipAllPauses = false;
246         m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
247     }
248 }
249
250 bool InspectorDebuggerAgent::isPaused()
251 {
252     return scriptDebugServer().isPaused();
253 }
254
255 bool InspectorDebuggerAgent::runningNestedMessageLoop()
256 {
257     return scriptDebugServer().runningNestedMessageLoop();
258 }
259
260 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type)
261 {
262     if (source == ConsoleAPIMessageSource && type == AssertMessageType && scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions)
263         breakProgram(InspectorFrontend::Debugger::Reason::Assert, nullptr);
264 }
265
266 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel, const String&, ScriptCallStack*, unsigned long)
267 {
268     addMessageToConsole(source, type);
269 }
270
271 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel, const String&, ScriptState*, ScriptArguments*, unsigned long)
272 {
273     addMessageToConsole(source, type);
274 }
275
276 String InspectorDebuggerAgent::preprocessEventListener(LocalFrame* frame, const String& source, const String& url, const String& functionName)
277 {
278     return scriptDebugServer().preprocessEventListener(frame, source, url, functionName);
279 }
280
281 PassOwnPtr<ScriptSourceCode> InspectorDebuggerAgent::preprocess(LocalFrame* frame, const ScriptSourceCode& sourceCode)
282 {
283     return scriptDebugServer().preprocess(frame, sourceCode);
284 }
285
286 static PassRefPtr<JSONObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex, bool isAnti)
287 {
288     RefPtr<JSONObject> breakpointObject = JSONObject::create();
289     breakpointObject->setString(DebuggerAgentState::url, url);
290     breakpointObject->setNumber(DebuggerAgentState::lineNumber, lineNumber);
291     breakpointObject->setNumber(DebuggerAgentState::columnNumber, columnNumber);
292     breakpointObject->setString(DebuggerAgentState::condition, condition);
293     breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex);
294     breakpointObject->setBoolean(DebuggerAgentState::isAnti, isAnti);
295     return breakpointObject;
296 }
297
298 static bool matches(const String& url, const String& pattern, bool isRegex)
299 {
300     if (isRegex) {
301         ScriptRegexp regex(pattern, TextCaseSensitive);
302         return regex.match(url) != -1;
303     }
304     return url == pattern;
305 }
306
307 void InspectorDebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int lineNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const String* const optionalCondition, const bool* isAntiBreakpoint, BreakpointId* outBreakpointId, RefPtr<Array<TypeBuilder::Debugger::Location> >& locations)
308 {
309     locations = Array<TypeBuilder::Debugger::Location>::create();
310     if (!optionalURL == !optionalURLRegex) {
311         *errorString = "Either url or urlRegex must be specified.";
312         return;
313     }
314
315     bool isAntiBreakpointValue = isAntiBreakpoint && *isAntiBreakpoint;
316
317     String url = optionalURL ? *optionalURL : *optionalURLRegex;
318     int columnNumber;
319     if (optionalColumnNumber) {
320         columnNumber = *optionalColumnNumber;
321         if (columnNumber < 0) {
322             *errorString = "Incorrect column number";
323             return;
324         }
325     } else {
326         columnNumber = isAntiBreakpointValue ? -1 : 0;
327     }
328     String condition = optionalCondition ? *optionalCondition : "";
329     bool isRegex = optionalURLRegex;
330
331     String breakpointId = (isRegex ? "/" + url + "/" : url) + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
332     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
333     if (breakpointsCookie->find(breakpointId) != breakpointsCookie->end()) {
334         *errorString = "Breakpoint at specified location already exists.";
335         return;
336     }
337
338     breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex, isAntiBreakpointValue));
339     m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
340
341     if (!isAntiBreakpointValue) {
342         ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
343         for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
344             if (!matches(it->value.url, url, isRegex))
345                 continue;
346             RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(breakpointId, it->key, breakpoint, UserBreakpointSource);
347             if (location)
348                 locations->addItem(location);
349         }
350     }
351     *outBreakpointId = breakpointId;
352 }
353
354 static bool parseLocation(ErrorString* errorString, PassRefPtr<JSONObject> location, String* scriptId, int* lineNumber, int* columnNumber)
355 {
356     if (!location->getString("scriptId", scriptId) || !location->getNumber("lineNumber", lineNumber)) {
357         // FIXME: replace with input validation.
358         *errorString = "scriptId and lineNumber are required.";
359         return false;
360     }
361     *columnNumber = 0;
362     location->getNumber("columnNumber", columnNumber);
363     return true;
364 }
365
366 void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPtr<JSONObject>& location, const String* const optionalCondition, BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
367 {
368     String scriptId;
369     int lineNumber;
370     int columnNumber;
371
372     if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
373         return;
374
375     String condition = optionalCondition ? *optionalCondition : emptyString();
376
377     String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, UserBreakpointSource);
378     if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpointIdToDebugServerBreakpointIds.end()) {
379         *errorString = "Breakpoint at specified location already exists.";
380         return;
381     }
382     ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
383     actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, UserBreakpointSource);
384     if (actualLocation)
385         *outBreakpointId = breakpointId;
386     else
387         *errorString = "Could not resolve breakpoint";
388 }
389
390 void InspectorDebuggerAgent::removeBreakpoint(ErrorString*, const String& breakpointId)
391 {
392     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
393     JSONObject::iterator it = breakpointsCookie->find(breakpointId);
394     bool isAntibreakpoint = false;
395     if (it != breakpointsCookie->end()) {
396         RefPtr<JSONObject> breakpointObject = it->value->asObject();
397         breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
398         breakpointsCookie->remove(breakpointId);
399         m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
400     }
401
402     if (!isAntibreakpoint)
403         removeBreakpoint(breakpointId);
404 }
405
406 void InspectorDebuggerAgent::removeBreakpoint(const String& breakpointId)
407 {
408     BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
409     if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
410         return;
411     for (size_t i = 0; i < debugServerBreakpointIdsIterator->value.size(); ++i) {
412         const String& debugServerBreakpointId = debugServerBreakpointIdsIterator->value[i];
413         scriptDebugServer().removeBreakpoint(debugServerBreakpointId);
414         m_serverBreakpoints.remove(debugServerBreakpointId);
415     }
416     m_breakpointIdToDebugServerBreakpointIds.remove(debugServerBreakpointIdsIterator);
417 }
418
419 void InspectorDebuggerAgent::continueToLocation(ErrorString* errorString, const RefPtr<JSONObject>& location, const bool* interstateLocationOpt)
420 {
421     bool interstateLocation = interstateLocationOpt ? *interstateLocationOpt : false;
422     if (!m_continueToLocationBreakpointId.isEmpty()) {
423         scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
424         m_continueToLocationBreakpointId = "";
425     }
426
427     String scriptId;
428     int lineNumber;
429     int columnNumber;
430
431     if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
432         return;
433
434     ScriptBreakpoint breakpoint(lineNumber, columnNumber, "");
435     m_continueToLocationBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &lineNumber, &columnNumber, interstateLocation);
436     resume(errorString);
437 }
438
439 void InspectorDebuggerAgent::getStepInPositions(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location> >& positions)
440 {
441     if (!isPaused() || m_currentCallStack.isEmpty()) {
442         *errorString = "Attempt to access callframe when debugger is not on pause";
443         return;
444     }
445     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
446     if (injectedScript.isEmpty()) {
447         *errorString = "Inspected frame has gone";
448         return;
449     }
450
451     injectedScript.getStepInPositions(errorString, m_currentCallStack, callFrameId, positions);
452 }
453
454 void InspectorDebuggerAgent::getBacktrace(ErrorString* errorString, RefPtr<Array<CallFrame> >& callFrames, RefPtr<StackTrace>& asyncStackTrace)
455 {
456     if (!assertPaused(errorString))
457         return;
458     m_currentCallStack = scriptDebugServer().currentCallFrames();
459     callFrames = currentCallFrames();
460     asyncStackTrace = currentAsyncStackTrace();
461 }
462
463 String InspectorDebuggerAgent::scriptURL(JavaScriptCallFrame* frame)
464 {
465     String scriptIdString = String::number(frame->sourceID());
466     ScriptsMap::iterator it = m_scripts.find(scriptIdString);
467     if (it == m_scripts.end())
468         return String();
469     return it->value.url;
470 }
471
472 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipExceptionPause(RefPtr<JavaScriptCallFrame>& topFrame)
473 {
474     if (m_skipAllPauses)
475         return ScriptDebugListener::Continue;
476     if (!topFrame)
477         return ScriptDebugListener::NoSkip;
478
479     String topFrameScriptUrl = scriptURL(topFrame.get());
480     if (m_cachedSkipStackRegExp && !topFrameScriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(topFrameScriptUrl) != -1)
481         return ScriptDebugListener::Continue;
482
483     // Match against breakpoints.
484     if (topFrameScriptUrl.isEmpty())
485         return ScriptDebugListener::NoSkip;
486
487     // Prepare top frame parameters.
488     int topFrameLineNumber = topFrame->line();
489     int topFrameColumnNumber = topFrame->column();
490
491     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
492     for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
493         RefPtr<JSONObject> breakpointObject = it->value->asObject();
494         bool isAntibreakpoint;
495         breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
496         if (!isAntibreakpoint)
497             continue;
498
499         int breakLineNumber;
500         breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakLineNumber);
501         int breakColumnNumber;
502         breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakColumnNumber);
503
504         if (breakLineNumber != topFrameLineNumber)
505             continue;
506
507         if (breakColumnNumber != -1 && breakColumnNumber != topFrameColumnNumber)
508             continue;
509
510         bool isRegex;
511         breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
512         String url;
513         breakpointObject->getString(DebuggerAgentState::url, &url);
514         if (!matches(topFrameScriptUrl, url, isRegex))
515             continue;
516
517         return ScriptDebugListener::Continue;
518     }
519
520     return ScriptDebugListener::NoSkip;
521 }
522
523 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipBreakpointPause(RefPtr<JavaScriptCallFrame>& topFrame)
524 {
525     if (m_skipAllPauses)
526         return ScriptDebugListener::Continue;
527     if (!topFrame)
528         return ScriptDebugListener::NoSkip;
529     return ScriptDebugListener::NoSkip;
530 }
531
532 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipStepPause(RefPtr<JavaScriptCallFrame>& topFrame)
533 {
534     if (m_skipAllPauses)
535         return ScriptDebugListener::Continue;
536     if (!topFrame)
537         return ScriptDebugListener::NoSkip;
538
539     if (m_cachedSkipStackRegExp) {
540         String scriptUrl = scriptURL(topFrame.get());
541         if (!scriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(scriptUrl) != -1) {
542             if (m_skipStepInCount > 0) {
543                 --m_skipStepInCount;
544                 return ScriptDebugListener::StepInto;
545             }
546             return ScriptDebugListener::StepOut;
547         }
548     }
549     return ScriptDebugListener::NoSkip;
550 }
551
552 PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source)
553 {
554     ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
555     if (scriptIterator == m_scripts.end())
556         return nullptr;
557     Script& script = scriptIterator->value;
558     if (breakpoint.lineNumber < script.startLine || script.endLine < breakpoint.lineNumber)
559         return nullptr;
560
561     int actualLineNumber;
562     int actualColumnNumber;
563     String debugServerBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber, false);
564     if (debugServerBreakpointId.isEmpty())
565         return nullptr;
566
567     m_serverBreakpoints.set(debugServerBreakpointId, std::make_pair(breakpointId, source));
568
569     BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
570     if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
571         m_breakpointIdToDebugServerBreakpointIds.set(breakpointId, Vector<String>()).storedValue->value.append(debugServerBreakpointId);
572     else
573         debugServerBreakpointIdsIterator->value.append(debugServerBreakpointId);
574
575     RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
576         .setScriptId(scriptId)
577         .setLineNumber(actualLineNumber);
578     location->setColumnNumber(actualColumnNumber);
579     return location;
580 }
581
582 void InspectorDebuggerAgent::searchInContent(ErrorString* error, const String& scriptId, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Array<WebCore::TypeBuilder::Page::SearchMatch> >& results)
583 {
584     bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
585     bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
586
587     ScriptsMap::iterator it = m_scripts.find(scriptId);
588     if (it != m_scripts.end())
589         results = ContentSearchUtils::searchInTextByLines(it->value.source, query, caseSensitive, isRegex);
590     else
591         *error = "No script for id: " + scriptId;
592 }
593
594 void InspectorDebuggerAgent::setScriptSource(ErrorString* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, const String& scriptId, const String& newContent, const bool* const preview, RefPtr<Array<CallFrame> >& newCallFrames, RefPtr<JSONObject>& result, RefPtr<StackTrace>& asyncStackTrace)
595 {
596     bool previewOnly = preview && *preview;
597     if (!scriptDebugServer().setScriptSource(scriptId, newContent, previewOnly, error, errorData, &m_currentCallStack, &result))
598         return;
599     newCallFrames = currentCallFrames();
600     asyncStackTrace = currentAsyncStackTrace();
601 }
602
603 void InspectorDebuggerAgent::restartFrame(ErrorString* errorString, const String& callFrameId, RefPtr<Array<CallFrame> >& newCallFrames, RefPtr<JSONObject>& result, RefPtr<StackTrace>& asyncStackTrace)
604 {
605     if (!isPaused() || m_currentCallStack.isEmpty()) {
606         *errorString = "Attempt to access callframe when debugger is not on pause";
607         return;
608     }
609     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
610     if (injectedScript.isEmpty()) {
611         *errorString = "Inspected frame has gone";
612         return;
613     }
614
615     injectedScript.restartFrame(errorString, m_currentCallStack, callFrameId, &result);
616     m_currentCallStack = scriptDebugServer().currentCallFrames();
617     newCallFrames = currentCallFrames();
618     asyncStackTrace = currentAsyncStackTrace();
619 }
620
621 void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& scriptId, String* scriptSource)
622 {
623     ScriptsMap::iterator it = m_scripts.find(scriptId);
624     if (it != m_scripts.end())
625         *scriptSource = it->value.source;
626     else
627         *error = "No script for id: " + scriptId;
628 }
629
630 void InspectorDebuggerAgent::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>& details)
631 {
632     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(functionId);
633     if (injectedScript.isEmpty()) {
634         *errorString = "Function object id is obsolete";
635         return;
636     }
637     injectedScript.getFunctionDetails(errorString, functionId, &details);
638 }
639
640 void InspectorDebuggerAgent::schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
641 {
642     if (m_javaScriptPauseScheduled)
643         return;
644     m_breakReason = breakReason;
645     m_breakAuxData = data;
646     scriptDebugServer().setPauseOnNextStatement(true);
647 }
648
649 void InspectorDebuggerAgent::cancelPauseOnNextStatement()
650 {
651     if (m_javaScriptPauseScheduled)
652         return;
653     clearBreakDetails();
654     scriptDebugServer().setPauseOnNextStatement(false);
655 }
656
657 void InspectorDebuggerAgent::didInstallTimer(ExecutionContext* context, int timerId, int timeout, bool singleShot)
658 {
659     if (m_asyncCallStackTracker.isEnabled())
660         m_asyncCallStackTracker.didInstallTimer(context, timerId, singleShot, scriptDebugServer().currentCallFramesForAsyncStack());
661 }
662
663 void InspectorDebuggerAgent::didRemoveTimer(ExecutionContext* context, int timerId)
664 {
665     if (m_asyncCallStackTracker.isEnabled())
666         m_asyncCallStackTracker.didRemoveTimer(context, timerId);
667 }
668
669 bool InspectorDebuggerAgent::willFireTimer(ExecutionContext* context, int timerId)
670 {
671     if (m_asyncCallStackTracker.isEnabled())
672         m_asyncCallStackTracker.willFireTimer(context, timerId);
673     return true;
674 }
675
676 void InspectorDebuggerAgent::didFireTimer()
677 {
678     if (m_asyncCallStackTracker.isEnabled())
679         m_asyncCallStackTracker.didFireAsyncCall();
680     cancelPauseOnNextStatement();
681 }
682
683 void InspectorDebuggerAgent::didRequestAnimationFrame(Document* document, int callbackId)
684 {
685     if (m_asyncCallStackTracker.isEnabled())
686         m_asyncCallStackTracker.didRequestAnimationFrame(document, callbackId, scriptDebugServer().currentCallFramesForAsyncStack());
687 }
688
689 void InspectorDebuggerAgent::didCancelAnimationFrame(Document* document, int callbackId)
690 {
691     if (m_asyncCallStackTracker.isEnabled())
692         m_asyncCallStackTracker.didCancelAnimationFrame(document, callbackId);
693 }
694
695 bool InspectorDebuggerAgent::willFireAnimationFrame(Document* document, int callbackId)
696 {
697     if (m_asyncCallStackTracker.isEnabled())
698         m_asyncCallStackTracker.willFireAnimationFrame(document, callbackId);
699     return true;
700 }
701
702 void InspectorDebuggerAgent::didFireAnimationFrame()
703 {
704     if (m_asyncCallStackTracker.isEnabled())
705         m_asyncCallStackTracker.didFireAsyncCall();
706 }
707
708 void InspectorDebuggerAgent::didAddEventListener(EventTarget* eventTarget, const AtomicString& eventType, EventListener* listener, bool useCapture)
709 {
710     if (m_asyncCallStackTracker.isEnabled())
711         m_asyncCallStackTracker.didAddEventListener(eventTarget, eventType, listener, useCapture, scriptDebugServer().currentCallFramesForAsyncStack());
712 }
713
714 void InspectorDebuggerAgent::didRemoveEventListener(EventTarget* eventTarget, const AtomicString& eventType, EventListener* listener, bool useCapture)
715 {
716     if (m_asyncCallStackTracker.isEnabled())
717         m_asyncCallStackTracker.didRemoveEventListener(eventTarget, eventType, listener, useCapture);
718 }
719
720 void InspectorDebuggerAgent::didRemoveAllEventListeners(EventTarget* eventTarget)
721 {
722     if (m_asyncCallStackTracker.isEnabled())
723         m_asyncCallStackTracker.didRemoveAllEventListeners(eventTarget);
724 }
725
726 void InspectorDebuggerAgent::willHandleEvent(EventTarget* eventTarget, const AtomicString& eventType, EventListener* listener, bool useCapture)
727 {
728     if (m_asyncCallStackTracker.isEnabled())
729         m_asyncCallStackTracker.willHandleEvent(eventTarget, eventType, listener, useCapture);
730 }
731
732 void InspectorDebuggerAgent::didHandleEvent()
733 {
734     if (m_asyncCallStackTracker.isEnabled())
735         m_asyncCallStackTracker.didFireAsyncCall();
736     cancelPauseOnNextStatement();
737 }
738
739 void InspectorDebuggerAgent::willLoadXHR(XMLHttpRequest* xhr, ThreadableLoaderClient*, const AtomicString&, const KURL&, bool async, FormData*, const HTTPHeaderMap&, bool)
740 {
741     if (m_asyncCallStackTracker.isEnabled() && async)
742         m_asyncCallStackTracker.willLoadXHR(xhr, scriptDebugServer().currentCallFramesForAsyncStack());
743 }
744
745 void InspectorDebuggerAgent::didEnqueueMutationRecord(ExecutionContext* context, MutationObserver* observer)
746 {
747     if (m_asyncCallStackTracker.isEnabled() && !m_asyncCallStackTracker.hasEnqueuedMutationRecord(context, observer))
748         m_asyncCallStackTracker.didEnqueueMutationRecord(context, observer, scriptDebugServer().currentCallFramesForAsyncStack());
749 }
750
751 void InspectorDebuggerAgent::didClearAllMutationRecords(ExecutionContext* context, MutationObserver* observer)
752 {
753     if (m_asyncCallStackTracker.isEnabled())
754         m_asyncCallStackTracker.didClearAllMutationRecords(context, observer);
755 }
756
757 void InspectorDebuggerAgent::willDeliverMutationRecords(ExecutionContext* context, MutationObserver* observer)
758 {
759     if (m_asyncCallStackTracker.isEnabled())
760         m_asyncCallStackTracker.willDeliverMutationRecords(context, observer);
761 }
762
763 void InspectorDebuggerAgent::didDeliverMutationRecords()
764 {
765     if (m_asyncCallStackTracker.isEnabled())
766         m_asyncCallStackTracker.didFireAsyncCall();
767 }
768
769 void InspectorDebuggerAgent::didPostPromiseTask(ExecutionContext* context, ExecutionContextTask* task, bool isResolved)
770 {
771     if (m_asyncCallStackTracker.isEnabled())
772         m_asyncCallStackTracker.didPostPromiseTask(context, task, isResolved, scriptDebugServer().currentCallFramesForAsyncStack());
773 }
774
775 void InspectorDebuggerAgent::willPerformPromiseTask(ExecutionContext* context, ExecutionContextTask* task)
776 {
777     if (m_asyncCallStackTracker.isEnabled())
778         m_asyncCallStackTracker.willPerformPromiseTask(context, task);
779 }
780
781 void InspectorDebuggerAgent::didPerformPromiseTask()
782 {
783     if (m_asyncCallStackTracker.isEnabled())
784         m_asyncCallStackTracker.didFireAsyncCall();
785 }
786
787 bool InspectorDebuggerAgent::isPromiseTrackerEnabled()
788 {
789     return m_promiseTracker.isEnabled();
790 }
791
792 void InspectorDebuggerAgent::didCreatePromise(const ScriptObject& promise)
793 {
794     if (m_promiseTracker.isEnabled())
795         m_promiseTracker.didCreatePromise(promise);
796 }
797
798 void InspectorDebuggerAgent::didUpdatePromiseParent(const ScriptObject& promise, const ScriptObject& parentPromise)
799 {
800     if (m_promiseTracker.isEnabled())
801         m_promiseTracker.didUpdatePromiseParent(promise, parentPromise);
802 }
803
804 void InspectorDebuggerAgent::didUpdatePromiseState(const ScriptObject& promise, V8PromiseCustom::PromiseState state, const ScriptValue& result)
805 {
806     if (m_promiseTracker.isEnabled())
807         m_promiseTracker.didUpdatePromiseState(promise, state, result);
808 }
809
810 void InspectorDebuggerAgent::pause(ErrorString*)
811 {
812     if (m_javaScriptPauseScheduled)
813         return;
814     clearBreakDetails();
815     scriptDebugServer().setPauseOnNextStatement(true);
816     m_javaScriptPauseScheduled = true;
817 }
818
819 void InspectorDebuggerAgent::resume(ErrorString* errorString)
820 {
821     if (!assertPaused(errorString))
822         return;
823     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
824     scriptDebugServer().continueProgram();
825 }
826
827 ScriptValue InspectorDebuggerAgent::resolveCallFrame(ErrorString* errorString, const String* callFrameId)
828 {
829     if (!callFrameId)
830         return ScriptValue();
831     if (!isPaused() || m_currentCallStack.isEmpty()) {
832         *errorString = "Attempt to access callframe when debugger is not on pause";
833         return ScriptValue();
834     }
835     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*callFrameId);
836     if (injectedScript.isEmpty()) {
837         *errorString = "Inspected frame has gone";
838         return ScriptValue();
839     }
840     return injectedScript.findCallFrameById(errorString, m_currentCallStack, *callFrameId);
841 }
842
843 void InspectorDebuggerAgent::stepOver(ErrorString* errorString, const String* callFrameId)
844 {
845     if (!assertPaused(errorString))
846         return;
847     ScriptValue frame = resolveCallFrame(errorString, callFrameId);
848     if (!errorString->isEmpty())
849         return;
850     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
851     scriptDebugServer().stepOverStatement(frame);
852 }
853
854 void InspectorDebuggerAgent::stepInto(ErrorString* errorString)
855 {
856     if (!assertPaused(errorString))
857         return;
858     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
859     scriptDebugServer().stepIntoStatement();
860     if (m_listener)
861         m_listener->stepInto();
862 }
863
864 void InspectorDebuggerAgent::stepOut(ErrorString* errorString, const String* callFrameId)
865 {
866     if (!assertPaused(errorString))
867         return;
868     ScriptValue frame = resolveCallFrame(errorString, callFrameId);
869     if (!errorString->isEmpty())
870         return;
871     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
872     scriptDebugServer().stepOutOfFunction(frame);
873 }
874
875 void InspectorDebuggerAgent::setPauseOnExceptions(ErrorString* errorString, const String& stringPauseState)
876 {
877     ScriptDebugServer::PauseOnExceptionsState pauseState;
878     if (stringPauseState == "none")
879         pauseState = ScriptDebugServer::DontPauseOnExceptions;
880     else if (stringPauseState == "all")
881         pauseState = ScriptDebugServer::PauseOnAllExceptions;
882     else if (stringPauseState == "uncaught")
883         pauseState = ScriptDebugServer::PauseOnUncaughtExceptions;
884     else {
885         *errorString = "Unknown pause on exceptions mode: " + stringPauseState;
886         return;
887     }
888     setPauseOnExceptionsImpl(errorString, pauseState);
889 }
890
891 void InspectorDebuggerAgent::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
892 {
893     scriptDebugServer().setPauseOnExceptionsState(static_cast<ScriptDebugServer::PauseOnExceptionsState>(pauseState));
894     if (scriptDebugServer().pauseOnExceptionsState() != pauseState)
895         *errorString = "Internal error. Could not change pause on exceptions state";
896     else
897         m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, pauseState);
898 }
899
900 void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString* errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
901 {
902     if (!isPaused() || m_currentCallStack.isEmpty()) {
903         *errorString = "Attempt to access callframe when debugger is not on pause";
904         return;
905     }
906     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
907     if (injectedScript.isEmpty()) {
908         *errorString = "Inspected frame has gone";
909         return;
910     }
911
912     ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
913     if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
914         if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
915             scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
916         muteConsole();
917     }
918
919     Vector<ScriptValue> asyncCallStacks;
920     const AsyncCallStackTracker::AsyncCallChain* asyncChain = m_asyncCallStackTracker.isEnabled() ? m_asyncCallStackTracker.currentAsyncCallChain() : 0;
921     if (asyncChain) {
922         const AsyncCallStackTracker::AsyncCallStackVector& callStacks = asyncChain->callStacks();
923         asyncCallStacks.resize(callStacks.size());
924         AsyncCallStackTracker::AsyncCallStackVector::const_iterator it = callStacks.begin();
925         for (size_t i = 0; it != callStacks.end(); ++it, ++i)
926             asyncCallStacks[i] = (*it)->callFrames();
927     }
928
929     injectedScript.evaluateOnCallFrame(errorString, m_currentCallStack, asyncCallStacks, callFrameId, expression, objectGroup ? *objectGroup : "", includeCommandLineAPI ? *includeCommandLineAPI : false, returnByValue ? *returnByValue : false, generatePreview ? *generatePreview : false, &result, wasThrown);
930
931     if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
932         unmuteConsole();
933         if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
934             scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
935     }
936 }
937
938 void InspectorDebuggerAgent::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, const int* executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, TypeBuilder::OptOutput<String>* syntaxErrorMessage)
939 {
940     InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
941     if (injectedScript.isEmpty()) {
942         *errorString = "Inspected frame has gone";
943         return;
944     }
945
946     String scriptIdValue;
947     String exceptionMessage;
948     scriptDebugServer().compileScript(injectedScript.scriptState(), expression, sourceURL, &scriptIdValue, &exceptionMessage);
949     if (!scriptIdValue && !exceptionMessage) {
950         *errorString = "Script compilation failed";
951         return;
952     }
953     *syntaxErrorMessage = exceptionMessage;
954     *scriptId = scriptIdValue;
955 }
956
957 void InspectorDebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
958 {
959     InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
960     if (injectedScript.isEmpty()) {
961         *errorString = "Inspected frame has gone";
962         return;
963     }
964
965     ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
966     if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
967         if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
968             scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
969         muteConsole();
970     }
971
972     ScriptValue value;
973     bool wasThrownValue;
974     String exceptionMessage;
975     scriptDebugServer().runScript(injectedScript.scriptState(), scriptId, &value, &wasThrownValue, &exceptionMessage);
976     *wasThrown = wasThrownValue;
977     if (value.isEmpty()) {
978         *errorString = "Script execution failed";
979         return;
980     }
981     result = injectedScript.wrapObject(value, objectGroup ? *objectGroup : "");
982     if (wasThrownValue)
983         result->setDescription(exceptionMessage);
984
985     if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
986         unmuteConsole();
987         if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
988             scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
989     }
990 }
991
992 void InspectorDebuggerAgent::setOverlayMessage(ErrorString*, const String*)
993 {
994 }
995
996 void InspectorDebuggerAgent::setVariableValue(ErrorString* errorString, int scopeNumber, const String& variableName, const RefPtr<JSONObject>& newValue, const String* callFrameId, const String* functionObjectId)
997 {
998     InjectedScript injectedScript;
999     if (callFrameId) {
1000         if (!isPaused() || m_currentCallStack.isEmpty()) {
1001             *errorString = "Attempt to access callframe when debugger is not on pause";
1002             return;
1003         }
1004         injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*callFrameId);
1005         if (injectedScript.isEmpty()) {
1006             *errorString = "Inspected frame has gone";
1007             return;
1008         }
1009     } else if (functionObjectId) {
1010         injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*functionObjectId);
1011         if (injectedScript.isEmpty()) {
1012             *errorString = "Function object id cannot be resolved";
1013             return;
1014         }
1015     } else {
1016         *errorString = "Either call frame or function object must be specified";
1017         return;
1018     }
1019     String newValueString = newValue->toJSONString();
1020
1021     injectedScript.setVariableValue(errorString, m_currentCallStack, callFrameId, functionObjectId, scopeNumber, variableName, newValueString);
1022 }
1023
1024 void InspectorDebuggerAgent::skipStackFrames(ErrorString* errorString, const String* pattern)
1025 {
1026     OwnPtr<ScriptRegexp> compiled;
1027     String patternValue = pattern ? *pattern : "";
1028     if (!patternValue.isEmpty()) {
1029         compiled = compileSkipCallFramePattern(patternValue);
1030         if (!compiled) {
1031             *errorString = "Invalid regular expression";
1032             return;
1033         }
1034     }
1035     m_state->setString(DebuggerAgentState::skipStackPattern, patternValue);
1036     m_cachedSkipStackRegExp = compiled.release();
1037 }
1038
1039 void InspectorDebuggerAgent::setAsyncCallStackDepth(ErrorString*, int depth)
1040 {
1041     m_state->setLong(DebuggerAgentState::asyncCallStackDepth, depth);
1042     m_asyncCallStackTracker.setAsyncCallStackDepth(depth);
1043 }
1044
1045 void InspectorDebuggerAgent::scriptExecutionBlockedByCSP(const String& directiveText)
1046 {
1047     if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions) {
1048         RefPtr<JSONObject> directive = JSONObject::create();
1049         directive->setString("directiveText", directiveText);
1050         breakProgram(InspectorFrontend::Debugger::Reason::CSPViolation, directive.release());
1051     }
1052 }
1053
1054 PassRefPtr<Array<CallFrame> > InspectorDebuggerAgent::currentCallFrames()
1055 {
1056     if (!m_pausedScriptState || m_currentCallStack.isEmpty())
1057         return Array<CallFrame>::create();
1058     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m_pausedScriptState.get());
1059     if (injectedScript.isEmpty()) {
1060         ASSERT_NOT_REACHED();
1061         return Array<CallFrame>::create();
1062     }
1063     return injectedScript.wrapCallFrames(m_currentCallStack, 0);
1064 }
1065
1066 PassRefPtr<StackTrace> InspectorDebuggerAgent::currentAsyncStackTrace()
1067 {
1068     if (!m_pausedScriptState || !m_asyncCallStackTracker.isEnabled())
1069         return nullptr;
1070     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m_pausedScriptState.get());
1071     if (injectedScript.isEmpty()) {
1072         ASSERT_NOT_REACHED();
1073         return nullptr;
1074     }
1075     const AsyncCallStackTracker::AsyncCallChain* chain = m_asyncCallStackTracker.currentAsyncCallChain();
1076     if (!chain)
1077         return nullptr;
1078     const AsyncCallStackTracker::AsyncCallStackVector& callStacks = chain->callStacks();
1079     if (callStacks.isEmpty())
1080         return nullptr;
1081     RefPtr<StackTrace> result;
1082     int asyncOrdinal = callStacks.size();
1083     for (AsyncCallStackTracker::AsyncCallStackVector::const_reverse_iterator it = callStacks.rbegin(); it != callStacks.rend(); ++it) {
1084         RefPtr<StackTrace> next = StackTrace::create()
1085             .setCallFrames(injectedScript.wrapCallFrames((*it)->callFrames(), asyncOrdinal--))
1086             .release();
1087         next->setDescription((*it)->description());
1088         if (result)
1089             next->setAsyncStackTrace(result.release());
1090         result.swap(next);
1091     }
1092     return result.release();
1093 }
1094
1095 String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script)
1096 {
1097     bool deprecated;
1098     String sourceMapURL = ContentSearchUtils::findSourceMapURL(script.source, ContentSearchUtils::JavaScriptMagicComment, &deprecated);
1099     if (!sourceMapURL.isEmpty()) {
1100         // FIXME: add deprecated console message here.
1101         return sourceMapURL;
1102     }
1103
1104     if (script.url.isEmpty())
1105         return String();
1106
1107     InspectorPageAgent* pageAgent = m_instrumentingAgents->inspectorPageAgent();
1108     if (!pageAgent)
1109         return String();
1110     return pageAgent->resourceSourceMapURL(script.url);
1111 }
1112
1113 // JavaScriptDebugListener functions
1114
1115 void InspectorDebuggerAgent::didParseSource(const String& scriptId, const Script& script)
1116 {
1117     // Don't send script content to the front end until it's really needed.
1118     const bool* isContentScript = script.isContentScript ? &script.isContentScript : 0;
1119     String sourceMapURL = sourceMapURLForScript(script);
1120     String* sourceMapURLParam = sourceMapURL.isNull() ? 0 : &sourceMapURL;
1121     String sourceURL;
1122     if (!script.startLine && !script.startColumn) {
1123         bool deprecated;
1124         sourceURL = ContentSearchUtils::findSourceURL(script.source, ContentSearchUtils::JavaScriptMagicComment, &deprecated);
1125         // FIXME: add deprecated console message here.
1126     }
1127     bool hasSourceURL = !sourceURL.isEmpty();
1128     String scriptURL = hasSourceURL ? sourceURL : script.url;
1129     bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : 0;
1130     m_frontend->scriptParsed(scriptId, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam);
1131
1132     m_scripts.set(scriptId, script);
1133
1134     if (scriptURL.isEmpty())
1135         return;
1136
1137     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
1138     for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
1139         RefPtr<JSONObject> breakpointObject = it->value->asObject();
1140         bool isAntibreakpoint;
1141         breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
1142         if (isAntibreakpoint)
1143             continue;
1144         bool isRegex;
1145         breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
1146         String url;
1147         breakpointObject->getString(DebuggerAgentState::url, &url);
1148         if (!matches(scriptURL, url, isRegex))
1149             continue;
1150         ScriptBreakpoint breakpoint;
1151         breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakpoint.lineNumber);
1152         breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakpoint.columnNumber);
1153         breakpointObject->getString(DebuggerAgentState::condition, &breakpoint.condition);
1154         RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it->key, scriptId, breakpoint, UserBreakpointSource);
1155         if (location)
1156             m_frontend->breakpointResolved(it->key, location);
1157     }
1158 }
1159
1160 void InspectorDebuggerAgent::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage)
1161 {
1162     m_frontend->scriptFailedToParse(url, data, firstLine, errorLine, errorMessage);
1163 }
1164
1165 void InspectorDebuggerAgent::didPause(ScriptState* scriptState, const ScriptValue& callFrames, const ScriptValue& exception, const Vector<String>& hitBreakpoints)
1166 {
1167     ASSERT(scriptState && !m_pausedScriptState);
1168     m_pausedScriptState = scriptState;
1169     m_currentCallStack = callFrames;
1170
1171     m_skipStepInCount = numberOfStepsBeforeStepOut;
1172
1173     if (!exception.isEmpty()) {
1174         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
1175         if (!injectedScript.isEmpty()) {
1176             m_breakReason = InspectorFrontend::Debugger::Reason::Exception;
1177             m_breakAuxData = injectedScript.wrapObject(exception, InspectorDebuggerAgent::backtraceObjectGroup)->openAccessors();
1178             // m_breakAuxData might be null after this.
1179         }
1180     }
1181
1182     RefPtr<Array<String> > hitBreakpointIds = Array<String>::create();
1183
1184     for (Vector<String>::const_iterator i = hitBreakpoints.begin(); i != hitBreakpoints.end(); ++i) {
1185         DebugServerBreakpointToBreakpointIdAndSourceMap::iterator breakpointIterator = m_serverBreakpoints.find(*i);
1186         if (breakpointIterator != m_serverBreakpoints.end()) {
1187             const String& localId = breakpointIterator->value.first;
1188             hitBreakpointIds->addItem(localId);
1189
1190             BreakpointSource source = breakpointIterator->value.second;
1191             if (m_breakReason == InspectorFrontend::Debugger::Reason::Other && source == DebugCommandBreakpointSource)
1192                 m_breakReason = InspectorFrontend::Debugger::Reason::DebugCommand;
1193         }
1194     }
1195
1196     m_frontend->paused(currentCallFrames(), m_breakReason, m_breakAuxData, hitBreakpointIds, currentAsyncStackTrace());
1197     m_javaScriptPauseScheduled = false;
1198
1199     if (!m_continueToLocationBreakpointId.isEmpty()) {
1200         scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
1201         m_continueToLocationBreakpointId = "";
1202     }
1203     if (m_listener)
1204         m_listener->didPause();
1205 }
1206
1207 void InspectorDebuggerAgent::didContinue()
1208 {
1209     m_pausedScriptState = nullptr;
1210     m_currentCallStack = ScriptValue();
1211     clearBreakDetails();
1212     m_frontend->resumed();
1213 }
1214
1215 bool InspectorDebuggerAgent::canBreakProgram()
1216 {
1217     return scriptDebugServer().canBreakProgram();
1218 }
1219
1220 void InspectorDebuggerAgent::breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
1221 {
1222     if (m_skipAllPauses)
1223         return;
1224     m_breakReason = breakReason;
1225     m_breakAuxData = data;
1226     scriptDebugServer().breakProgram();
1227 }
1228
1229 void InspectorDebuggerAgent::clear()
1230 {
1231     m_pausedScriptState = nullptr;
1232     m_currentCallStack = ScriptValue();
1233     m_scripts.clear();
1234     m_breakpointIdToDebugServerBreakpointIds.clear();
1235     m_asyncCallStackTracker.clear();
1236     m_promiseTracker.clear();
1237     m_continueToLocationBreakpointId = String();
1238     clearBreakDetails();
1239     m_javaScriptPauseScheduled = false;
1240     ErrorString error;
1241     setOverlayMessage(&error, 0);
1242 }
1243
1244 bool InspectorDebuggerAgent::assertPaused(ErrorString* errorString)
1245 {
1246     if (!m_pausedScriptState) {
1247         *errorString = "Can only perform operation while paused.";
1248         return false;
1249     }
1250     return true;
1251 }
1252
1253 void InspectorDebuggerAgent::clearBreakDetails()
1254 {
1255     m_breakReason = InspectorFrontend::Debugger::Reason::Other;
1256     m_breakAuxData = nullptr;
1257 }
1258
1259 void InspectorDebuggerAgent::setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source, const String& condition)
1260 {
1261     String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, source);
1262     ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
1263     resolveBreakpoint(breakpointId, scriptId, breakpoint, source);
1264 }
1265
1266 void InspectorDebuggerAgent::removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source)
1267 {
1268     removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, source));
1269 }
1270
1271 void InspectorDebuggerAgent::reset()
1272 {
1273     m_scripts.clear();
1274     m_breakpointIdToDebugServerBreakpointIds.clear();
1275     m_asyncCallStackTracker.clear();
1276     m_promiseTracker.clear();
1277     if (m_frontend)
1278         m_frontend->globalObjectCleared();
1279 }
1280
1281 } // namespace WebCore
1282