aboutsummaryrefslogtreecommitdiffstats
path: root/support
diff options
context:
space:
mode:
authorPaul Rouget <me@paulrouget.com>2020-08-03 17:23:30 +0200
committerPaul Rouget <me@paulrouget.com>2020-08-03 17:36:52 +0200
commit52f01a8a1491584f0f8915fbcd4f1473a3fe64bf (patch)
tree5670e3a31760888d92b96109f6833a2c649c77c9 /support
parent0c00022ae04d9116c4a31b389fc03d843ff368bd (diff)
downloadservo-52f01a8a1491584f0f8915fbcd4f1473a3fe64bf.tar.gz
servo-52f01a8a1491584f0f8915fbcd4f1473a3fe64bf.zip
UWP: Crash report UI
Diffstat (limited to 'support')
-rw-r--r--support/hololens/ServoApp/BrowserPage.cpp82
-rw-r--r--support/hololens/ServoApp/BrowserPage.h6
-rw-r--r--support/hololens/ServoApp/BrowserPage.xaml16
-rw-r--r--support/hololens/ServoApp/ServoControl/Servo.cpp48
-rw-r--r--support/hololens/ServoApp/ServoControl/Servo.h4
-rw-r--r--support/hololens/ServoApp/ServoControl/ServoControl.cpp50
-rw-r--r--support/hololens/ServoApp/ServoControl/ServoControl.h10
-rw-r--r--support/hololens/ServoApp/ServoControl/ServoControl.idl1
-rw-r--r--support/hololens/ServoApp/Strings/en-US/Resources.resw15
9 files changed, 196 insertions, 36 deletions
diff --git a/support/hololens/ServoApp/BrowserPage.cpp b/support/hololens/ServoApp/BrowserPage.cpp
index 095617f6dea..d3f738427c6 100644
--- a/support/hololens/ServoApp/BrowserPage.cpp
+++ b/support/hololens/ServoApp/BrowserPage.cpp
@@ -19,6 +19,7 @@ using namespace winrt::Windows::ApplicationModel::Resources;
using namespace winrt::Windows::UI::Notifications;
using namespace winrt::Windows::Data::Json;
using namespace winrt::Windows::Data::Xml::Dom;
+using namespace winrt::Windows::Storage;
using namespace winrt::servo;
namespace winrt::ServoApp::implementation {
@@ -37,15 +38,19 @@ void BrowserPage::BindServoEvents() {
backButton().IsEnabled(back);
forwardButton().IsEnabled(forward);
});
+ servoView().OnServoPanic([=](const auto &, hstring /*message*/) {
+ mPanicking = true;
+ CheckCrashReport();
+ });
servoView().OnLoadStarted([=] {
urlbarLoadingIndicator().IsActive(true);
transientLoadingIndicator().IsIndeterminate(true);
-
reloadButton().IsEnabled(false);
reloadButton().Visibility(Visibility::Collapsed);
stopButton().IsEnabled(true);
stopButton().Visibility(Visibility::Visible);
devtoolsButton().IsEnabled(true);
+ CheckCrashReport();
});
servoView().OnLoadEnded([=] {
urlbarLoadingIndicator().IsActive(false);
@@ -297,24 +302,59 @@ void BrowserPage::OnDevtoolsMessage(DevtoolsMessageLevel level, hstring source,
});
}
+void BrowserPage::CheckCrashReport() {
+ Concurrency::create_task([=] {
+ auto pref = servo::Servo::GetPref(L"shell.crash_reporter.enabled");
+ bool reporter_enabled = unbox_value<bool>(std::get<1>(pref));
+ auto storageFolder = ApplicationData::Current().LocalFolder();
+ bool file_exist =
+ storageFolder.TryGetItemAsync(L"crash-report.txt").get() != nullptr;
+ if (reporter_enabled && file_exist) {
+ auto crash_file = storageFolder.GetFileAsync(L"crash-report.txt").get();
+ auto content = FileIO::ReadTextAsync(crash_file).get();
+ Dispatcher().RunAsync(CoreDispatcherPriority::High, [=] {
+ auto resourceLoader = ResourceLoader::GetForCurrentView();
+ auto message = resourceLoader.GetString(mPanicking ? L"crash/Happening"
+ : L"crash/Happened");
+ crashTabMessage().Text(message);
+ crashReport().Text(content);
+ crashTab().Visibility(Visibility::Visible);
+ crashTab().IsSelected(true);
+ ShowToolbox();
+ });
+ } else {
+ Dispatcher().RunAsync(CoreDispatcherPriority::High, [=] {
+ crashTab().Visibility(Visibility::Collapsed);
+ devtoolsTabConsole().IsSelected(true);
+ });
+ }
+ });
+}
+
+void BrowserPage::OnDismissCrashReport(IInspectable const &,
+ RoutedEventArgs const &) {
+ Concurrency::create_task([=] {
+ auto storageFolder = ApplicationData::Current().LocalFolder();
+ auto crash_file = storageFolder.GetFileAsync(L"crash-report.txt").get();
+ crash_file.DeleteAsync().get();
+ });
+ HideToolbox();
+}
+
+void BrowserPage::OnSubmitCrashReport(IInspectable const &,
+ RoutedEventArgs const &) {
+ // FIXME
+}
+
void BrowserPage::OnDevtoolsDetached() {}
-void BrowserPage::OnDevtoolsButtonClicked(IInspectable const &,
- RoutedEventArgs const &) {
+void BrowserPage::ShowToolbox() {
if (toolbox().Visibility() == Visibility::Visible) {
- prefList().Children().Clear();
- toolbox().Visibility(Visibility::Collapsed);
- ClearConsole();
- if (mDevtoolsClient != nullptr) {
- mDevtoolsClient->Stop();
- }
return;
}
-
toolbox().Visibility(Visibility::Visible);
-
+ CheckCrashReport();
BuildPrefList();
-
auto resourceLoader = ResourceLoader::GetForCurrentView();
if (mDevtoolsStatus == DevtoolsStatus::Running) {
hstring port = to_hstring(mDevtoolsPort);
@@ -337,6 +377,24 @@ void BrowserPage::OnDevtoolsButtonClicked(IInspectable const &,
}
}
+void BrowserPage::HideToolbox() {
+ prefList().Children().Clear();
+ toolbox().Visibility(Visibility::Collapsed);
+ ClearConsole();
+ if (mDevtoolsClient != nullptr) {
+ mDevtoolsClient->Stop();
+ }
+}
+
+void BrowserPage::OnDevtoolsButtonClicked(IInspectable const &,
+ RoutedEventArgs const &) {
+ if (toolbox().Visibility() == Visibility::Visible) {
+ HideToolbox();
+ } else {
+ ShowToolbox();
+ }
+}
+
void BrowserPage::OnJSInputEdited(IInspectable const &,
Input::KeyRoutedEventArgs const &e) {
if (e.Key() == Windows::System::VirtualKey::Enter) {
diff --git a/support/hololens/ServoApp/BrowserPage.h b/support/hololens/ServoApp/BrowserPage.h
index 2f800a516ac..a5ad43b4286 100644
--- a/support/hololens/ServoApp/BrowserPage.h
+++ b/support/hololens/ServoApp/BrowserPage.h
@@ -41,6 +41,8 @@ public:
void Shutdown();
void LoadFXRURI(Uri uri);
void SetArgs(hstring);
+ void OnDismissCrashReport(IInspectable const &, RoutedEventArgs const &);
+ void OnSubmitCrashReport(IInspectable const &, RoutedEventArgs const &);
void OnMediaControlsPlayClicked(IInspectable const &,
RoutedEventArgs const &);
void OnMediaControlsPauseClicked(IInspectable const &,
@@ -55,11 +57,15 @@ public:
private:
void SetTransientMode(bool);
void UpdatePref(ServoApp::Pref, Controls::Control);
+ void CheckCrashReport();
void BindServoEvents();
void BuildPrefList();
+ void ShowToolbox();
+ void HideToolbox();
DevtoolsStatus mDevtoolsStatus = DevtoolsStatus::Stopped;
unsigned int mDevtoolsPort = 0;
hstring mDevtoolsToken;
+ bool mPanicking = false;
std::unique_ptr<servo::DevtoolsClient> mDevtoolsClient;
Collections::IObservableVector<IInspectable> mLogs;
};
diff --git a/support/hololens/ServoApp/BrowserPage.xaml b/support/hololens/ServoApp/BrowserPage.xaml
index 9b73f29527b..d85947b8807 100644
--- a/support/hololens/ServoApp/BrowserPage.xaml
+++ b/support/hololens/ServoApp/BrowserPage.xaml
@@ -150,7 +150,7 @@
</Button>
</Grid>
</muxc:TabView.TabStripFooter>
- <muxc:TabViewItem x:Uid="devtoolsTabConsole" IsClosable="False">
+ <muxc:TabViewItem x:Uid="devtoolsTabConsole" x:Name="devtoolsTabConsole" IsClosable="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
@@ -199,6 +199,20 @@
</ScrollViewer>
</Grid>
</muxc:TabViewItem>
+ <muxc:TabViewItem x:Uid="crashTab" x:Name="crashTab" IsClosable="False" Visibility="Collapsed">
+ <Grid VerticalAlignment="Stretch">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <StackPanel Grid.Row="0" Padding="4" Orientation="Horizontal">
+ <TextBlock VerticalAlignment="Center" x:Name="crashTabMessage"></TextBlock>
+ <Button IsTabStop="true" x:Uid="SubmitCrashReportButton" Margin="4" Click="OnSubmitCrashReport"/>
+ <Button IsTabStop="true" x:Uid="DismissCrashReportButton" Margin="4" Click="OnDismissCrashReport"/>
+ </StackPanel>
+ <TextBox Grid.Row="1" TextWrapping="Wrap" IsTabStop="true" x:Name="crashReport" AcceptsReturn="True" IsSpellCheckEnabled="False" Margin="3"/>
+ </Grid>
+ </muxc:TabViewItem>
</muxc:TabView>
<ProgressBar x:Name="transientLoadingIndicator" Visibility="Collapsed" Grid.Row="3"/>
<CommandBar Grid.Row="4" x:Name="mediaControls" Visibility="Collapsed">
diff --git a/support/hololens/ServoApp/ServoControl/Servo.cpp b/support/hololens/ServoApp/ServoControl/Servo.cpp
index 3496610ed86..4e3eeedf981 100644
--- a/support/hololens/ServoApp/ServoControl/Servo.cpp
+++ b/support/hololens/ServoApp/ServoControl/Servo.cpp
@@ -21,8 +21,10 @@ void on_title_changed(const char *title) {
sServo->Delegate().OnServoTitleChanged(char2hstring(title));
}
-void on_url_changed(const char *url) {
- sServo->Delegate().OnServoURLChanged(char2hstring(url));
+void on_url_changed(const char *curl) {
+ auto url = char2hstring(curl);
+ sServo->CurrentUrl(url);
+ sServo->Delegate().OnServoURLChanged(url);
}
void wakeup() { sServo->Delegate().WakeUp(); }
@@ -35,12 +37,46 @@ void on_animating_changed(bool aAnimating) {
sServo->Delegate().OnServoAnimatingChanged(aAnimating);
}
-void on_panic(const char *backtrace) {
+void on_panic(const char *cbacktrace) {
+
if (sLogHandle != INVALID_HANDLE_VALUE) {
CloseHandle(sLogHandle);
sLogHandle = INVALID_HANDLE_VALUE;
}
- throw hresult_error(E_FAIL, char2hstring(backtrace));
+
+ auto backtrace = char2hstring(cbacktrace);
+
+ try {
+ // Making all sync operations sync, as we are crashing.
+ auto storageFolder = ApplicationData::Current().LocalFolder();
+ auto stdout_txt = storageFolder.GetFileAsync(L"stdout.txt").get();
+ auto crash_txt =
+ storageFolder
+ .CreateFileAsync(L"crash-report.txt",
+ CreationCollisionOption::ReplaceExisting)
+ .get();
+ auto out = FileIO::ReadTextAsync(stdout_txt).get();
+ FileIO::WriteTextAsync(crash_txt, L"--- CUSTOM MESSAGE ---\r\n").get();
+ FileIO::AppendTextAsync(crash_txt,
+ L"Feel free to add details here before reporting")
+ .get();
+ FileIO::AppendTextAsync(
+ crash_txt, L"\r\n--- CURRENT URL (remove if sensitive) ---\r\n")
+ .get();
+ FileIO::AppendTextAsync(crash_txt, sServo->CurrentUrl()).get();
+ FileIO::AppendTextAsync(crash_txt, L"\r\n--- BACKTRACE ---\r\n").get();
+ FileIO::AppendTextAsync(crash_txt, backtrace).get();
+ FileIO::AppendTextAsync(crash_txt, L"\r\n--- STDOUT ---\r\n").get();
+ FileIO::AppendTextAsync(crash_txt, out).get();
+ FileIO::AppendTextAsync(crash_txt, L"\r\n").get();
+ } catch (...) {
+ log(L"Failed to log panic to crash report");
+ }
+
+ // If this is happening in the GL thread, the app can continue running.
+ // So let's show the crash report:
+ sServo->Delegate().OnServoPanic(backtrace);
+ throw hresult_error(E_FAIL, backtrace);
}
void on_ime_show(const char *text, int32_t x, int32_t y, int32_t width,
@@ -371,9 +407,7 @@ std::vector<Servo::PrefTuple> Servo::GetPrefs() {
return {};
}
auto prefs = capi::get_prefs();
- std::vector<
- std::tuple<hstring, winrt::Windows::Foundation::IInspectable, bool>>
- vec;
+ std::vector<PrefTuple> vec;
for (auto i = 0; i < prefs.len; i++) {
auto pref = WrapPref(prefs.list[i]);
vec.push_back(pref);
diff --git a/support/hololens/ServoApp/ServoControl/Servo.h b/support/hololens/ServoApp/ServoControl/Servo.h
index db2ade2e14e..fb2c2f5fb22 100644
--- a/support/hololens/ServoApp/ServoControl/Servo.h
+++ b/support/hololens/ServoApp/ServoControl/Servo.h
@@ -31,6 +31,8 @@ public:
float, ServoDelegate &, bool);
~Servo();
ServoDelegate &Delegate() { return mDelegate; }
+ hstring CurrentUrl() { return mUrl; }
+ void CurrentUrl(hstring url) { mUrl = url; }
typedef std::tuple<hstring, winrt::Windows::Foundation::IInspectable, bool>
PrefTuple;
@@ -96,6 +98,7 @@ public:
private:
ServoDelegate &mDelegate;
+ hstring mUrl;
GLsizei mWindowWidth;
GLsizei mWindowHeight;
static void SaveUserPref(PrefTuple);
@@ -115,6 +118,7 @@ public:
virtual void OnServoURLChanged(hstring) = 0;
virtual bool OnServoAllowNavigation(hstring) = 0;
virtual void OnServoAnimatingChanged(bool) = 0;
+ virtual void OnServoPanic(hstring) = 0;
virtual void OnServoIMEShow(hstring text, int32_t x, int32_t y, int32_t width,
int32_t height) = 0;
virtual void OnServoIMEHide() = 0;
diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.cpp b/support/hololens/ServoApp/ServoControl/ServoControl.cpp
index 9898f0ea258..b2ff048248f 100644
--- a/support/hololens/ServoApp/ServoControl/ServoControl.cpp
+++ b/support/hololens/ServoApp/ServoControl/ServoControl.cpp
@@ -418,34 +418,48 @@ void ServoControl::Loop() {
while (true) {
EnterCriticalSection(&mGLLock);
- while (mTasks.size() == 0 && !mAnimating && mLooping) {
- SleepConditionVariableCS(&mGLCondVar, &mGLLock, INFINITE);
- }
- if (!mLooping) {
+ try {
+ while (mTasks.size() == 0 && !mAnimating && mLooping) {
+ SleepConditionVariableCS(&mGLCondVar, &mGLLock, INFINITE);
+ }
+ if (!mLooping) {
+ LeaveCriticalSection(&mGLLock);
+ break;
+ }
+ for (auto &&task : mTasks) {
+ task();
+ }
+ mTasks.clear();
LeaveCriticalSection(&mGLLock);
- break;
- }
- for (auto &&task : mTasks) {
- task();
+ mServo->PerformUpdates();
+ } catch (hresult_error const &e) {
+ log(L"GL Thread exception: %s", e.message().c_str());
+ throw e;
+ } catch (...) {
+ log(L"GL Thread exception");
+ throw winrt::hresult_error(E_FAIL, L"GL Thread exception");
}
- mTasks.clear();
- LeaveCriticalSection(&mGLLock);
- mServo->PerformUpdates();
}
mServo->DeInit();
}
void ServoControl::StartRenderLoop() {
if (mLooping) {
-#if defined _DEBUG
throw winrt::hresult_error(E_FAIL, L"GL thread is already looping");
-#else
- return;
-#endif
}
mLooping = true;
log(L"BrowserPage::StartRenderLoop(). UI thread: %i", GetCurrentThreadId());
- auto task = Concurrency::create_task([=] { Loop(); });
+ auto task = Concurrency::create_task([=] {
+ try {
+ Loop();
+ } catch (...) {
+ // Do our best to recover. Exception has been logged at that point.
+ mLooping = false;
+ mLoopTask.reset();
+ mServo.reset();
+ LeaveCriticalSection(&mGLLock);
+ }
+ });
mLoopTask = std::make_unique<Concurrency::task<void>>(task);
}
@@ -502,6 +516,10 @@ bool ServoControl::OnServoAllowNavigation(hstring uri) {
return !mTransient;
}
+void ServoControl::OnServoPanic(hstring backtrace) {
+ RunOnUIThread([=] { mOnServoPanic(*this, backtrace); });
+}
+
void ServoControl::OnServoAnimatingChanged(bool animating) {
EnterCriticalSection(&mGLLock);
mAnimating = animating;
diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.h b/support/hololens/ServoApp/ServoControl/ServoControl.h
index bf53f0e6487..be1f8090776 100644
--- a/support/hololens/ServoApp/ServoControl/ServoControl.h
+++ b/support/hololens/ServoApp/ServoControl/ServoControl.h
@@ -100,6 +100,14 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
mOnTitleChangedEvent.remove(token);
}
+ winrt::event_token
+ OnServoPanic(Windows::Foundation::EventHandler<hstring> const &handler) {
+ return mOnServoPanic.add(handler);
+ };
+ void OnServoPanic(winrt::event_token const &token) noexcept {
+ mOnServoPanic.remove(token);
+ }
+
winrt::event_token OnHistoryChanged(HistoryChangedDelegate const &handler) {
return mOnHistoryChangedEvent.add(handler);
};
@@ -173,6 +181,7 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
virtual void OnServoURLChanged(winrt::hstring);
virtual bool OnServoAllowNavigation(winrt::hstring);
virtual void OnServoAnimatingChanged(bool);
+ virtual void OnServoPanic(hstring);
virtual void OnServoIMEHide();
virtual void OnServoIMEShow(hstring text, int32_t, int32_t, int32_t, int32_t);
virtual void OnServoMediaSessionMetadata(winrt::hstring, winrt::hstring,
@@ -193,6 +202,7 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
private:
winrt::event<Windows::Foundation::EventHandler<hstring>> mOnURLChangedEvent;
winrt::event<Windows::Foundation::EventHandler<hstring>> mOnTitleChangedEvent;
+ winrt::event<Windows::Foundation::EventHandler<hstring>> mOnServoPanic;
winrt::event<HistoryChangedDelegate> mOnHistoryChangedEvent;
winrt::event<DevtoolsStatusChangedDelegate> mOnDevtoolsStatusChangedEvent;
winrt::event<EventDelegate> mOnLoadStartedEvent;
diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.idl b/support/hololens/ServoApp/ServoControl/ServoControl.idl
index 33e7629170c..fe83d535322 100644
--- a/support/hololens/ServoApp/ServoControl/ServoControl.idl
+++ b/support/hololens/ServoApp/ServoControl/ServoControl.idl
@@ -39,6 +39,7 @@ namespace ServoApp {
event DevtoolsStatusChangedDelegate OnDevtoolsStatusChanged;
event HistoryChangedDelegate OnHistoryChanged;
event Windows.Foundation.EventHandler<String> OnTitleChanged;
+ event Windows.Foundation.EventHandler<String> OnServoPanic;
event Windows.Foundation.EventHandler<String> OnURLChanged;
event MediaSessionMetadataDelegate OnMediaSessionMetadata;
event Windows.Foundation.EventHandler<int> OnMediaSessionPlaybackStateChange;
diff --git a/support/hololens/ServoApp/Strings/en-US/Resources.resw b/support/hololens/ServoApp/Strings/en-US/Resources.resw
index 86b9d2558e4..717ffbff23b 100644
--- a/support/hololens/ServoApp/Strings/en-US/Resources.resw
+++ b/support/hololens/ServoApp/Strings/en-US/Resources.resw
@@ -114,6 +114,21 @@
<data name="devtoolsTabPrefs.[using:Microsoft.UI.Xaml.Controls]TabViewItem.Header" xml:space="preserve">
<value>Preferences</value>
</data>
+ <data name="crashTab.[using:Microsoft.UI.Xaml.Controls]TabViewItem.Header" xml:space="preserve">
+ <value>Crash Report</value>
+ </data>
+ <data name="crash.Happening" xml:space="preserve">
+ <value>Internal crash detected. Application might be unstable:</value>
+ </data>
+ <data name="crash.Happened" xml:space="preserve">
+ <value>Internal crash was detected during last run:</value>
+ </data>
+ <data name="SubmitCrashReportButton.Content" xml:space="preserve">
+ <value>Send crash report</value>
+ </data>
+ <data name="DismissCrashReportButton.Content" xml:space="preserve">
+ <value>Dismiss</value>
+ </data>
<data name="preferenceSearchbox.PlaceholderText" xml:space="preserve">
<value>Search Preferences</value>
</data>