Home | History | Annotate | Download | only in inspector
      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 "core/inspector/InspectorDebuggerAgent.h"
     32 #include "core/inspector/JavaScriptCallFrame.h"
     33 
     34 #include "InspectorFrontend.h"
     35 #include "bindings/v8/ScriptDebugServer.h"
     36 #include "bindings/v8/ScriptObject.h"
     37 #include "core/inspector/ContentSearchUtils.h"
     38 #include "core/inspector/InjectedScript.h"
     39 #include "core/inspector/InjectedScriptManager.h"
     40 #include "core/inspector/InspectorPageAgent.h"
     41 #include "core/inspector/InspectorState.h"
     42 #include "core/inspector/InstrumentingAgents.h"
     43 #include "core/inspector/ScriptArguments.h"
     44 #include "core/inspector/ScriptCallStack.h"
     45 #include "core/loader/cache/Resource.h"
     46 #include "core/platform/JSONValues.h"
     47 #include "core/platform/text/RegularExpression.h"
     48 #include "wtf/text/WTFString.h"
     49 
     50 using WebCore::TypeBuilder::Array;
     51 using WebCore::TypeBuilder::Debugger::FunctionDetails;
     52 using WebCore::TypeBuilder::Debugger::ScriptId;
     53 using WebCore::TypeBuilder::Runtime::RemoteObject;
     54 
     55 namespace WebCore {
     56 
     57 namespace DebuggerAgentState {
     58 static const char debuggerEnabled[] = "debuggerEnabled";
     59 static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
     60 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState";
     61 
     62 // Breakpoint properties.
     63 static const char url[] = "url";
     64 static const char isRegex[] = "isRegex";
     65 static const char lineNumber[] = "lineNumber";
     66 static const char columnNumber[] = "columnNumber";
     67 static const char condition[] = "condition";
     68 static const char isAnti[] = "isAnti";
     69 static const char skipStackPattern[] = "skipStackPattern";
     70 };
     71 
     72 static const int numberOfStepsBeforeStepOut = 10;
     73 
     74 const char* InspectorDebuggerAgent::backtraceObjectGroup = "backtrace";
     75 
     76 static String breakpointIdSuffix(InspectorDebuggerAgent::BreakpointSource source)
     77 {
     78     switch (source) {
     79     case InspectorDebuggerAgent::UserBreakpointSource:
     80         break;
     81     case InspectorDebuggerAgent::DebugCommandBreakpointSource:
     82         return ":debug";
     83     case InspectorDebuggerAgent::MonitorCommandBreakpointSource:
     84         return ":monitor";
     85     }
     86     return String();
     87 }
     88 
     89 static String generateBreakpointId(const String& scriptId, int lineNumber, int columnNumber, InspectorDebuggerAgent::BreakpointSource source)
     90 {
     91     return scriptId + ':' + String::number(lineNumber) + ':' + String::number(columnNumber) + breakpointIdSuffix(source);
     92 }
     93 
     94 InspectorDebuggerAgent::InspectorDebuggerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
     95     : InspectorBaseAgent<InspectorDebuggerAgent>("Debugger", instrumentingAgents, inspectorState)
     96     , m_injectedScriptManager(injectedScriptManager)
     97     , m_frontend(0)
     98     , m_pausedScriptState(0)
     99     , m_javaScriptPauseScheduled(false)
    100     , m_listener(0)
    101     , m_skipStepInCount(numberOfStepsBeforeStepOut)
    102 {
    103     // FIXME: make breakReason optional so that there was no need to init it with "other".
    104     clearBreakDetails();
    105     m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
    106 }
    107 
    108 InspectorDebuggerAgent::~InspectorDebuggerAgent()
    109 {
    110     ASSERT(!m_instrumentingAgents->inspectorDebuggerAgent());
    111 }
    112 
    113 void InspectorDebuggerAgent::enable()
    114 {
    115     m_instrumentingAgents->setInspectorDebuggerAgent(this);
    116 
    117     // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
    118     scriptDebugServer().setBreakpointsActivated(true);
    119     startListeningScriptDebugServer();
    120 
    121     if (m_listener)
    122         m_listener->debuggerWasEnabled();
    123 }
    124 
    125 void InspectorDebuggerAgent::disable()
    126 {
    127     m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, JSONObject::create());
    128     m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
    129     m_state->setString(DebuggerAgentState::skipStackPattern, "");
    130     m_instrumentingAgents->setInspectorDebuggerAgent(0);
    131 
    132     stopListeningScriptDebugServer();
    133     scriptDebugServer().clearBreakpoints();
    134     scriptDebugServer().clearCompiledScripts();
    135     clear();
    136 
    137     if (m_listener)
    138         m_listener->debuggerWasDisabled();
    139 }
    140 
    141 bool InspectorDebuggerAgent::enabled()
    142 {
    143     return m_state->getBoolean(DebuggerAgentState::debuggerEnabled);
    144 }
    145 
    146 void InspectorDebuggerAgent::enable(ErrorString*)
    147 {
    148     if (enabled())
    149         return;
    150 
    151     enable();
    152     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
    153 
    154     ASSERT(m_frontend);
    155 }
    156 
    157 void InspectorDebuggerAgent::disable(ErrorString*)
    158 {
    159     if (!enabled())
    160         return;
    161 
    162     disable();
    163     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
    164 }
    165 
    166 static PassOwnPtr<RegularExpression> compileSkipCallFramePattern(String patternText)
    167 {
    168     if (patternText.isEmpty())
    169         return nullptr;
    170     OwnPtr<RegularExpression> result = adoptPtr(new RegularExpression(patternText, TextCaseSensitive));
    171     if (!result->isValid())
    172         result.clear();
    173     return result.release();
    174 }
    175 
    176 void InspectorDebuggerAgent::restore()
    177 {
    178     if (enabled()) {
    179         m_frontend->globalObjectCleared();
    180         enable();
    181         long pauseState = m_state->getLong(DebuggerAgentState::pauseOnExceptionsState);
    182         String error;
    183         setPauseOnExceptionsImpl(&error, pauseState);
    184         m_cachedSkipStackRegExp = compileSkipCallFramePattern(m_state->getString(DebuggerAgentState::skipStackPattern));
    185     }
    186 }
    187 
    188 void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
    189 {
    190     m_frontend = frontend->debugger();
    191 }
    192 
    193 void InspectorDebuggerAgent::clearFrontend()
    194 {
    195     m_frontend = 0;
    196 
    197     if (!enabled())
    198         return;
    199 
    200     disable();
    201 
    202     // FIXME: due to m_state->mute() hack in InspectorController, debuggerEnabled is actually set to false only
    203     // in InspectorState, but not in cookie. That's why after navigation debuggerEnabled will be true,
    204     // but after front-end re-open it will still be false.
    205     m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
    206 }
    207 
    208 void InspectorDebuggerAgent::setBreakpointsActive(ErrorString*, bool active)
    209 {
    210     scriptDebugServer().setBreakpointsActivated(active);
    211 }
    212 
    213 bool InspectorDebuggerAgent::isPaused()
    214 {
    215     return scriptDebugServer().isPaused();
    216 }
    217 
    218 bool InspectorDebuggerAgent::runningNestedMessageLoop()
    219 {
    220     return scriptDebugServer().runningNestedMessageLoop();
    221 }
    222 
    223 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type)
    224 {
    225     if (source == ConsoleAPIMessageSource && type == AssertMessageType && scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions)
    226         breakProgram(InspectorFrontend::Debugger::Reason::Assert, 0);
    227 }
    228 
    229 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel, const String&, PassRefPtr<ScriptCallStack>, unsigned long)
    230 {
    231     addMessageToConsole(source, type);
    232 }
    233 
    234 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel, const String&, ScriptState*, PassRefPtr<ScriptArguments>, unsigned long)
    235 {
    236     addMessageToConsole(source, type);
    237 }
    238 
    239 
    240 static PassRefPtr<JSONObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex, bool isAnti)
    241 {
    242     RefPtr<JSONObject> breakpointObject = JSONObject::create();
    243     breakpointObject->setString(DebuggerAgentState::url, url);
    244     breakpointObject->setNumber(DebuggerAgentState::lineNumber, lineNumber);
    245     breakpointObject->setNumber(DebuggerAgentState::columnNumber, columnNumber);
    246     breakpointObject->setString(DebuggerAgentState::condition, condition);
    247     breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex);
    248     breakpointObject->setBoolean(DebuggerAgentState::isAnti, isAnti);
    249     return breakpointObject;
    250 }
    251 
    252 static bool matches(const String& url, const String& pattern, bool isRegex)
    253 {
    254     if (isRegex) {
    255         RegularExpression regex(pattern, TextCaseSensitive);
    256         return regex.match(url) != -1;
    257     }
    258     return url == pattern;
    259 }
    260 
    261 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, TypeBuilder::Debugger::BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location> >& locations)
    262 {
    263     locations = Array<TypeBuilder::Debugger::Location>::create();
    264     if (!optionalURL == !optionalURLRegex) {
    265         *errorString = "Either url or urlRegex must be specified.";
    266         return;
    267     }
    268 
    269     bool isAntiBreakpointValue = isAntiBreakpoint && *isAntiBreakpoint;
    270 
    271     String url = optionalURL ? *optionalURL : *optionalURLRegex;
    272     int columnNumber;
    273     if (optionalColumnNumber) {
    274         columnNumber = *optionalColumnNumber;
    275         if (columnNumber < 0) {
    276             *errorString = "Incorrect column number";
    277             return;
    278         }
    279     } else {
    280         columnNumber = isAntiBreakpointValue ? -1 : 0;
    281     }
    282     String condition = optionalCondition ? *optionalCondition : "";
    283     bool isRegex = optionalURLRegex;
    284 
    285     String breakpointId = (isRegex ? "/" + url + "/" : url) + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
    286     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
    287     if (breakpointsCookie->find(breakpointId) != breakpointsCookie->end()) {
    288         *errorString = "Breakpoint at specified location already exists.";
    289         return;
    290     }
    291 
    292     breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex, isAntiBreakpointValue));
    293     m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
    294 
    295     if (!isAntiBreakpointValue) {
    296         ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
    297         for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
    298             if (!matches(it->value.url, url, isRegex))
    299                 continue;
    300             RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(breakpointId, it->key, breakpoint, UserBreakpointSource);
    301             if (location)
    302                 locations->addItem(location);
    303         }
    304     }
    305     *outBreakpointId = breakpointId;
    306 }
    307 
    308 static bool parseLocation(ErrorString* errorString, PassRefPtr<JSONObject> location, String* scriptId, int* lineNumber, int* columnNumber)
    309 {
    310     if (!location->getString("scriptId", scriptId) || !location->getNumber("lineNumber", lineNumber)) {
    311         // FIXME: replace with input validation.
    312         *errorString = "scriptId and lineNumber are required.";
    313         return false;
    314     }
    315     *columnNumber = 0;
    316     location->getNumber("columnNumber", columnNumber);
    317     return true;
    318 }
    319 
    320 void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPtr<JSONObject>& location, const String* const optionalCondition, TypeBuilder::Debugger::BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
    321 {
    322     String scriptId;
    323     int lineNumber;
    324     int columnNumber;
    325 
    326     if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
    327         return;
    328 
    329     String condition = optionalCondition ? *optionalCondition : emptyString();
    330 
    331     String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, UserBreakpointSource);
    332     if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpointIdToDebugServerBreakpointIds.end()) {
    333         *errorString = "Breakpoint at specified location already exists.";
    334         return;
    335     }
    336     ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
    337     actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, UserBreakpointSource);
    338     if (actualLocation)
    339         *outBreakpointId = breakpointId;
    340     else
    341         *errorString = "Could not resolve breakpoint";
    342 }
    343 
    344 void InspectorDebuggerAgent::removeBreakpoint(ErrorString*, const String& breakpointId)
    345 {
    346     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
    347     JSONObject::iterator it = breakpointsCookie->find(breakpointId);
    348     bool isAntibreakpoint = false;
    349     if (it != breakpointsCookie->end()) {
    350         RefPtr<JSONObject> breakpointObject = it->value->asObject();
    351         breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
    352         breakpointsCookie->remove(breakpointId);
    353         m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
    354     }
    355 
    356     if (!isAntibreakpoint)
    357         removeBreakpoint(breakpointId);
    358 }
    359 
    360 void InspectorDebuggerAgent::removeBreakpoint(const String& breakpointId)
    361 {
    362     BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
    363     if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
    364         return;
    365     for (size_t i = 0; i < debugServerBreakpointIdsIterator->value.size(); ++i) {
    366         const String& debugServerBreakpointId = debugServerBreakpointIdsIterator->value[i];
    367         scriptDebugServer().removeBreakpoint(debugServerBreakpointId);
    368         m_serverBreakpoints.remove(debugServerBreakpointId);
    369     }
    370     m_breakpointIdToDebugServerBreakpointIds.remove(debugServerBreakpointIdsIterator);
    371 }
    372 
    373 void InspectorDebuggerAgent::continueToLocation(ErrorString* errorString, const RefPtr<JSONObject>& location, const bool* interstateLocationOpt)
    374 {
    375     bool interstateLocation = interstateLocationOpt ? *interstateLocationOpt : false;
    376     if (!m_continueToLocationBreakpointId.isEmpty()) {
    377         scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
    378         m_continueToLocationBreakpointId = "";
    379     }
    380 
    381     String scriptId;
    382     int lineNumber;
    383     int columnNumber;
    384 
    385     if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
    386         return;
    387 
    388     ScriptBreakpoint breakpoint(lineNumber, columnNumber, "");
    389     m_continueToLocationBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &lineNumber, &columnNumber, interstateLocation);
    390     resume(errorString);
    391 }
    392 
    393 void InspectorDebuggerAgent::getStepInPositions(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location> >& positions)
    394 {
    395     if (!isPaused() || m_currentCallStack.isNull()) {
    396         *errorString = "Attempt to access callframe when debugger is not on pause";
    397         return;
    398     }
    399     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
    400     if (injectedScript.hasNoValue()) {
    401         *errorString = "Inspected frame has gone";
    402         return;
    403     }
    404 
    405     injectedScript.getStepInPositions(errorString, m_currentCallStack, callFrameId, positions);
    406 }
    407 
    408 void InspectorDebuggerAgent::getBacktrace(ErrorString* errorString, RefPtr<Array<TypeBuilder::Debugger::CallFrame> >& callFrames)
    409 {
    410     if (!assertPaused(errorString))
    411         return;
    412     scriptDebugServer().updateCallStack(&m_currentCallStack);
    413     callFrames = currentCallFrames();
    414 }
    415 
    416 String InspectorDebuggerAgent::scriptURL(JavaScriptCallFrame* frame)
    417 {
    418     String scriptIdString = String::number(frame->sourceID());
    419     ScriptsMap::iterator it = m_scripts.find(scriptIdString);
    420     if (it == m_scripts.end())
    421         return String();
    422     return it->value.url;
    423 }
    424 
    425 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipExceptionPause(RefPtr<JavaScriptCallFrame>& topFrame)
    426 {
    427     String topFrameScriptUrl = scriptURL(topFrame.get());
    428     if (m_cachedSkipStackRegExp && !topFrameScriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(topFrameScriptUrl) != -1)
    429         return ScriptDebugListener::Continue;
    430 
    431     // Prepare top frame parameters;
    432     int topFrameLineNumber = topFrame->line();
    433     int topFrameColumnNumber = topFrame->column();
    434 
    435     // Match against breakpoints.
    436     if (topFrameScriptUrl.isEmpty())
    437         return ScriptDebugListener::NoSkip;
    438 
    439     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
    440     for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
    441         RefPtr<JSONObject> breakpointObject = it->value->asObject();
    442         bool isAntibreakpoint;
    443         breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
    444         if (!isAntibreakpoint)
    445             continue;
    446 
    447         int breakLineNumber;
    448         breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakLineNumber);
    449         int breakColumnNumber;
    450         breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakColumnNumber);
    451 
    452         if (breakLineNumber != topFrameLineNumber)
    453             continue;
    454 
    455         if (breakColumnNumber != -1 && breakColumnNumber != topFrameColumnNumber)
    456             continue;
    457 
    458         bool isRegex;
    459         breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
    460         String url;
    461         breakpointObject->getString(DebuggerAgentState::url, &url);
    462         if (!matches(topFrameScriptUrl, url, isRegex))
    463             continue;
    464 
    465         return ScriptDebugListener::Continue;
    466     }
    467 
    468     return ScriptDebugListener::NoSkip;
    469 }
    470 
    471 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipBreakpointPause(RefPtr<JavaScriptCallFrame>& topFrame)
    472 {
    473     return ScriptDebugListener::NoSkip;
    474 }
    475 
    476 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipStepPause(RefPtr<JavaScriptCallFrame>& topFrame)
    477 {
    478     if (m_cachedSkipStackRegExp) {
    479         String scriptUrl = scriptURL(topFrame.get());
    480         if (!scriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(scriptUrl) != -1) {
    481             if (m_skipStepInCount > 0) {
    482                 --m_skipStepInCount;
    483                 return ScriptDebugListener::StepInto;
    484             }
    485             return ScriptDebugListener::StepOut;
    486         }
    487     }
    488     return ScriptDebugListener::NoSkip;
    489 }
    490 
    491 PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source)
    492 {
    493     ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
    494     if (scriptIterator == m_scripts.end())
    495         return 0;
    496     Script& script = scriptIterator->value;
    497     if (breakpoint.lineNumber < script.startLine || script.endLine < breakpoint.lineNumber)
    498         return 0;
    499 
    500     int actualLineNumber;
    501     int actualColumnNumber;
    502     String debugServerBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber, false);
    503     if (debugServerBreakpointId.isEmpty())
    504         return 0;
    505 
    506     m_serverBreakpoints.set(debugServerBreakpointId, std::make_pair(breakpointId, source));
    507 
    508     BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
    509     if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
    510         debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.set(breakpointId, Vector<String>()).iterator;
    511     debugServerBreakpointIdsIterator->value.append(debugServerBreakpointId);
    512 
    513     RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
    514         .setScriptId(scriptId)
    515         .setLineNumber(actualLineNumber);
    516     location->setColumnNumber(actualColumnNumber);
    517     return location;
    518 }
    519 
    520 static PassRefPtr<JSONObject> scriptToInspectorObject(ScriptObject scriptObject)
    521 {
    522     if (scriptObject.hasNoValue())
    523         return 0;
    524     RefPtr<JSONValue> value = scriptObject.toJSONValue(scriptObject.scriptState());
    525     if (!value)
    526         return 0;
    527     return value->asObject();
    528 }
    529 
    530 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)
    531 {
    532     bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
    533     bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
    534 
    535     ScriptsMap::iterator it = m_scripts.find(scriptId);
    536     if (it != m_scripts.end())
    537         results = ContentSearchUtils::searchInTextByLines(it->value.source, query, caseSensitive, isRegex);
    538     else
    539         *error = "No script for id: " + scriptId;
    540 }
    541 
    542 void InspectorDebuggerAgent::setScriptSource(ErrorString* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, const String& scriptId, const String& newContent, const bool* const preview, RefPtr<Array<TypeBuilder::Debugger::CallFrame> >& newCallFrames, RefPtr<JSONObject>& result)
    543 {
    544     bool previewOnly = preview && *preview;
    545     ScriptObject resultObject;
    546     if (!scriptDebugServer().setScriptSource(scriptId, newContent, previewOnly, error, errorData, &m_currentCallStack, &resultObject))
    547         return;
    548     newCallFrames = currentCallFrames();
    549     RefPtr<JSONObject> object = scriptToInspectorObject(resultObject);
    550     if (object)
    551         result = object;
    552 }
    553 void InspectorDebuggerAgent::restartFrame(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::CallFrame> >& newCallFrames, RefPtr<JSONObject>& result)
    554 {
    555     if (!isPaused() || m_currentCallStack.isNull()) {
    556         *errorString = "Attempt to access callframe when debugger is not on pause";
    557         return;
    558     }
    559     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
    560     if (injectedScript.hasNoValue()) {
    561         *errorString = "Inspected frame has gone";
    562         return;
    563     }
    564 
    565     injectedScript.restartFrame(errorString, m_currentCallStack, callFrameId, &result);
    566     scriptDebugServer().updateCallStack(&m_currentCallStack);
    567     newCallFrames = currentCallFrames();
    568 }
    569 
    570 void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& scriptId, String* scriptSource)
    571 {
    572     ScriptsMap::iterator it = m_scripts.find(scriptId);
    573     if (it != m_scripts.end())
    574         *scriptSource = it->value.source;
    575     else
    576         *error = "No script for id: " + scriptId;
    577 }
    578 
    579 void InspectorDebuggerAgent::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<TypeBuilder::Debugger::FunctionDetails>& details)
    580 {
    581     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(functionId);
    582     if (injectedScript.hasNoValue()) {
    583         *errorString = "Function object id is obsolete";
    584         return;
    585     }
    586     injectedScript.getFunctionDetails(errorString, functionId, &details);
    587 }
    588 
    589 void InspectorDebuggerAgent::schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
    590 {
    591     if (m_javaScriptPauseScheduled)
    592         return;
    593     m_breakReason = breakReason;
    594     m_breakAuxData = data;
    595     scriptDebugServer().setPauseOnNextStatement(true);
    596 }
    597 
    598 void InspectorDebuggerAgent::cancelPauseOnNextStatement()
    599 {
    600     if (m_javaScriptPauseScheduled)
    601         return;
    602     clearBreakDetails();
    603     scriptDebugServer().setPauseOnNextStatement(false);
    604 }
    605 
    606 void InspectorDebuggerAgent::didFireTimer()
    607 {
    608     cancelPauseOnNextStatement();
    609 }
    610 
    611 void InspectorDebuggerAgent::didHandleEvent()
    612 {
    613     cancelPauseOnNextStatement();
    614 }
    615 
    616 void InspectorDebuggerAgent::pause(ErrorString*)
    617 {
    618     if (m_javaScriptPauseScheduled)
    619         return;
    620     clearBreakDetails();
    621     scriptDebugServer().setPauseOnNextStatement(true);
    622     m_javaScriptPauseScheduled = true;
    623 }
    624 
    625 void InspectorDebuggerAgent::resume(ErrorString* errorString)
    626 {
    627     if (!assertPaused(errorString))
    628         return;
    629     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
    630     scriptDebugServer().continueProgram();
    631 }
    632 
    633 void InspectorDebuggerAgent::stepOver(ErrorString* errorString)
    634 {
    635     if (!assertPaused(errorString))
    636         return;
    637     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
    638     scriptDebugServer().stepOverStatement();
    639 }
    640 
    641 void InspectorDebuggerAgent::stepInto(ErrorString* errorString)
    642 {
    643     if (!assertPaused(errorString))
    644         return;
    645     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
    646     scriptDebugServer().stepIntoStatement();
    647     if (m_listener)
    648         m_listener->stepInto();
    649 }
    650 
    651 void InspectorDebuggerAgent::stepOut(ErrorString* errorString)
    652 {
    653     if (!assertPaused(errorString))
    654         return;
    655     m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
    656     scriptDebugServer().stepOutOfFunction();
    657 }
    658 
    659 void InspectorDebuggerAgent::setPauseOnExceptions(ErrorString* errorString, const String& stringPauseState)
    660 {
    661     ScriptDebugServer::PauseOnExceptionsState pauseState;
    662     if (stringPauseState == "none")
    663         pauseState = ScriptDebugServer::DontPauseOnExceptions;
    664     else if (stringPauseState == "all")
    665         pauseState = ScriptDebugServer::PauseOnAllExceptions;
    666     else if (stringPauseState == "uncaught")
    667         pauseState = ScriptDebugServer::PauseOnUncaughtExceptions;
    668     else {
    669         *errorString = "Unknown pause on exceptions mode: " + stringPauseState;
    670         return;
    671     }
    672     setPauseOnExceptionsImpl(errorString, pauseState);
    673 }
    674 
    675 void InspectorDebuggerAgent::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
    676 {
    677     scriptDebugServer().setPauseOnExceptionsState(static_cast<ScriptDebugServer::PauseOnExceptionsState>(pauseState));
    678     if (scriptDebugServer().pauseOnExceptionsState() != pauseState)
    679         *errorString = "Internal error. Could not change pause on exceptions state";
    680     else
    681         m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, pauseState);
    682 }
    683 
    684 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<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
    685 {
    686     if (!isPaused() || m_currentCallStack.isNull()) {
    687         *errorString = "Attempt to access callframe when debugger is not on pause";
    688         return;
    689     }
    690     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
    691     if (injectedScript.hasNoValue()) {
    692         *errorString = "Inspected frame has gone";
    693         return;
    694     }
    695 
    696     ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
    697     if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
    698         if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
    699             scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
    700         muteConsole();
    701     }
    702 
    703     injectedScript.evaluateOnCallFrame(errorString, m_currentCallStack, callFrameId, expression, objectGroup ? *objectGroup : "", includeCommandLineAPI ? *includeCommandLineAPI : false, returnByValue ? *returnByValue : false, generatePreview ? *generatePreview : false, &result, wasThrown);
    704 
    705     if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
    706         unmuteConsole();
    707         if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
    708             scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
    709     }
    710 }
    711 
    712 void InspectorDebuggerAgent::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, TypeBuilder::OptOutput<ScriptId>* scriptId, TypeBuilder::OptOutput<String>* syntaxErrorMessage)
    713 {
    714     InjectedScript injectedScript = injectedScriptForEval(errorString, 0);
    715     if (injectedScript.hasNoValue()) {
    716         *errorString = "Inspected frame has gone";
    717         return;
    718     }
    719 
    720     String scriptIdValue;
    721     String exceptionMessage;
    722     scriptDebugServer().compileScript(injectedScript.scriptState(), expression, sourceURL, &scriptIdValue, &exceptionMessage);
    723     if (!scriptIdValue && !exceptionMessage) {
    724         *errorString = "Script compilation failed";
    725         return;
    726     }
    727     *syntaxErrorMessage = exceptionMessage;
    728     *scriptId = scriptIdValue;
    729 }
    730 
    731 void InspectorDebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
    732 {
    733     InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
    734     if (injectedScript.hasNoValue()) {
    735         *errorString = "Inspected frame has gone";
    736         return;
    737     }
    738 
    739     ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
    740     if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
    741         if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
    742             scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
    743         muteConsole();
    744     }
    745 
    746     ScriptValue value;
    747     bool wasThrownValue;
    748     String exceptionMessage;
    749     scriptDebugServer().runScript(injectedScript.scriptState(), scriptId, &value, &wasThrownValue, &exceptionMessage);
    750     *wasThrown = wasThrownValue;
    751     if (value.hasNoValue()) {
    752         *errorString = "Script execution failed";
    753         return;
    754     }
    755     result = injectedScript.wrapObject(value, objectGroup ? *objectGroup : "");
    756     if (wasThrownValue)
    757         result->setDescription(exceptionMessage);
    758 
    759     if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
    760         unmuteConsole();
    761         if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
    762             scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
    763     }
    764 }
    765 
    766 void InspectorDebuggerAgent::setOverlayMessage(ErrorString*, const String*)
    767 {
    768 }
    769 
    770 void InspectorDebuggerAgent::setVariableValue(ErrorString* errorString, int scopeNumber, const String& variableName, const RefPtr<JSONObject>& newValue, const String* callFrameId, const String* functionObjectId)
    771 {
    772     InjectedScript injectedScript;
    773     if (callFrameId) {
    774         if (!isPaused() || m_currentCallStack.isNull()) {
    775             *errorString = "Attempt to access callframe when debugger is not on pause";
    776             return;
    777         }
    778         injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*callFrameId);
    779         if (injectedScript.hasNoValue()) {
    780             *errorString = "Inspected frame has gone";
    781             return;
    782         }
    783     } else if (functionObjectId) {
    784         injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*functionObjectId);
    785         if (injectedScript.hasNoValue()) {
    786             *errorString = "Function object id cannot be resolved";
    787             return;
    788         }
    789     } else {
    790         *errorString = "Either call frame or function object must be specified";
    791         return;
    792     }
    793     String newValueString = newValue->toJSONString();
    794 
    795     injectedScript.setVariableValue(errorString, m_currentCallStack, callFrameId, functionObjectId, scopeNumber, variableName, newValueString);
    796 }
    797 
    798 void InspectorDebuggerAgent::skipStackFrames(ErrorString* errorString, const String* pattern)
    799 {
    800     OwnPtr<RegularExpression> compiled;
    801     String patternValue = pattern ? *pattern : "";
    802     if (!patternValue.isEmpty()) {
    803         compiled = compileSkipCallFramePattern(patternValue);
    804         if (!compiled) {
    805             *errorString = "Invalid regular expression";
    806             return;
    807         }
    808     }
    809     m_state->setString(DebuggerAgentState::skipStackPattern, patternValue);
    810     m_cachedSkipStackRegExp = compiled.release();
    811 }
    812 
    813 void InspectorDebuggerAgent::scriptExecutionBlockedByCSP(const String& directiveText)
    814 {
    815     if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions) {
    816         RefPtr<JSONObject> directive = JSONObject::create();
    817         directive->setString("directiveText", directiveText);
    818         breakProgram(InspectorFrontend::Debugger::Reason::CSPViolation, directive.release());
    819     }
    820 }
    821 
    822 PassRefPtr<Array<TypeBuilder::Debugger::CallFrame> > InspectorDebuggerAgent::currentCallFrames()
    823 {
    824     if (!m_pausedScriptState)
    825         return Array<TypeBuilder::Debugger::CallFrame>::create();
    826     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m_pausedScriptState);
    827     if (injectedScript.hasNoValue()) {
    828         ASSERT_NOT_REACHED();
    829         return Array<TypeBuilder::Debugger::CallFrame>::create();
    830     }
    831     return injectedScript.wrapCallFrames(m_currentCallStack);
    832 }
    833 
    834 String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script)
    835 {
    836     bool deprecated;
    837     String sourceMapURL = ContentSearchUtils::findSourceMapURL(script.source, ContentSearchUtils::JavaScriptMagicComment, &deprecated);
    838     if (!sourceMapURL.isEmpty()) {
    839         // FIXME: add deprecated console message here.
    840         return sourceMapURL;
    841     }
    842 
    843     if (script.url.isEmpty())
    844         return String();
    845 
    846     InspectorPageAgent* pageAgent = m_instrumentingAgents->inspectorPageAgent();
    847     if (!pageAgent)
    848         return String();
    849     return pageAgent->resourceSourceMapURL(script.url);
    850 }
    851 
    852 // JavaScriptDebugListener functions
    853 
    854 void InspectorDebuggerAgent::didParseSource(const String& scriptId, const Script& script)
    855 {
    856     // Don't send script content to the front end until it's really needed.
    857     const bool* isContentScript = script.isContentScript ? &script.isContentScript : 0;
    858     String sourceMapURL = sourceMapURLForScript(script);
    859     String* sourceMapURLParam = sourceMapURL.isNull() ? 0 : &sourceMapURL;
    860     String sourceURL;
    861     if (!script.startLine && !script.startColumn) {
    862         bool deprecated;
    863         sourceURL = ContentSearchUtils::findSourceURL(script.source, ContentSearchUtils::JavaScriptMagicComment, &deprecated);
    864         // FIXME: add deprecated console message here.
    865     }
    866     bool hasSourceURL = !sourceURL.isEmpty();
    867     String scriptURL = hasSourceURL ? sourceURL : script.url;
    868     bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : 0;
    869     m_frontend->scriptParsed(scriptId, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam);
    870 
    871     m_scripts.set(scriptId, script);
    872 
    873     if (scriptURL.isEmpty())
    874         return;
    875 
    876     RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
    877     for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
    878         RefPtr<JSONObject> breakpointObject = it->value->asObject();
    879         bool isAntibreakpoint;
    880         breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
    881         if (isAntibreakpoint)
    882             continue;
    883         bool isRegex;
    884         breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
    885         String url;
    886         breakpointObject->getString(DebuggerAgentState::url, &url);
    887         if (!matches(scriptURL, url, isRegex))
    888             continue;
    889         ScriptBreakpoint breakpoint;
    890         breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakpoint.lineNumber);
    891         breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakpoint.columnNumber);
    892         breakpointObject->getString(DebuggerAgentState::condition, &breakpoint.condition);
    893         RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it->key, scriptId, breakpoint, UserBreakpointSource);
    894         if (location)
    895             m_frontend->breakpointResolved(it->key, location);
    896     }
    897 }
    898 
    899 void InspectorDebuggerAgent::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage)
    900 {
    901     m_frontend->scriptFailedToParse(url, data, firstLine, errorLine, errorMessage);
    902 }
    903 
    904 void InspectorDebuggerAgent::didPause(ScriptState* scriptState, const ScriptValue& callFrames, const ScriptValue& exception, const Vector<String>& hitBreakpoints)
    905 {
    906     ASSERT(scriptState && !m_pausedScriptState);
    907     m_pausedScriptState = scriptState;
    908     m_currentCallStack = callFrames;
    909 
    910     m_skipStepInCount = numberOfStepsBeforeStepOut;
    911 
    912     if (!exception.hasNoValue()) {
    913         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
    914         if (!injectedScript.hasNoValue()) {
    915             m_breakReason = InspectorFrontend::Debugger::Reason::Exception;
    916             m_breakAuxData = injectedScript.wrapObject(exception, "backtrace")->openAccessors();
    917             // m_breakAuxData might be null after this.
    918         }
    919     }
    920 
    921     RefPtr<Array<String> > hitBreakpointIds = Array<String>::create();
    922 
    923     for (Vector<String>::const_iterator i = hitBreakpoints.begin(); i != hitBreakpoints.end(); ++i) {
    924         DebugServerBreakpointToBreakpointIdAndSourceMap::iterator breakpointIterator = m_serverBreakpoints.find(*i);
    925         if (breakpointIterator != m_serverBreakpoints.end()) {
    926             const String& localId = breakpointIterator->value.first;
    927             hitBreakpointIds->addItem(localId);
    928 
    929             BreakpointSource source = breakpointIterator->value.second;
    930             if (m_breakReason == InspectorFrontend::Debugger::Reason::Other && source == DebugCommandBreakpointSource)
    931                 m_breakReason = InspectorFrontend::Debugger::Reason::DebugCommand;
    932         }
    933     }
    934 
    935     m_frontend->paused(currentCallFrames(), m_breakReason, m_breakAuxData, hitBreakpointIds);
    936     m_javaScriptPauseScheduled = false;
    937 
    938     if (!m_continueToLocationBreakpointId.isEmpty()) {
    939         scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
    940         m_continueToLocationBreakpointId = "";
    941     }
    942     if (m_listener)
    943         m_listener->didPause();
    944 }
    945 
    946 void InspectorDebuggerAgent::didContinue()
    947 {
    948     m_pausedScriptState = 0;
    949     m_currentCallStack = ScriptValue();
    950     clearBreakDetails();
    951     m_frontend->resumed();
    952 }
    953 
    954 bool InspectorDebuggerAgent::canBreakProgram()
    955 {
    956     return scriptDebugServer().canBreakProgram();
    957 }
    958 
    959 void InspectorDebuggerAgent::breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
    960 {
    961     m_breakReason = breakReason;
    962     m_breakAuxData = data;
    963     scriptDebugServer().breakProgram();
    964 }
    965 
    966 void InspectorDebuggerAgent::clear()
    967 {
    968     m_pausedScriptState = 0;
    969     m_currentCallStack = ScriptValue();
    970     m_scripts.clear();
    971     m_breakpointIdToDebugServerBreakpointIds.clear();
    972     m_continueToLocationBreakpointId = String();
    973     clearBreakDetails();
    974     m_javaScriptPauseScheduled = false;
    975     ErrorString error;
    976     setOverlayMessage(&error, 0);
    977 }
    978 
    979 bool InspectorDebuggerAgent::assertPaused(ErrorString* errorString)
    980 {
    981     if (!m_pausedScriptState) {
    982         *errorString = "Can only perform operation while paused.";
    983         return false;
    984     }
    985     return true;
    986 }
    987 
    988 void InspectorDebuggerAgent::clearBreakDetails()
    989 {
    990     m_breakReason = InspectorFrontend::Debugger::Reason::Other;
    991     m_breakAuxData = 0;
    992 }
    993 
    994 void InspectorDebuggerAgent::setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source, const String& condition)
    995 {
    996     String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, source);
    997     ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
    998     resolveBreakpoint(breakpointId, scriptId, breakpoint, source);
    999 }
   1000 
   1001 void InspectorDebuggerAgent::removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source)
   1002 {
   1003     removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, source));
   1004 }
   1005 
   1006 void InspectorDebuggerAgent::reset()
   1007 {
   1008     m_scripts.clear();
   1009     m_breakpointIdToDebugServerBreakpointIds.clear();
   1010     if (m_frontend)
   1011         m_frontend->globalObjectCleared();
   1012 }
   1013 
   1014 } // namespace WebCore
   1015 
   1016