xref: /haiku/src/apps/debugger/user_interface/report/ReportUserInterface.cpp (revision 56430ad8002b8fd1ac69b590e9cc130de6d9e852)
1 /*
2  * Copyright 2015, Rene Gollent, rene@gollent.com.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "ReportUserInterface.h"
8 
9 #include <stdio.h>
10 
11 #include <Entry.h>
12 #include <FindDirectory.h>
13 #include <Path.h>
14 
15 #include <AutoLocker.h>
16 
17 #include "MessageCodes.h"
18 #include "UiUtils.h"
19 
20 
21 ReportUserInterface::ReportUserInterface(thread_id targetThread,
22 	const char* reportPath)
23 	:
24 	fTeam(NULL),
25 	fListener(NULL),
26 	fTargetThread(targetThread),
27 	fReportPath(reportPath),
28 	fShowSemaphore(-1),
29 	fReportSemaphore(-1),
30 	fShown(false),
31 	fTerminating(false)
32 {
33 }
34 
35 
36 ReportUserInterface::~ReportUserInterface()
37 {
38 	if (fShowSemaphore >= 0)
39 		delete_sem(fShowSemaphore);
40 
41 	fTeam->RemoveListener(this);
42 }
43 
44 
45 const char*
46 ReportUserInterface::ID() const
47 {
48 	return "ReportUserInterface";
49 }
50 
51 
52 status_t
53 ReportUserInterface::Init(Team* team, UserInterfaceListener* listener)
54 {
55 	fShowSemaphore = create_sem(0, "show report");
56 	if (fShowSemaphore < 0)
57 		return fShowSemaphore;
58 
59 	fReportSemaphore = create_sem(0, "report generator wait");
60 	if (fReportSemaphore < 0)
61 		return fReportSemaphore;
62 
63 	fTeam = team;
64 	fListener = listener;
65 
66 	fTeam->AddListener(this);
67 
68 	return B_OK;
69 }
70 
71 
72 void
73 ReportUserInterface::Show()
74 {
75 	fShown = true;
76 	release_sem(fShowSemaphore);
77 }
78 
79 
80 void
81 ReportUserInterface::Terminate()
82 {
83 	fTerminating = true;
84 }
85 
86 
87 bool
88 ReportUserInterface::IsInteractive() const
89 {
90 	return false;
91 }
92 
93 
94 status_t
95 ReportUserInterface::LoadSettings(const TeamUiSettings* settings)
96 {
97 	return B_OK;
98 }
99 
100 
101 status_t
102 ReportUserInterface::SaveSettings(TeamUiSettings*& settings) const
103 {
104 	return B_OK;
105 }
106 
107 
108 void
109 ReportUserInterface::NotifyUser(const char* title, const char* message,
110 	user_notification_type type)
111 {
112 }
113 
114 
115 void
116 ReportUserInterface::NotifyBackgroundWorkStatus(const char* message)
117 {
118 }
119 
120 
121 int32
122 ReportUserInterface::SynchronouslyAskUser(const char* title,
123 	const char* message, const char* choice1, const char* choice2,
124 	const char* choice3)
125 {
126 	return -1;
127 }
128 
129 
130 status_t
131 ReportUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref)
132 {
133 	return B_UNSUPPORTED;
134 }
135 
136 
137 void
138 ReportUserInterface::Run()
139 {
140 	// Wait for the Show() semaphore to be released.
141 	status_t error;
142 	do {
143 		error = acquire_sem(fShowSemaphore);
144 	} while (error == B_INTERRUPTED);
145 
146 	if (error != B_OK)
147 		return;
148 
149 	bool waitNeeded = false;
150 	if (fTargetThread > 0) {
151 		AutoLocker< ::Team> teamLocker(fTeam);
152 		::Thread* thread = fTeam->ThreadByID(fTargetThread);
153 		if (thread == NULL)
154 			waitNeeded = true;
155 		else if (thread->State() != THREAD_STATE_STOPPED) {
156 			waitNeeded = true;
157 			fListener->ThreadActionRequested(fTargetThread, MSG_THREAD_STOP);
158 		}
159 	}
160 
161 	if (waitNeeded) {
162 		do {
163 			error = acquire_sem(fShowSemaphore);
164 		} while (error == B_INTERRUPTED);
165 
166 		if (error != B_OK)
167 			return;
168 	}
169 
170 	entry_ref ref;
171 	if (fReportPath != NULL && fReportPath[0] == '/') {
172 		error = get_ref_for_path(fReportPath, &ref);
173 	} else {
174 		char filename[B_FILE_NAME_LENGTH];
175 		if (fReportPath != NULL)
176 			strlcpy(filename, fReportPath, sizeof(filename));
177 		else
178 			UiUtils::ReportNameForTeam(fTeam, filename, sizeof(filename));
179 
180 		BPath path;
181 		error = find_directory(B_DESKTOP_DIRECTORY, &path);
182 		if (error == B_OK)
183 			error = path.Append(filename);
184 		if (error == B_OK)
185 			error = get_ref_for_path(path.Path(), &ref);
186 	}
187 
188 	if (error != B_OK)
189 		printf("Unable to get ref for report path %s\n", strerror(error));
190 	else {
191 		fListener->DebugReportRequested(&ref);
192 
193 		do {
194 			error = acquire_sem(fReportSemaphore);
195 		} while (error == B_INTERRUPTED);
196 	}
197 
198 	fListener->UserInterfaceQuitRequested(
199 		UserInterfaceListener::QUIT_OPTION_ASK_KILL_TEAM);
200 }
201 
202 
203 void
204 ReportUserInterface::ThreadAdded(const Team::ThreadEvent& event)
205 {
206 	::Thread* thread = event.GetThread();
207 	if (thread->ID() != fTargetThread)
208 		return;
209 
210 	if (thread->State() != THREAD_STATE_STOPPED)
211 		fListener->ThreadActionRequested(thread->ID(), MSG_THREAD_STOP);
212 	else
213 		release_sem(fShowSemaphore);
214 }
215 
216 
217 void
218 ReportUserInterface::ThreadStateChanged(const Team::ThreadEvent& event)
219 {
220 	::Thread* thread = event.GetThread();
221 	if (thread->ID() != fTargetThread)
222 		return;
223 	else if (thread->State() == THREAD_STATE_STOPPED)
224 		release_sem(fShowSemaphore);
225 }
226 
227 
228 void
229 ReportUserInterface::DebugReportChanged(const Team::DebugReportEvent& event)
230 {
231 	printf("Debug report saved to %s\n", event.GetReportPath());
232 	release_sem(fReportSemaphore);
233 }
234