20
20
21
21
#include " libplatform/libplatform.h"
22
22
23
+ #include < map>
24
+ #include < sstream>
23
25
#include < string.h>
24
26
#include < utility>
25
27
#include < vector>
@@ -53,6 +55,21 @@ void PrintDebuggerReadyMessage(int port, const std::string& id) {
53
55
fflush (stderr);
54
56
}
55
57
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
+
56
73
void Escape (std::string* string) {
57
74
for (char & c : *string) {
58
75
c = (c == ' \" ' || c == ' \\ ' ) ? ' _' : c;
@@ -74,33 +91,23 @@ void OnBufferAlloc(uv_handle_t* handle, size_t len, uv_buf_t* buf) {
74
91
buf->len = len;
75
92
}
76
93
77
- void SendHttpResponse (InspectorSocket* socket, const char * response,
78
- size_t len) {
94
+ void SendHttpResponse (InspectorSocket* socket, const std::string& response) {
79
95
const char HEADERS[] = " HTTP/1.0 200 OK\r\n "
80
96
" Content-Type: application/json; charset=UTF-8\r\n "
81
97
" Cache-Control: no-cache\r\n "
82
98
" Content-Length: %zu\r\n "
83
99
" \r\n " ;
84
100
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 () );
86
102
inspector_write (socket, header, header_len);
87
- inspector_write (socket, response, len );
103
+ inspector_write (socket, response. data (), response. size () );
88
104
}
89
105
90
106
void 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));
104
111
}
105
112
106
113
std::string GetProcessTitle () {
@@ -114,47 +121,6 @@ std::string GetProcessTitle() {
114
121
}
115
122
}
116
123
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
-
158
124
void SendProtocolJson (InspectorSocket* socket) {
159
125
z_stream strm;
160
126
strm.zalloc = Z_NULL;
@@ -167,13 +133,13 @@ void SendProtocolJson(InspectorSocket* socket) {
167
133
PROTOCOL_JSON[2 ];
168
134
strm.next_in = const_cast <uint8_t *>(PROTOCOL_JSON + 3 );
169
135
strm.avail_in = sizeof (PROTOCOL_JSON) - 3 ;
170
- std::vector< char > data (kDecompressedSize );
136
+ std::string data (kDecompressedSize , ' \0 ' );
171
137
strm.next_out = reinterpret_cast <Byte *>(&data[0 ]);
172
138
strm.avail_out = data.size ();
173
139
CHECK_EQ (Z_STREAM_END, inflate (&strm, Z_FINISH));
174
140
CHECK_EQ (0 , strm.avail_out );
175
141
CHECK_EQ (Z_OK, inflateEnd (&strm));
176
- SendHttpResponse (socket, & data[ 0 ], data. size () );
142
+ SendHttpResponse (socket, data);
177
143
}
178
144
179
145
const char * match_path_segment (const char * path, const char * expected) {
@@ -205,6 +171,12 @@ std::string GenerateID() {
205
171
return uuid;
206
172
}
207
173
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
+ }
208
180
} // namespace
209
181
210
182
@@ -253,8 +225,9 @@ class AgentImpl {
253
225
void PostIncomingMessage (const String16& message);
254
226
void WaitForFrontendMessage ();
255
227
void NotifyMessageReceived ();
256
- bool RespondToGet (InspectorSocket* socket, const std::string& path);
257
228
State ToState (State state);
229
+ void SendTargentsListResponse (InspectorSocket* socket);
230
+ bool RespondToGet (InspectorSocket* socket, const std::string& path);
258
231
259
232
uv_sem_t start_sem_;
260
233
ConditionVariable incoming_message_cond_;
@@ -673,14 +646,41 @@ void AgentImpl::OnRemoteDataIO(InspectorSocket* socket,
673
646
}
674
647
}
675
648
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
+
676
677
bool AgentImpl::RespondToGet (InspectorSocket* socket, const std::string& path) {
677
678
const char * command = match_path_segment (path.c_str (), " /json" );
678
679
if (command == nullptr )
679
680
return false ;
680
681
681
682
if (match_path_segment (command, " list" ) || command[0 ] == ' \0 ' ) {
682
- SendTargentsListResponse (socket, script_name_, script_path_, id_,
683
- GetWsUrl (port_, id_));
683
+ SendTargentsListResponse (socket);
684
684
} else if (match_path_segment (command, " protocol" )) {
685
685
SendProtocolJson (socket);
686
686
} else if (match_path_segment (command, " version" )) {
@@ -689,8 +689,7 @@ bool AgentImpl::RespondToGet(InspectorSocket* socket, const std::string& path) {
689
689
const char * pid = match_path_segment (command, " activate" );
690
690
if (pid != id_)
691
691
return false ;
692
- const char TARGET_ACTIVATED[] = " Target activated" ;
693
- SendHttpResponse (socket, TARGET_ACTIVATED, sizeof (TARGET_ACTIVATED) - 1 );
692
+ SendHttpResponse (socket, " Target activated" );
694
693
}
695
694
return true ;
696
695
}
0 commit comments