1 /*
2  * SessionClientEvent.cpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 #include <session/SessionClientEvent.hpp>
17 
18 #include <boost/lexical_cast.hpp>
19 
20 #include <shared_core/Error.hpp>
21 #include <core/Log.hpp>
22 #include <shared_core/FilePath.hpp>
23 #include <shared_core/SafeConvert.hpp>
24 #include <core/FileSerializer.hpp>
25 #include <core/system/System.hpp>
26 
27 using namespace rstudio::core;
28 
29 namespace rstudio {
30 namespace session {
31 
32 namespace client_events {
33 
34 const int kBusy = 1;
35 const int kConsolePrompt = 2;
36 const int kConsoleWriteOutput = 3;
37 const int kConsoleWriteError = 4;
38 const int kShowErrorMessage = 5;
39 const int kShowHelp = 6;
40 const int kBrowseUrl = 7;
41 const int kShowEditor = 11;
42 const int kChooseFile = 13;
43 const int kAbendWarning = 14;
44 const int kQuit = 15;
45 const int kSuicide = 16;
46 const int kFileChanged = 17;
47 const int kWorkingDirChanged = 18;
48 const int kPlotsStateChanged = 19;
49 const int kPackageStatusChanged = 21;
50 const int kPackageStateChanged = 22;
51 const int kLocator = 23;
52 const int kConsoleResetHistory = 25;
53 const int kSessionSerialization = 26;
54 const int kHistoryEntriesAdded = 27;
55 const int kQuotaStatus = 29;
56 const int kFileEdit = 32;
57 const int kShowContent = 33;
58 const int kShowData = 34;
59 const int kAsyncCompletion = 35;
60 const int kSaveActionChanged = 36;
61 const int kConsoleWritePrompt = 37;
62 const int kConsoleWriteInput = 38;
63 const int kShowWarningBar = 39;
64 const int kOpenProjectError = 40;
65 const int kVcsRefresh = 41;
66 const int kAskPass = 42;
67 const int kConsoleProcessOutput = 43;
68 const int kConsoleProcessExit = 44;
69 const int kListChanged = 45;
70 const int kConsoleProcessCreated = 46;
71 const int kUserPrefsChanged = 47;
72 const int kHandleUnsavedChanges = 48;
73 const int kConsoleProcessPrompt = 49;
74 const int kHTMLPreviewStartedEvent = 51;
75 const int kHTMLPreviewOutputEvent = 52;
76 const int kHTMLPreviewCompletedEvent = 53;
77 const int kCompilePdfStartedEvent = 54;
78 const int kCompilePdfOutputEvent = 55;
79 const int kCompilePdfErrorsEvent = 56;
80 const int kCompilePdfCompletedEvent = 57;
81 const int kSynctexEditFile = 58;
82 const int kFindResult = 59;
83 const int kFindOperationEnded = 60;
84 const int kRPubsUploadStatus = 61;
85 const int kBuildStarted = 62;
86 const int kBuildOutput = 63;
87 const int kBuildCompleted = 64;
88 const int kBuildErrors = 65;
89 const int kDirectoryNavigate = 66;
90 const int kDeferredInitCompleted = 67;
91 const int kPlotsZoomSizeChanged = 68;
92 const int kSourceCppStarted = 69;
93 const int kSourceCppCompleted = 70;
94 const int kLoadedPackageUpdates = 71;
95 const int kActivatePane = 72;
96 const int kShowPresentationPane = 73;
97 const int kEnvironmentRefresh = 74;
98 const int kContextDepthChanged = 75;
99 const int kEnvironmentAssigned = 76;
100 const int kEnvironmentRemoved = 77;
101 const int kBrowserLineChanged = 78;
102 const int kPackageLoaded = 79;
103 const int kPackageUnloaded = 80;
104 const int kPresentationPaneRequestCompleted = 81;
105 const int kUnhandledError = 82;
106 const int kErrorHandlerChanged = 83;
107 const int kViewerNavigate = 84;
108 const int kSourceExtendedTypeDetected = 85;
109 const int kShinyViewer = 86;
110 const int kDebugSourceCompleted = 87;
111 const int kRmdRenderStarted = 88;
112 const int kRmdRenderOutput = 89;
113 const int kRmdRenderCompleted = 90;
114 const int kRmdTemplateDiscovered = 91;
115 const int kRmdTemplateDiscoveryCompleted = 92;
116 const int kRmdShinyDocStarted = 93;
117 const int kRmdRSConnectDeploymentOutput = 94;
118 const int kRmdRSConnectDeploymentCompleted = 95;
119 const int kUserPrompt = 96;
120 const int kInstallRtools = 97;
121 const int kInstallShiny = 98;
122 const int kSuspendAndRestart = 99;
123 const int kDataViewChanged = 100;
124 const int kViewFunction = 101;
125 const int kMarkersChanged = 102;
126 const int kEnableRStudioConnect = 103;
127 const int kUpdateGutterMarkers = 104;
128 const int kSnippetsChanged = 105;
129 const int kJumpToFunction = 106;
130 const int kCollabEditStarted = 107;
131 const int kSessionCountChanged = 108;
132 const int kCollabEditEnded = 109;
133 const int kProjectUsersChanged = 110;
134 const int kRVersionsChanged = 111;
135 const int kShinyGadgetDialog = 112;
136 const int kRmdParamsReady = 113;
137 const int kRegisterUserCommand = 114;
138 const int kRmdRSConnectDeploymentFailed = 115;
139 const int kSendToConsole = 119;
140 const int kUserFollowStarted = 120;
141 const int kUserFollowEnded = 121;
142 const int kProjectAccessRevoked = 122;
143 const int kCollabEditSaved = 123;
144 const int kAddinRegistryUpdated = 124;
145 const int kChunkOutput = 125;
146 const int kChunkOutputFinished = 126;
147 const int kRprofStarted = 127;
148 const int kRprofStopped = 128;
149 const int kRprofCreated = 129;
150 const int kEditorCommand = 131;
151 const int kPreviewRmd = 132;
152 const int kWebsiteFileSaved = 133;
153 const int kChunkPlotRefreshed = 134;
154 const int kChunkPlotRefreshFinished = 135;
155 const int kReloadWithLastChanceSave = 136;
156 const int kConnectionUpdated = 139;
157 const int kEnableConnections = 140;
158 const int kConnectionListChanged = 141;
159 const int kActiveConnectionsChanged = 142;
160 const int kConnectionOpened = 143;
161 const int kNotebookRangeExecuted = 144;
162 const int kChunkExecStateChanged = 145;
163 const int kNavigateShinyFrame = 146;
164 const int kUpdateNewConnectionDialog = 147;
165 const int kProjectTemplateRegistryUpdated = 148;
166 const int kTerminalSubprocs = 149;
167 const int kPackageExtensionIndexingCompleted = 150;
168 const int kRStudioAPIShowDialog = 151;
169 const int kRStudioAPIShowDialogCompleted = 152;
170 const int kObjectExplorerEvent = 153;
171 const int kSendToTerminal = 154;
172 const int kClearTerminal = 155;
173 const int kAddTerminal = 156;
174 const int kActivateTerminal = 157;
175 const int kTerminalCwd = 158;
176 const int kAdminNotification = 159;
177 const int kRequestDocumentSave = 160;
178 const int kRequestDocumentSaveCompleted = 161;
179 const int kRequestOpenProject = 162;
180 const int kOpenFileDialog = 163;
181 const int kRemoveTerminal = 164;
182 const int kShowPageViewerEvent = 165;
183 const int kAskSecret = 166;
184 const int kTestsStarted = 167;
185 const int kTestsOutput = 168;
186 const int kTestsCompleted = 169;
187 const int kJobUpdated = 170;
188 const int kJobRefresh = 171;
189 const int kJobOutput = 172;
190 const int kDataOutputCompleted = 173;
191 const int kNewDocumentWithCode = 174;
192 const int kPlumberViewer = 175;
193 const int kAvailablePackagesReady = 176;
194 const int kComputeThemeColors = 177;
195 const int kRequestDocumentClose = 178;
196 const int kRequestDocumentCloseCompleted = 179;
197 const int kExecuteAppCommand = 180;
198 const int kUserStateChanged = 181;
199 const int kHighlightUi = 182;
200 const int kReplaceResult = 183;
201 const int kReplaceUpdated = 184;
202 const int kTutorialCommand = 185;
203 const int kTutorialLaunch = 186;
204 const int kReticulateEvent = 187;
205 const int kEnvironmentChanged = 188;
206 const int kRStudioApiRequest = 189;
207 const int kDocumentCloseAllNoSave = 190;
208 const int kMemoryUsageChanged = 191;
209 const int kCommandCallbacksChanged = 192;
210 const int kConsoleActivate = 193;
211 const int kJobsActivate = 194;
212 }
213 
init(int type,const json::Value & data)214 void ClientEvent::init(int type, const json::Value& data)
215 {
216    type_ = type;
217    data_ = data;
218    id_ = core::system::generateUuid();
219 }
220 
asJsonObject(int id,json::Object * pObject) const221 void ClientEvent::asJsonObject(int id, json::Object* pObject) const
222 {
223    json::Object& object = *pObject;
224    object["id"] = id;
225    object["type"] = typeName();
226    object["data"] = data();
227 }
228 
typeName() const229 std::string ClientEvent::typeName() const
230 {
231    switch (type_)
232    {
233       case client_events::kBusy:
234          return "busy";
235       case client_events::kConsolePrompt:
236          return "console_prompt";
237       case client_events::kConsoleWriteOutput:
238          return "console_output";
239       case client_events::kConsoleWriteError:
240          return "console_error";
241       case client_events::kShowErrorMessage:
242          return "show_error_message";
243       case client_events::kShowHelp:
244          return "show_help";
245       case client_events::kBrowseUrl:
246          return "browse_url";
247       case client_events::kShowEditor:
248          return "show_editor";
249       case client_events::kChooseFile:
250          return "choose_file";
251       case client_events::kAbendWarning:
252          return "abend_warning";
253       case client_events::kQuit:
254          return "quit";
255       case client_events::kSuicide:
256          return "suicide";
257       case client_events::kFileChanged:
258          return "file_changed";
259       case client_events::kWorkingDirChanged:
260          return "working_dir_changed";
261       case client_events::kPlotsStateChanged:
262          return "plots_state_changed";
263       case client_events::kPackageStatusChanged:
264          return "package_status_changed";
265       case client_events::kPackageStateChanged:
266          return "package_state_changed";
267       case client_events::kLocator:
268          return "locator";
269       case client_events::kConsoleResetHistory:
270          return "console_reset_history";
271       case client_events::kSessionSerialization:
272          return "session_serialization";
273       case client_events::kHistoryEntriesAdded:
274          return "history_entries_added";
275       case client_events::kQuotaStatus:
276          return "quota_status";
277       case client_events::kFileEdit:
278          return "file_edit";
279       case client_events::kShowContent:
280          return "show_content";
281       case client_events::kShowData:
282          return "show_data";
283       case client_events::kAsyncCompletion:
284          return "async_completion";
285       case client_events::kSaveActionChanged:
286          return "save_action_changed";
287       case client_events::kConsoleWritePrompt:
288          return "console_write_prompt";
289       case client_events::kConsoleWriteInput:
290          return "console_write_input";
291       case client_events::kShowWarningBar:
292          return "show_warning_bar";
293       case client_events::kOpenProjectError:
294          return "open_project_error";
295       case client_events::kVcsRefresh:
296          return "vcs_refresh";
297       case client_events::kAskPass:
298          return "ask_pass";
299       case client_events::kConsoleProcessOutput:
300          return "console_process_output";
301       case client_events::kConsoleProcessExit:
302          return "console_process_exit";
303       case client_events::kListChanged:
304          return "list_changed";
305       case client_events::kUserPrefsChanged:
306          return "user_prefs_changed";
307       case client_events::kHandleUnsavedChanges:
308          return "handle_unsaved_changes";
309       case client_events::kConsoleProcessPrompt:
310          return "console_process_prompt";
311       case client_events::kConsoleProcessCreated:
312          return "console_process_created";
313       case client_events::kHTMLPreviewStartedEvent:
314          return "html_preview_started_event";
315       case client_events::kHTMLPreviewOutputEvent:
316          return "html_preview_output_event";
317       case client_events::kHTMLPreviewCompletedEvent:
318          return "html_preview_completed_event";
319       case client_events::kCompilePdfStartedEvent:
320          return "compile_pdf_started_event";
321       case client_events::kCompilePdfOutputEvent:
322          return "compile_pdf_output_event";
323       case client_events::kCompilePdfErrorsEvent:
324          return "compile_pdf_errors_event";
325       case client_events::kCompilePdfCompletedEvent:
326          return "compile_pdf_completed_event";
327       case client_events::kSynctexEditFile:
328          return "synctex_edit_file";
329       case client_events::kFindResult:
330          return "find_result";
331       case client_events::kFindOperationEnded:
332          return "find_operation_ended";
333       case client_events::kRPubsUploadStatus:
334          return "rpubs_upload_status";
335       case client_events::kBuildStarted:
336          return "build_started";
337       case client_events::kBuildOutput:
338          return "build_output";
339       case client_events::kBuildCompleted:
340          return "build_completed";
341       case client_events::kBuildErrors:
342          return "build_errors";
343       case client_events::kDirectoryNavigate:
344          return "directory_navigate";
345       case client_events::kDeferredInitCompleted:
346          return "deferred_init_completed";
347       case client_events::kPlotsZoomSizeChanged:
348          return "plots_zoom_size_changed";
349       case client_events::kSourceCppStarted:
350          return "source_cpp_started";
351       case client_events::kSourceCppCompleted:
352          return "source_cpp_completed";
353       case client_events::kLoadedPackageUpdates:
354          return "loaded_package_updates";
355       case client_events::kActivatePane:
356          return "activate_pane";
357       case client_events::kShowPresentationPane:
358          return "show_presentation_pane";
359       case client_events::kEnvironmentRefresh:
360          return "environment_refresh";
361       case client_events::kContextDepthChanged:
362          return "context_depth_changed";
363       case client_events::kEnvironmentAssigned:
364          return "environment_assigned";
365       case client_events::kEnvironmentRemoved:
366          return "environment_removed";
367       case client_events::kBrowserLineChanged:
368          return "browser_line_changed";
369       case client_events::kPackageLoaded:
370          return "package_loaded";
371       case client_events::kPackageUnloaded:
372          return "package_unloaded";
373       case client_events::kPresentationPaneRequestCompleted:
374          return "presentation_pane_request_completed";
375       case client_events::kUnhandledError:
376          return "unhandled_error";
377       case client_events::kErrorHandlerChanged:
378          return "error_handler_changed";
379       case client_events::kViewerNavigate:
380          return "viewer_navigate";
381       case client_events::kSourceExtendedTypeDetected:
382          return "source_extended_type_detected";
383       case client_events::kShinyViewer:
384          return "shiny_viewer";
385       case client_events::kDebugSourceCompleted:
386          return "debug_source_completed";
387       case client_events::kRmdRenderStarted:
388          return "rmd_render_started";
389       case client_events::kRmdRenderOutput:
390          return "rmd_render_output";
391       case client_events::kRmdRenderCompleted:
392          return "rmd_render_completed";
393       case client_events::kRmdShinyDocStarted:
394          return "rmd_shiny_doc_started";
395       case client_events::kRmdRSConnectDeploymentOutput:
396          return "rsconnect_deployment_output";
397       case client_events::kRmdRSConnectDeploymentCompleted:
398          return "rsconnect_deployment_completed";
399       case client_events::kRmdRSConnectDeploymentFailed:
400          return "rsconnect_deployment_failed";
401       case client_events::kUserPrompt:
402          return "user_prompt";
403       case client_events::kInstallRtools:
404          return "install_r_tools";
405       case client_events::kInstallShiny:
406          return "install_shiny";
407       case client_events::kSuspendAndRestart:
408          return "suspend_and_restart";
409       case client_events::kDataViewChanged:
410          return "data_view_changed";
411       case client_events::kViewFunction:
412          return "view_function";
413       case client_events::kMarkersChanged:
414          return "markers_changed";
415       case client_events::kEnableRStudioConnect:
416          return "enable_rstudio_connect";
417       case client_events::kUpdateGutterMarkers:
418          return "update_gutter_markers";
419       case client_events::kSnippetsChanged:
420          return "snippets_changed";
421       case client_events::kJumpToFunction:
422          return "jump_to_function";
423       case client_events::kCollabEditStarted:
424          return "collab_edit_started";
425       case client_events::kSessionCountChanged:
426          return "session_count_changed";
427       case client_events::kCollabEditEnded:
428          return "collab_edit_ended";
429       case client_events::kProjectUsersChanged:
430          return "project_users_changed";
431       case client_events::kRVersionsChanged:
432          return "r_versions_changed";
433       case client_events::kShinyGadgetDialog:
434          return "shiny_gadget_dialog";
435       case client_events::kRmdParamsReady:
436          return "rmd_params_ready";
437       case client_events::kRegisterUserCommand:
438          return "register_user_command";
439       case client_events::kSendToConsole:
440          return "send_to_console";
441       case client_events::kUserFollowStarted:
442          return "user_follow_started";
443       case client_events::kUserFollowEnded:
444          return "user_follow_ended";
445       case client_events::kProjectAccessRevoked:
446          return "project_access_revoked";
447       case client_events::kCollabEditSaved:
448          return "collab_edit_saved";
449       case client_events::kAddinRegistryUpdated:
450          return "addin_registry_updated";
451       case client_events::kChunkOutput:
452          return "chunk_output";
453       case client_events::kChunkOutputFinished:
454          return "chunk_output_finished";
455       case client_events::kRprofStarted:
456          return "rprof_started";
457       case client_events::kRprofStopped:
458          return "rprof_stopped";
459       case client_events::kRprofCreated:
460          return "rprof_created";
461       case client_events::kEditorCommand:
462          return "editor_command";
463       case client_events::kPreviewRmd:
464          return "preview_rmd";
465       case client_events::kWebsiteFileSaved:
466          return "website_file_saved";
467       case client_events::kChunkPlotRefreshed:
468          return "chunk_plot_refreshed";
469       case client_events::kChunkPlotRefreshFinished:
470          return "chunk_plot_refresh_finished";
471       case client_events::kReloadWithLastChanceSave:
472          return "reload_with_last_chance_save";
473       case client_events::kConnectionUpdated:
474          return "connection_updated";
475       case client_events::kEnableConnections:
476          return "enable_connections";
477       case client_events::kConnectionListChanged:
478          return "connection_list_changed";
479       case client_events::kActiveConnectionsChanged:
480          return "active_connections_changed";
481       case client_events::kConnectionOpened:
482          return "connection_opened";
483       case client_events::kNotebookRangeExecuted:
484          return "notebook_range_executed";
485       case client_events::kChunkExecStateChanged:
486          return "chunk_exec_state_changed";
487       case client_events::kNavigateShinyFrame:
488          return "navigate_shiny_frame";
489       case client_events::kUpdateNewConnectionDialog:
490          return "update_new_connection_dialog";
491       case client_events::kProjectTemplateRegistryUpdated:
492          return "project_template_registry_updated";
493       case client_events::kTerminalSubprocs:
494          return "terminal_subprocs";
495       case client_events::kPackageExtensionIndexingCompleted:
496          return "package_extension_indexing_completed";
497       case client_events::kRStudioAPIShowDialog:
498          return "rstudioapi_show_dialog";
499       case client_events::kRStudioAPIShowDialogCompleted:
500          return "rstudioapi_show_dialog_completed";
501       case client_events::kObjectExplorerEvent:
502          return "object_explorer_event";
503       case client_events::kSendToTerminal:
504          return "send_to_terminal";
505       case client_events::kClearTerminal:
506          return "clear_terminal";
507       case client_events::kAddTerminal:
508          return "add_terminal";
509       case client_events::kActivateTerminal:
510          return "activate_terminal";
511       case client_events::kTerminalCwd:
512          return "terminal_cwd";
513       case client_events::kAdminNotification:
514          return "admin_notification";
515       case client_events::kRequestDocumentSave:
516          return "request_document_save";
517       case client_events::kRequestDocumentSaveCompleted:
518          return "request_document_save_completed";
519       case client_events::kRequestOpenProject:
520          return "request_open_project";
521       case client_events::kOpenFileDialog:
522          return "open_file_dialog";
523       case client_events::kRemoveTerminal:
524          return "remove_terminal";
525       case client_events::kShowPageViewerEvent:
526          return "show_page_viewer";
527       case client_events::kAskSecret:
528          return "ask_secret";
529       case client_events::kTestsStarted:
530          return "tests_started";
531       case client_events::kTestsOutput:
532          return "tests_output";
533       case client_events::kTestsCompleted:
534          return "tests_completed";
535       case client_events::kJobUpdated:
536          return "job_updated";
537       case client_events::kJobRefresh:
538          return "job_refresh";
539       case client_events::kJobOutput:
540          return "job_output";
541       case client_events::kDataOutputCompleted:
542          return "data_output_completed";
543       case client_events::kNewDocumentWithCode:
544          return "new_document_with_code";
545       case client_events::kAvailablePackagesReady:
546          return "available_packages_ready";
547       case client_events::kPlumberViewer:
548          return "plumber_viewer";
549       case client_events::kComputeThemeColors:
550          return "compute_theme_colors";
551       case client_events::kRequestDocumentClose:
552          return "request_document_close";
553       case client_events::kRequestDocumentCloseCompleted:
554          return "request_document_close_completed";
555       case client_events::kExecuteAppCommand:
556          return "execute_app_command";
557       case client_events::kUserStateChanged:
558          return "user_state_changed";
559       case client_events::kHighlightUi:
560          return "highlight_ui";
561       case client_events::kReplaceResult:
562          return "replace_result";
563       case client_events::kReplaceUpdated:
564          return "replace_updated";
565       case client_events::kTutorialCommand:
566          return "tutorial_command";
567       case client_events::kTutorialLaunch:
568          return "tutorial_launch";
569       case client_events::kReticulateEvent:
570          return "reticulate_event";
571       case client_events::kEnvironmentChanged:
572          return "environment_changed";
573       case client_events::kRStudioApiRequest:
574          return "rstudioapi_request";
575       case client_events::kDocumentCloseAllNoSave:
576          return "document_close_all_no_save";
577       case client_events::kMemoryUsageChanged:
578          return "memory_usage_changed";
579       case client_events::kCommandCallbacksChanged:
580          return "command_callbacks_changed";
581       case client_events::kConsoleActivate:
582          return "console_activate";
583       case client_events::kJobsActivate:
584          return "jobs_activate";
585       default:
586          LOG_WARNING_MESSAGE("unexpected event type: " +
587                              safe_convert::numberToString(type_));
588          return "";
589    }
590 }
591 
showEditorEvent(const std::string & content,bool isRCode,bool lineWrapping)592 ClientEvent showEditorEvent(const std::string& content,
593                             bool isRCode,
594                             bool lineWrapping)
595 {
596    json::Object data;
597    data["content"] = content;
598    data["is_r_code"] = isRCode;
599    data["line_wrapping"] = lineWrapping;
600    return ClientEvent(client_events::kShowEditor, data);
601 }
602 
browseUrlEvent(const std::string & url,const std::string & window)603 ClientEvent browseUrlEvent(const std::string& url, const std::string& window)
604 {
605    json::Object browseURLInfo;
606    browseURLInfo["url"] = url;
607    browseURLInfo["window"] = window;
608    return ClientEvent(client_events::kBrowseUrl, browseURLInfo);
609 }
610 
611 
showErrorMessageEvent(const std::string & title,const std::string & message)612 ClientEvent showErrorMessageEvent(const std::string& title,
613                                   const std::string& message)
614 {
615    json::Object errorMessage;
616    errorMessage["title"] = title;
617    errorMessage["message"] = message;
618    return ClientEvent(client_events::kShowErrorMessage, errorMessage);
619 }
620 
621 
622 
623 
624 } // namespace session
625 } // namespace rstudio
626