2020
2121#include " libplatform/libplatform.h"
2222
23+ #include < map>
24+ #include < sstream>
2325#include < string.h>
2426#include < utility>
2527#include < vector>
@@ -53,6 +55,21 @@ void PrintDebuggerReadyMessage(int port, const std::string& id) {
5355 fflush (stderr);
5456}
5557
58+ std::string MapToString (const std::map<std::string, std::string> object) {
59+ std::ostringstream json;
60+ json << " [ {\n " ;
61+ bool first = true ;
62+ for (const auto & name_value : object) {
63+ if (!first)
64+ json << " ,\n " ;
65+ json << " \" " << name_value.first << " \" : \" " ;
66+ json << name_value.second << " \" " ;
67+ first = false ;
68+ }
69+ json << " \n } ]" ;
70+ return json.str ();
71+ }
72+
5673void Escape (std::string* string) {
5774 for (char & c : *string) {
5875 c = (c == ' \" ' || c == ' \\ ' ) ? ' _' : c;
@@ -74,33 +91,23 @@ void OnBufferAlloc(uv_handle_t* handle, size_t len, uv_buf_t* buf) {
7491 buf->len = len;
7592}
7693
77- void SendHttpResponse (InspectorSocket* socket, const char * response,
78- size_t len) {
94+ void SendHttpResponse (InspectorSocket* socket, const std::string& response) {
7995 const char HEADERS[] = " HTTP/1.0 200 OK\r\n "
8096 " Content-Type: application/json; charset=UTF-8\r\n "
8197 " Cache-Control: no-cache\r\n "
8298 " Content-Length: %zu\r\n "
8399 " \r\n " ;
84100 char header[sizeof (HEADERS) + 20 ];
85- int header_len = snprintf (header, sizeof (header), HEADERS, len );
101+ int header_len = snprintf (header, sizeof (header), HEADERS, response. size () );
86102 inspector_write (socket, header, header_len);
87- inspector_write (socket, response, len );
103+ inspector_write (socket, response. data (), response. size () );
88104}
89105
90106void SendVersionResponse (InspectorSocket* socket) {
91- const char VERSION_RESPONSE_TEMPLATE[] =
92- " [ {"
93- " \" Browser\" : \" node.js/%s\" ,"
94- " \" Protocol-Version\" : \" 1.1\" ,"
95- " \" User-Agent\" : \" Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"
96- " (KHTML, like Gecko) Chrome/45.0.2446.0 Safari/537.36\" ,"
97- " \" WebKit-Version\" : \" 537.36 (@198122)\" "
98- " } ]" ;
99- char buffer[sizeof (VERSION_RESPONSE_TEMPLATE) + 128 ];
100- size_t len = snprintf (buffer, sizeof (buffer), VERSION_RESPONSE_TEMPLATE,
101- NODE_VERSION);
102- ASSERT_LT (len, sizeof (buffer));
103- SendHttpResponse (socket, buffer, len);
107+ std::map<std::string, std::string> response;
108+ response[" Browser" ] = " node.js/" NODE_VERSION;
109+ response[" Protocol-Version" ] = " 1.1" ;
110+ SendHttpResponse (socket, MapToString (response));
104111}
105112
106113std::string GetProcessTitle () {
@@ -114,47 +121,6 @@ std::string GetProcessTitle() {
114121 }
115122}
116123
117- void SendTargentsListResponse (InspectorSocket* socket,
118- const std::string& script_name_,
119- const std::string& script_path_,
120- const std::string& id,
121- const std::string& ws_url) {
122- const char LIST_RESPONSE_TEMPLATE[] =
123- " [ {"
124- " \" description\" : \" node.js instance\" ,"
125- " \" devtoolsFrontendUrl\" : "
126- " \" https://chrome-devtools-frontend.appspot.com/serve_file/"
127- " @" V8_INSPECTOR_REVISION
128- " /inspector.html?experiments=true&v8only=true"
129- " &ws=%s\" ,"
130- " \" faviconUrl\" : \" https://nodejs.org/static/favicon.ico\" ,"
131- " \" id\" : \" %s\" ,"
132- " \" title\" : \" %s\" ,"
133- " \" type\" : \" node\" ,"
134- " \" url\" : \" %s\" ,"
135- " \" webSocketDebuggerUrl\" : \" ws://%s\" "
136- " } ]" ;
137- std::string title = script_name_.empty () ? GetProcessTitle () : script_name_;
138-
139- // This attribute value is a "best effort" URL that is passed as a JSON
140- // string. It is not guaranteed to resolve to a valid resource.
141- std::string url = " file://" + script_path_;
142-
143- Escape (&title);
144- Escape (&url);
145-
146- int buf_len = sizeof (LIST_RESPONSE_TEMPLATE) + ws_url.length () * 2 +
147- id.length () + title.length () + url.length ();
148- std::string buffer (buf_len, ' \0 ' );
149-
150- int len = snprintf (&buffer[0 ], buf_len, LIST_RESPONSE_TEMPLATE,
151- ws_url.c_str (), id.c_str (), title.c_str (), url.c_str (),
152- ws_url.c_str ());
153- buffer.resize (len);
154- ASSERT_LT (len, buf_len); // Buffer should be big enough!
155- SendHttpResponse (socket, buffer.data (), len);
156- }
157-
158124void SendProtocolJson (InspectorSocket* socket) {
159125 z_stream strm;
160126 strm.zalloc = Z_NULL;
@@ -167,13 +133,13 @@ void SendProtocolJson(InspectorSocket* socket) {
167133 PROTOCOL_JSON[2 ];
168134 strm.next_in = const_cast <uint8_t *>(PROTOCOL_JSON + 3 );
169135 strm.avail_in = sizeof (PROTOCOL_JSON) - 3 ;
170- std::vector< char > data (kDecompressedSize );
136+ std::string data (kDecompressedSize , ' \0 ' );
171137 strm.next_out = reinterpret_cast <Byte*>(&data[0 ]);
172138 strm.avail_out = data.size ();
173139 CHECK_EQ (Z_STREAM_END, inflate (&strm, Z_FINISH));
174140 CHECK_EQ (0 , strm.avail_out );
175141 CHECK_EQ (Z_OK, inflateEnd (&strm));
176- SendHttpResponse (socket, & data[ 0 ], data. size () );
142+ SendHttpResponse (socket, data);
177143}
178144
179145const char * match_path_segment (const char * path, const char * expected) {
@@ -205,6 +171,12 @@ std::string GenerateID() {
205171 return uuid;
206172}
207173
174+ // std::to_string is not available on Smart OS and ARM flavours
175+ const std::string to_string (uint64_t number) {
176+ std::ostringstream result;
177+ result << number;
178+ return result.str ();
179+ }
208180} // namespace
209181
210182
@@ -253,8 +225,9 @@ class AgentImpl {
253225 void PostIncomingMessage (const String16& message);
254226 void WaitForFrontendMessage ();
255227 void NotifyMessageReceived ();
256- bool RespondToGet (InspectorSocket* socket, const std::string& path);
257228 State ToState (State state);
229+ void SendTargentsListResponse (InspectorSocket* socket);
230+ bool RespondToGet (InspectorSocket* socket, const std::string& path);
258231
259232 uv_sem_t start_sem_;
260233 ConditionVariable incoming_message_cond_;
@@ -673,14 +646,41 @@ void AgentImpl::OnRemoteDataIO(InspectorSocket* socket,
673646 }
674647}
675648
649+ void AgentImpl::SendTargentsListResponse (InspectorSocket* socket) {
650+ std::map<std::string, std::string> response;
651+ response[" description" ] = " node.js instance" ;
652+ response[" faviconUrl" ] = " https://nodejs.org/static/favicon.ico" ;
653+ response[" id" ] = id_;
654+ response[" title" ] = script_name_.empty () ? GetProcessTitle () : script_name_;
655+ Escape (&response[" title" ]);
656+ response[" type" ] = " node" ;
657+ // This attribute value is a "best effort" URL that is passed as a JSON
658+ // string. It is not guaranteed to resolve to a valid resource.
659+ response[" url" ] = " file://" + script_path_;
660+ Escape (&response[" url" ]);
661+
662+ if (!client_socket_) {
663+ std::string address = GetWsUrl (port_, id_);
664+
665+ std::ostringstream frontend_url;
666+ frontend_url << " https://chrome-devtools-frontend.appspot.com/serve_file/@" ;
667+ frontend_url << V8_INSPECTOR_REVISION;
668+ frontend_url << " /inspector.html?experiments=true&v8only=true&ws=" ;
669+ frontend_url << address;
670+
671+ response[" devtoolsFrontendUrl" ] += frontend_url.str ();
672+ response[" webSocketDebuggerUrl" ] = " ws://" + address;
673+ }
674+ SendHttpResponse (socket, MapToString (response));
675+ }
676+
676677bool AgentImpl::RespondToGet (InspectorSocket* socket, const std::string& path) {
677678 const char * command = match_path_segment (path.c_str (), " /json" );
678679 if (command == nullptr )
679680 return false ;
680681
681682 if (match_path_segment (command, " list" ) || command[0 ] == ' \0 ' ) {
682- SendTargentsListResponse (socket, script_name_, script_path_, id_,
683- GetWsUrl (port_, id_));
683+ SendTargentsListResponse (socket);
684684 } else if (match_path_segment (command, " protocol" )) {
685685 SendProtocolJson (socket);
686686 } else if (match_path_segment (command, " version" )) {
@@ -689,8 +689,7 @@ bool AgentImpl::RespondToGet(InspectorSocket* socket, const std::string& path) {
689689 const char * pid = match_path_segment (command, " activate" );
690690 if (pid != id_)
691691 return false ;
692- const char TARGET_ACTIVATED[] = " Target activated" ;
693- SendHttpResponse (socket, TARGET_ACTIVATED, sizeof (TARGET_ACTIVATED) - 1 );
692+ SendHttpResponse (socket, " Target activated" );
694693 }
695694 return true ;
696695}
0 commit comments