fix: do not run dialog callback inside transaction commit (#31606)

This commit is contained in:
Cheng Zhao 2021-11-02 06:08:31 +09:00 committed by GitHub
parent 1e618ef06c
commit c4d35cd18c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 17 deletions

View file

@ -16,6 +16,9 @@
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "shell/browser/native_window.h"
#include "shell/common/gin_converters/file_path_converter.h"
@ -290,6 +293,27 @@ void ReadDialogPaths(NSOpenPanel* dialog, std::vector<base::FilePath>* paths) {
ReadDialogPathsWithBookmarks(dialog, paths, &ignored_bookmarks);
}
void ResolvePromiseInNextTick(gin_helper::Promise<v8::Local<v8::Value>> promise,
v8::Local<v8::Value> value) {
// The completionHandler runs inside a transaction commit, and we should
// not do any runModal inside it. However since we can not control what
// users will run in the microtask, we have to delay the resolution until
// next tick, otherwise crash like this may happen:
// https://github.com/electron/electron/issues/26884
base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
[](gin_helper::Promise<v8::Local<v8::Value>> promise,
v8::Global<v8::Value> global) {
v8::Isolate* isolate = promise.isolate();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Value> value = global.Get(isolate);
promise.Resolve(value);
},
std::move(promise), v8::Global<v8::Value>(promise.isolate(), value)));
}
} // namespace
bool ShowOpenDialogSync(const DialogSettings& settings,
@ -320,7 +344,6 @@ void OpenDialogCompletion(int chosen,
#if defined(MAS_BUILD)
dict.Set("bookmarks", std::vector<std::string>());
#endif
promise.Resolve(dict);
} else {
std::vector<base::FilePath> paths;
dict.Set("canceled", false);
@ -336,8 +359,9 @@ void OpenDialogCompletion(int chosen,
ReadDialogPaths(dialog, &paths);
dict.Set("filePaths", paths);
#endif
promise.Resolve(dict);
}
ResolvePromiseInNextTick(promise.As<v8::Local<v8::Value>>(),
dict.GetHandle());
}
void ShowOpenDialog(const DialogSettings& settings,
@ -410,7 +434,8 @@ void SaveDialogCompletion(int chosen,
}
#endif
}
promise.Resolve(dict);
ResolvePromiseInNextTick(promise.As<v8::Local<v8::Value>>(),
dict.GetHandle());
}
void ShowSaveDialog(const DialogSettings& settings,