tizen beta release
[profile/ivi/webkit-efl.git] / Source / WebCore / inspector / InspectorDebuggerAgent.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010-2011 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 "InspectorDebuggerAgent.h"
32
33 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
34 #include "ContentSearchUtils.h"
35 #include "InjectedScript.h"
36 #include "InjectedScriptManager.h"
37 #include "InspectorFrontend.h"
38 #include "InspectorState.h"
39 #include "InspectorValues.h"
40 #include "InstrumentingAgents.h"
41 #include "RegularExpression.h"
42 #include "ScriptDebugServer.h"
43 #include "ScriptObject.h"
44 #include <wtf/text/WTFString.h>
45
46 namespace WebCore {
47
48 namespace DebuggerAgentState {
49 static const char debuggerEnabled[] = "debuggerEnabled";
50 static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
51 };
52
53 const char* InspectorDebuggerAgent::backtraceObjectGroup = "backtrace-object-group";
54
55 InspectorDebuggerAgent::InspectorDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, InjectedScriptManager* injectedScriptManager)
56     : InspectorBaseAgent<InspectorDebuggerAgent>("Debugger", instrumentingAgents, inspectorState)
57     , m_injectedScriptManager(injectedScriptManager)
58     , m_frontend(0)
59     , m_pausedScriptState(0)
60     , m_javaScriptPauseScheduled(false)
61     , m_listener(0)
62 {
63     // FIXME: make breakReason optional so that there was no need to init it with "other".
64     clearBreakDetails();
65 }
66
67 InspectorDebuggerAgent::~InspectorDebuggerAgent()
68 {
69     ASSERT(!m_instrumentingAgents->inspectorDebuggerAgent());
70 }
71
72 void InspectorDebuggerAgent::enable()
73 {
74     m_instrumentingAgents->setInspectorDebuggerAgent(this);
75
76     // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
77     scriptDebugServer().setBreakpointsActivated(true);
78     startListeningScriptDebugServer();
79
80     if (m_listener)
81         m_listener->debuggerWasEnabled();
82 }
83
84 void InspectorDebuggerAgent::disable()
85 {
86     m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, InspectorObject::create());
87     m_instrumentingAgents->setInspectorDebuggerAgent(0);
88
89     stopListeningScriptDebugServer();
90     scriptDebugServer().clearBreakpoints();
91     clear();
92
93     if (m_listener)
94         m_listener->debuggerWasDisabled();
95 }
96
97 bool InspectorDebuggerAgent::enabled()
98 {
99     return m_state->getBoolean(DebuggerAgentState::debuggerEnabled);
100 }
101
102 void InspectorDebuggerAgent::getAgentCapabilities(InspectorArray* capabilities)
103 {
104     if (scriptDebugServer().canSetScriptSource())
105         capabilities->pushString(InspectorFrontend::Debugger::capabilitySetScriptSource);
106 }
107
108 void InspectorDebuggerAgent::enable(ErrorString*)
109 {
110     if (enabled())
111         return;
112
113     enable();
114     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
115
116     ASSERT(m_frontend);
117 }
118
119 void InspectorDebuggerAgent::disable(ErrorString*)
120 {
121     if (!enabled())
122         return;
123
124     disable();
125     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
126 }
127
128 void InspectorDebuggerAgent::restore()
129 {
130     if (enabled()) {
131         m_frontend->globalObjectCleared();
132         enable();
133     }
134 }
135
136 void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
137 {
138     m_frontend = frontend->debugger();
139 }
140
141 void InspectorDebuggerAgent::clearFrontend()
142 {
143     m_frontend = 0;
144
145     if (!enabled())
146         return;
147
148     disable();
149
150     // FIXME: due to m_state->mute() hack in InspectorController, debuggerEnabled is actually set to false only
151     // in InspectorState, but not in cookie. That's why after navigation debuggerEnabled will be true,
152     // but after front-end re-open it will still be false.
153     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
154 }
155
156 void InspectorDebuggerAgent::setBreakpointsActive(ErrorString*, bool active)
157 {
158     if (active)
159         scriptDebugServer().activateBreakpoints();
160     else
161         scriptDebugServer().deactivateBreakpoints();
162 }
163
164 void InspectorDebuggerAgent::didClearMainFrameWindowObject()
165 {
166     m_scripts.clear();
167     m_breakpointIdToDebugServerBreakpointIds.clear();
168     if (m_frontend)
169         m_frontend->globalObjectCleared();
170 }
171
172 static PassRefPtr<InspectorObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex)
173 {
174     RefPtr<InspectorObject> breakpointObject = InspectorObject::create();
175     breakpointObject->setString("url", url);
176     breakpointObject->setNumber("lineNumber", lineNumber);
177     breakpointObject->setNumber("columnNumber", columnNumber);
178     breakpointObject->setString("condition", condition);
179     breakpointObject->setBoolean("isRegex", isRegex);
180     return breakpointObject;
181 }
182
183 static bool matches(const String& url, const String& pattern, bool isRegex)
184 {
185     if (isRegex) {
186         RegularExpression regex(pattern, TextCaseSensitive);
187         return regex.match(url) != -1;
188     }
189     return url == pattern;
190 }
191
192 void InspectorDebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int lineNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const String* const optionalCondition, String* outBreakpointId, RefPtr<InspectorArray>* locations)
193 {
194     if (!optionalURL == !optionalURLRegex) {
195         *errorString = "Either url or urlRegex must be specified.";
196         return;
197     }
198
199     String url = optionalURL ? *optionalURL : *optionalURLRegex;
200     int columnNumber = optionalColumnNumber ? *optionalColumnNumber : 0;
201     String condition = optionalCondition ? *optionalCondition : "";
202     bool isRegex = optionalURLRegex;
203
204     String breakpointId = (isRegex ? "/" + url + "/" : url) + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
205     RefPtr<InspectorObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
206     if (breakpointsCookie->find(breakpointId) != breakpointsCookie->end()) {
207         *errorString = "Breakpoint at specified location already exists.";
208         return;
209     }
210
211     breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex));
212     m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
213
214     ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
215     for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
216         if (!matches(it->second.url, url, isRegex))
217             continue;
218         RefPtr<InspectorObject> location = resolveBreakpoint(breakpointId, it->first, breakpoint);
219         if (location)
220             (*locations)->pushObject(location);
221     }
222     *outBreakpointId = breakpointId;
223 }
224
225 static bool parseLocation(ErrorString* errorString, RefPtr<InspectorObject> location, String* scriptId, int* lineNumber, int* columnNumber)
226 {
227     if (!location->getString("scriptId", scriptId) || !location->getNumber("lineNumber", lineNumber)) {
228         // FIXME: replace with input validation.
229         *errorString = "scriptId and lineNumber are required.";
230         return false;
231     }
232     *columnNumber = 0;
233     location->getNumber("columnNumber", columnNumber);
234     return true;
235 }
236
237 void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, PassRefPtr<InspectorObject> location, const String* const optionalCondition, String* outBreakpointId, RefPtr<InspectorObject>* actualLocation)
238 {
239     String scriptId;
240     int lineNumber;
241     int columnNumber;
242
243     if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
244         return;
245
246     String condition = optionalCondition ? *optionalCondition : emptyString();
247
248     String breakpointId = scriptId + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
249     if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpointIdToDebugServerBreakpointIds.end())
250         return;
251     ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
252     *actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint);
253     if (*actualLocation)
254         *outBreakpointId = breakpointId;
255     else
256         *errorString = "Could not resolve breakpoint";
257 }
258
259 void InspectorDebuggerAgent::removeBreakpoint(ErrorString*, const String& breakpointId)
260 {
261     RefPtr<InspectorObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
262     breakpointsCookie->remove(breakpointId);
263     m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
264
265     BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
266     if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
267         return;
268     for (size_t i = 0; i < debugServerBreakpointIdsIterator->second.size(); ++i)
269         scriptDebugServer().removeBreakpoint(debugServerBreakpointIdsIterator->second[i]);
270     m_breakpointIdToDebugServerBreakpointIds.remove(debugServerBreakpointIdsIterator);
271 }
272
273 void InspectorDebuggerAgent::continueToLocation(ErrorString* errorString, PassRefPtr<InspectorObject> location)
274 {
275     if (!m_continueToLocationBreakpointId.isEmpty()) {
276         scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
277         m_continueToLocationBreakpointId = "";
278     }
279
280     String scriptId;
281     int lineNumber;
282     int columnNumber;
283
284     if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
285         return;
286
287     ScriptBreakpoint breakpoint(lineNumber, columnNumber, "");
288     m_continueToLocationBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &lineNumber, &columnNumber);
289     resume(errorString);
290 }
291
292 PassRefPtr<InspectorObject> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint)
293 {
294     ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
295     if (scriptIterator == m_scripts.end())
296         return 0;
297     Script& script = scriptIterator->second;
298     if (breakpoint.lineNumber < script.startLine || script.endLine < breakpoint.lineNumber)
299         return 0;
300
301     int actualLineNumber;
302     int actualColumnNumber;
303     String debugServerBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber);
304     if (debugServerBreakpointId.isEmpty())
305         return 0;
306
307     BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
308     if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
309         debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.set(breakpointId, Vector<String>()).first;
310     debugServerBreakpointIdsIterator->second.append(debugServerBreakpointId);
311
312     RefPtr<InspectorObject> location = InspectorObject::create();
313     location->setString("scriptId", scriptId);
314     location->setNumber("lineNumber", actualLineNumber);
315     location->setNumber("columnNumber", actualColumnNumber);
316     return location;
317 }
318
319 static PassRefPtr<InspectorObject> scriptToInspectorObject(ScriptObject scriptObject)
320 {
321     if (scriptObject.hasNoValue())
322         return 0;
323     RefPtr<InspectorValue> value = scriptObject.toInspectorValue(scriptObject.scriptState());
324     if (!value)
325         return 0;
326     return value->asObject();
327 }
328
329 void InspectorDebuggerAgent::searchInContent(ErrorString* error, const String& scriptId, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<InspectorArray>* results)
330 {
331     bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
332     bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
333
334     ScriptsMap::iterator it = m_scripts.find(scriptId);
335     if (it != m_scripts.end())
336         *results = ContentSearchUtils::searchInTextByLines(it->second.source, query, caseSensitive, isRegex);
337     else
338         *error = "No script for id: " + scriptId;
339 }
340
341 void InspectorDebuggerAgent::setScriptSource(ErrorString* error, const String& scriptId, const String& newContent, const bool* const preview, RefPtr<InspectorArray>* newCallFrames, RefPtr<InspectorObject>* result)
342 {
343     bool previewOnly = preview && *preview;
344     ScriptObject resultObject;
345     if (!scriptDebugServer().setScriptSource(scriptId, newContent, previewOnly, error, &m_currentCallStack, &resultObject))
346         return;
347     *newCallFrames = currentCallFrames();
348     RefPtr<InspectorObject> object = scriptToInspectorObject(resultObject);
349     if (object)
350         *result = object;
351 }
352
353 void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& scriptId, String* scriptSource)
354 {
355     ScriptsMap::iterator it = m_scripts.find(scriptId);
356     if (it != m_scripts.end())
357         *scriptSource = it->second.source;
358     else
359         *error = "No script for id: " + scriptId;
360 }
361
362 void InspectorDebuggerAgent::getFunctionLocation(ErrorString* errorString, const String& functionId, RefPtr<InspectorObject>* location)
363 {
364     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(functionId);
365     if (injectedScript.hasNoValue()) {
366         *errorString = "Inspected frame has gone";
367         return;
368     }
369     injectedScript.getFunctionLocation(errorString, functionId, location);
370 }
371
372 void InspectorDebuggerAgent::schedulePauseOnNextStatement(const String& breakReason, PassRefPtr<InspectorObject> data)
373 {
374     if (m_javaScriptPauseScheduled)
375         return;
376     m_breakReason = breakReason;
377     m_breakAuxData = data;
378     scriptDebugServer().setPauseOnNextStatement(true);
379 }
380
381 void InspectorDebuggerAgent::cancelPauseOnNextStatement()
382 {
383     if (m_javaScriptPauseScheduled)
384         return;
385     clearBreakDetails();
386     scriptDebugServer().setPauseOnNextStatement(false);
387 }
388
389 void InspectorDebuggerAgent::pause(ErrorString*)
390 {
391     if (m_javaScriptPauseScheduled)
392         return;
393     clearBreakDetails();
394     scriptDebugServer().setPauseOnNextStatement(true);
395     m_javaScriptPauseScheduled = true;
396 }
397
398 void InspectorDebuggerAgent::resume(ErrorString* errorString)
399 {
400     if (!assertPaused(errorString))
401         return;
402     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
403     scriptDebugServer().continueProgram();
404 }
405
406 void InspectorDebuggerAgent::stepOver(ErrorString* errorString)
407 {
408     if (!assertPaused(errorString))
409         return;
410     scriptDebugServer().stepOverStatement();
411 }
412
413 void InspectorDebuggerAgent::stepInto(ErrorString* errorString)
414 {
415     if (!assertPaused(errorString))
416         return;
417     scriptDebugServer().stepIntoStatement();
418 }
419
420 void InspectorDebuggerAgent::stepOut(ErrorString* errorString)
421 {
422     if (!assertPaused(errorString))
423         return;
424     scriptDebugServer().stepOutOfFunction();
425 }
426
427 void InspectorDebuggerAgent::setPauseOnExceptions(ErrorString* errorString, const String& stringPauseState)
428 {
429     ScriptDebugServer::PauseOnExceptionsState pauseState;
430     if (stringPauseState == "none")
431         pauseState = ScriptDebugServer::DontPauseOnExceptions;
432     else if (stringPauseState == "all")
433         pauseState = ScriptDebugServer::PauseOnAllExceptions;
434     else if (stringPauseState == "uncaught")
435         pauseState = ScriptDebugServer::PauseOnUncaughtExceptions;
436     else {
437         *errorString = "Unknown pause on exceptions mode: " + stringPauseState;
438         return;
439     }
440     scriptDebugServer().setPauseOnExceptionsState(static_cast<ScriptDebugServer::PauseOnExceptionsState>(pauseState));
441     if (scriptDebugServer().pauseOnExceptionsState() != pauseState)
442         *errorString = "Internal error. Could not change pause on exceptions state";
443 }
444
445 void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString* errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const returnByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
446 {
447     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
448     if (injectedScript.hasNoValue()) {
449         *errorString = "Inspected frame has gone";
450         return;
451     }
452     injectedScript.evaluateOnCallFrame(errorString, m_currentCallStack, callFrameId, expression, objectGroup ? *objectGroup : "", includeCommandLineAPI ? *includeCommandLineAPI : false, returnByValue ? *returnByValue : false, result, wasThrown);
453 }
454
455 PassRefPtr<InspectorArray> InspectorDebuggerAgent::currentCallFrames()
456 {
457     if (!m_pausedScriptState)
458         return InspectorArray::create();
459     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m_pausedScriptState);
460     if (injectedScript.hasNoValue()) {
461         ASSERT_NOT_REACHED();
462         return InspectorArray::create();
463     }
464     return injectedScript.wrapCallFrames(m_currentCallStack);
465 }
466
467 // JavaScriptDebugListener functions
468
469 void InspectorDebuggerAgent::didParseSource(const String& scriptId, const Script& script)
470 {
471     // Don't send script content to the front end until it's really needed.
472     m_frontend->scriptParsed(scriptId, script.url, script.startLine, script.startColumn, script.endLine, script.endColumn, script.isContentScript ? &script.isContentScript : 0);
473
474     m_scripts.set(scriptId, script);
475
476     if (script.url.isEmpty())
477         return;
478
479     RefPtr<InspectorObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
480     for (InspectorObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
481         RefPtr<InspectorObject> breakpointObject = it->second->asObject();
482         bool isRegex;
483         breakpointObject->getBoolean("isRegex", &isRegex);
484         String url;
485         breakpointObject->getString("url", &url);
486         if (!matches(script.url, url, isRegex))
487             continue;
488         ScriptBreakpoint breakpoint;
489         breakpointObject->getNumber("lineNumber", &breakpoint.lineNumber);
490         breakpointObject->getNumber("columnNumber", &breakpoint.columnNumber);
491         breakpointObject->getString("condition", &breakpoint.condition);
492         RefPtr<InspectorObject> location = resolveBreakpoint(it->first, scriptId, breakpoint);
493         if (location)
494             m_frontend->breakpointResolved(it->first, location);
495     }
496 }
497
498 void InspectorDebuggerAgent::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage)
499 {
500     m_frontend->scriptFailedToParse(url, data, firstLine, errorLine, errorMessage);
501 }
502
503 void InspectorDebuggerAgent::didPause(ScriptState* scriptState, const ScriptValue& callFrames, const ScriptValue& exception)
504 {
505     ASSERT(scriptState && !m_pausedScriptState);
506     m_pausedScriptState = scriptState;
507     m_currentCallStack = callFrames;
508
509     if (!exception.hasNoValue()) {
510         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
511         if (!injectedScript.hasNoValue()) {
512             m_breakReason = "exception";
513             m_breakAuxData = injectedScript.wrapObject(exception, "backtrace");
514         }
515     }
516
517     m_frontend->paused(currentCallFrames(), m_breakReason, m_breakAuxData);
518     m_javaScriptPauseScheduled = false;
519
520     if (!m_continueToLocationBreakpointId.isEmpty()) {
521         scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
522         m_continueToLocationBreakpointId = "";
523     }
524 }
525
526 void InspectorDebuggerAgent::didContinue()
527 {
528     m_pausedScriptState = 0;
529     m_currentCallStack = ScriptValue();
530     clearBreakDetails();
531     m_frontend->resumed();
532 }
533
534 void InspectorDebuggerAgent::breakProgram(const String& breakReason, PassRefPtr<InspectorObject> data)
535 {
536     m_breakReason = breakReason;
537     m_breakAuxData = data;
538     scriptDebugServer().breakProgram();
539 }
540
541 void InspectorDebuggerAgent::clear()
542 {
543     m_pausedScriptState = 0;
544     m_currentCallStack = ScriptValue();
545     m_scripts.clear();
546     m_breakpointIdToDebugServerBreakpointIds.clear();
547     m_continueToLocationBreakpointId = String();
548     clearBreakDetails();
549     m_javaScriptPauseScheduled = false;
550 }
551
552 bool InspectorDebuggerAgent::assertPaused(ErrorString* errorString)
553 {
554     if (!m_pausedScriptState) {
555         *errorString = "Can only perform operation while paused.";
556         return false;
557     }
558     return true;
559 }
560
561 void InspectorDebuggerAgent::clearBreakDetails()
562 {
563     m_breakReason = "other";
564     m_breakAuxData = 0;
565 }
566
567 } // namespace WebCore
568
569 #endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)