chore: make util::Promise a move-only type (#17071)

This commit is contained in:
Cheng Zhao 2019-02-21 12:32:44 +00:00 committed by GitHub
parent a40d826b11
commit 32a4de4a68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 325 additions and 260 deletions

View file

@ -533,12 +533,11 @@ int ImportIntoCertStore(CertificateManagerModel* model,
} }
#endif #endif
void OnIconDataAvailable(scoped_refptr<util::Promise> promise, void OnIconDataAvailable(util::Promise promise, gfx::Image* icon) {
gfx::Image* icon) {
if (icon && !icon->IsEmpty()) { if (icon && !icon->IsEmpty()) {
promise->Resolve(*icon); promise.Resolve(*icon);
} else { } else {
promise->RejectWithErrorMessage("Failed to get file icon."); promise.RejectWithErrorMessage("Failed to get file icon.");
} }
} }
@ -1126,7 +1125,8 @@ JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
v8::Local<v8::Promise> App::GetFileIcon(const base::FilePath& path, v8::Local<v8::Promise> App::GetFileIcon(const base::FilePath& path,
mate::Arguments* args) { mate::Arguments* args) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
base::FilePath normalized_path = path.NormalizePathSeparators(); base::FilePath normalized_path = path.NormalizePathSeparators();
IconLoader::IconSize icon_size; IconLoader::IconSize icon_size;
@ -1143,13 +1143,14 @@ v8::Local<v8::Promise> App::GetFileIcon(const base::FilePath& path,
gfx::Image* icon = gfx::Image* icon =
icon_manager->LookupIconFromFilepath(normalized_path, icon_size); icon_manager->LookupIconFromFilepath(normalized_path, icon_size);
if (icon) { if (icon) {
promise->Resolve(*icon); promise.Resolve(*icon);
} else { } else {
icon_manager->LoadIcon(normalized_path, icon_size, icon_manager->LoadIcon(
base::Bind(&OnIconDataAvailable, promise), normalized_path, icon_size,
base::BindOnce(&OnIconDataAvailable, std::move(promise)),
&cancelable_task_tracker_); &cancelable_task_tracker_);
} }
return promise->GetHandle(); return handle;
} }
std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) { std::vector<mate::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
@ -1198,30 +1199,30 @@ v8::Local<v8::Value> App::GetGPUFeatureStatus(v8::Isolate* isolate) {
v8::Local<v8::Promise> App::GetGPUInfo(v8::Isolate* isolate, v8::Local<v8::Promise> App::GetGPUInfo(v8::Isolate* isolate,
const std::string& info_type) { const std::string& info_type) {
auto* const gpu_data_manager = content::GpuDataManagerImpl::GetInstance(); auto* const gpu_data_manager = content::GpuDataManagerImpl::GetInstance();
scoped_refptr<util::Promise> promise = new util::Promise(isolate); util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
if (info_type != "basic" && info_type != "complete") { if (info_type != "basic" && info_type != "complete") {
promise->RejectWithErrorMessage( promise.RejectWithErrorMessage(
"Invalid info type. Use 'basic' or 'complete'"); "Invalid info type. Use 'basic' or 'complete'");
return promise->GetHandle(); return handle;
} }
std::string reason; std::string reason;
if (!gpu_data_manager->GpuAccessAllowed(&reason)) { if (!gpu_data_manager->GpuAccessAllowed(&reason)) {
promise->RejectWithErrorMessage("GPU access not allowed. Reason: " + promise.RejectWithErrorMessage("GPU access not allowed. Reason: " + reason);
reason); return handle;
return promise->GetHandle();
} }
auto* const info_mgr = GPUInfoManager::GetInstance(); auto* const info_mgr = GPUInfoManager::GetInstance();
if (info_type == "complete") { if (info_type == "complete") {
#if defined(OS_WIN) || defined(OS_MACOSX) #if defined(OS_WIN) || defined(OS_MACOSX)
info_mgr->FetchCompleteInfo(promise); info_mgr->FetchCompleteInfo(std::move(promise));
#else #else
info_mgr->FetchBasicInfo(promise); info_mgr->FetchBasicInfo(std::move(promise));
#endif #endif
} else /* (info_type == "basic") */ { } else /* (info_type == "basic") */ {
info_mgr->FetchBasicInfo(promise); info_mgr->FetchBasicInfo(std::move(promise));
} }
return promise->GetHandle(); return handle;
} }
static void RemoveNoSandboxSwitch(base::CommandLine* command_line) { static void RemoveNoSandboxSwitch(base::CommandLine* command_line) {

View file

@ -66,74 +66,73 @@ scoped_refptr<TracingController::TraceDataEndpoint> GetTraceDataEndpoint(
result_file_path, base::Bind(callback, result_file_path)); result_file_path, base::Bind(callback, result_file_path));
} }
void OnRecordingStopped(scoped_refptr<atom::util::Promise> promise, void OnRecordingStopped(const atom::util::CopyablePromise& promise,
const base::FilePath& path) { const base::FilePath& path) {
promise->Resolve(path); promise.GetPromise().Resolve(path);
} }
v8::Local<v8::Promise> StopRecording(v8::Isolate* isolate, v8::Local<v8::Promise> StopRecording(v8::Isolate* isolate,
const base::FilePath& path) { const base::FilePath& path) {
scoped_refptr<atom::util::Promise> promise = new atom::util::Promise(isolate); atom::util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
TracingController::GetInstance()->StopTracing( // TODO(zcbenz): Remove the use of CopyablePromise when the
GetTraceDataEndpoint(path, base::Bind(&OnRecordingStopped, promise))); // CreateFileEndpoint API accepts OnceCallback.
TracingController::GetInstance()->StopTracing(GetTraceDataEndpoint(
return promise->GetHandle(); path,
base::Bind(&OnRecordingStopped, atom::util::CopyablePromise(promise))));
return handle;
} }
void OnCategoriesAvailable(scoped_refptr<atom::util::Promise> promise, void OnCategoriesAvailable(atom::util::Promise promise,
const std::set<std::string>& categories) { const std::set<std::string>& categories) {
promise->Resolve(categories); promise.Resolve(categories);
} }
v8::Local<v8::Promise> GetCategories(v8::Isolate* isolate) { v8::Local<v8::Promise> GetCategories(v8::Isolate* isolate) {
scoped_refptr<atom::util::Promise> promise = new atom::util::Promise(isolate); atom::util::Promise promise(isolate);
bool success = TracingController::GetInstance()->GetCategories( v8::Local<v8::Promise> handle = promise.GetHandle();
base::BindOnce(&OnCategoriesAvailable, promise));
if (!success) // Note: This method always succeeds.
promise->RejectWithErrorMessage("Could not get categories."); TracingController::GetInstance()->GetCategories(
base::BindOnce(&OnCategoriesAvailable, std::move(promise)));
return promise->GetHandle(); return handle;
} }
void OnTracingStarted(scoped_refptr<atom::util::Promise> promise) { void OnTracingStarted(atom::util::Promise promise) {
promise->Resolve(); promise.Resolve();
} }
v8::Local<v8::Promise> StartTracing( v8::Local<v8::Promise> StartTracing(
v8::Isolate* isolate, v8::Isolate* isolate,
const base::trace_event::TraceConfig& trace_config) { const base::trace_event::TraceConfig& trace_config) {
scoped_refptr<atom::util::Promise> promise = new atom::util::Promise(isolate); atom::util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
bool success = TracingController::GetInstance()->StartTracing( // Note: This method always succeeds.
trace_config, base::BindOnce(&OnTracingStarted, promise)); TracingController::GetInstance()->StartTracing(
trace_config, base::BindOnce(&OnTracingStarted, std::move(promise)));
if (!success) return handle;
promise->RejectWithErrorMessage("Could not start tracing");
return promise->GetHandle();
} }
void OnTraceBufferUsageAvailable(scoped_refptr<atom::util::Promise> promise, void OnTraceBufferUsageAvailable(atom::util::Promise promise,
float percent_full, float percent_full,
size_t approximate_count) { size_t approximate_count) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(promise->isolate()); mate::Dictionary dict = mate::Dictionary::CreateEmpty(promise.isolate());
dict.Set("percentage", percent_full); dict.Set("percentage", percent_full);
dict.Set("value", approximate_count); dict.Set("value", approximate_count);
promise->Resolve(dict.GetHandle()); promise.Resolve(dict.GetHandle());
} }
v8::Local<v8::Promise> GetTraceBufferUsage(v8::Isolate* isolate) { v8::Local<v8::Promise> GetTraceBufferUsage(v8::Isolate* isolate) {
scoped_refptr<atom::util::Promise> promise = new atom::util::Promise(isolate); atom::util::Promise promise(isolate);
bool success = TracingController::GetInstance()->GetTraceBufferUsage( v8::Local<v8::Promise> handle = promise.GetHandle();
base::BindOnce(&OnTraceBufferUsageAvailable, promise));
if (!success) // Note: This method always succeeds.
promise->RejectWithErrorMessage("Could not get trace buffer usage."); TracingController::GetInstance()->GetTraceBufferUsage(
base::BindOnce(&OnTraceBufferUsageAvailable, std::move(promise)));
return promise->GetHandle(); return handle;
} }
void Initialize(v8::Local<v8::Object> exports, void Initialize(v8::Local<v8::Object> exports,

View file

@ -136,29 +136,29 @@ inline net::CookieStore* GetCookieStore(
return getter->GetURLRequestContext()->cookie_store(); return getter->GetURLRequestContext()->cookie_store();
} }
void ResolvePromiseWithCookies(scoped_refptr<util::Promise> promise, void ResolvePromiseWithCookies(util::Promise promise,
net::CookieList cookieList) { const net::CookieList& cookie_list) {
promise->Resolve(cookieList); promise.Resolve(cookie_list);
} }
void ResolvePromise(scoped_refptr<util::Promise> promise) { void ResolvePromise(util::Promise promise) {
promise->Resolve(); promise.Resolve();
} }
// Resolve |promise| in UI thread. // Resolve |promise| in UI thread.
void ResolvePromiseInUI(scoped_refptr<util::Promise> promise) { void ResolvePromiseInUI(util::Promise promise) {
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
base::BindOnce(ResolvePromise, std::move(promise))); base::BindOnce(ResolvePromise, std::move(promise)));
} }
// Run |callback| on UI thread. // Run |callback| on UI thread.
void RunCallbackInUI(const base::Closure& callback) { void RunCallbackInUI(base::OnceClosure callback) {
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback); base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(callback));
} }
// Remove cookies from |list| not matching |filter|, and pass it to |callback|. // Remove cookies from |list| not matching |filter|, and pass it to |callback|.
void FilterCookies(std::unique_ptr<base::DictionaryValue> filter, void FilterCookies(std::unique_ptr<base::DictionaryValue> filter,
scoped_refptr<util::Promise> promise, util::Promise promise,
const net::CookieList& list) { const net::CookieList& list) {
net::CookieList result; net::CookieList result;
for (const auto& cookie : list) { for (const auto& cookie : list) {
@ -174,50 +174,50 @@ void FilterCookies(std::unique_ptr<base::DictionaryValue> filter,
// Receives cookies matching |filter| in IO thread. // Receives cookies matching |filter| in IO thread.
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter, void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
std::unique_ptr<base::DictionaryValue> filter, std::unique_ptr<base::DictionaryValue> filter,
scoped_refptr<util::Promise> promise) { util::Promise promise) {
std::string url; std::string url;
filter->GetString("url", &url); filter->GetString("url", &url);
auto filtered_callback = auto filtered_callback =
base::Bind(FilterCookies, base::Passed(&filter), std::move(promise)); base::BindOnce(FilterCookies, std::move(filter), std::move(promise));
// Empty url will match all url cookies. // Empty url will match all url cookies.
if (url.empty()) if (url.empty())
GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback); GetCookieStore(getter)->GetAllCookiesAsync(std::move(filtered_callback));
else else
GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url), GetCookieStore(getter)->GetAllCookiesForURLAsync(
filtered_callback); GURL(url), std::move(filtered_callback));
} }
// Removes cookie with |url| and |name| in IO thread. // Removes cookie with |url| and |name| in IO thread.
void RemoveCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter, void RemoveCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
const GURL& url, const GURL& url,
const std::string& name, const std::string& name,
scoped_refptr<util::Promise> promise) { util::Promise promise) {
GetCookieStore(getter)->DeleteCookieAsync( GetCookieStore(getter)->DeleteCookieAsync(
url, name, base::BindOnce(ResolvePromiseInUI, std::move(promise))); url, name, base::BindOnce(ResolvePromiseInUI, std::move(promise)));
} }
// Resolves/rejects the |promise| in UI thread. // Resolves/rejects the |promise| in UI thread.
void SettlePromiseInUI(scoped_refptr<util::Promise> promise, void SettlePromiseInUI(util::Promise promise, const std::string& errmsg) {
const std::string& errmsg) {
if (errmsg.empty()) { if (errmsg.empty()) {
promise->Resolve(); promise.Resolve();
} else { } else {
promise->RejectWithErrorMessage(errmsg); promise.RejectWithErrorMessage(errmsg);
} }
} }
// Callback of SetCookie. // Callback of SetCookie.
void OnSetCookie(scoped_refptr<util::Promise> promise, bool success) { void OnSetCookie(util::Promise promise, bool success) {
const std::string errmsg = success ? "" : "Setting cookie failed"; const std::string errmsg = success ? "" : "Setting cookie failed";
RunCallbackInUI(base::Bind(SettlePromiseInUI, std::move(promise), errmsg)); RunCallbackInUI(
base::BindOnce(SettlePromiseInUI, std::move(promise), errmsg));
} }
// Flushes cookie store in IO thread. // Flushes cookie store in IO thread.
void FlushCookieStoreOnIOThread( void FlushCookieStoreOnIOThread(
scoped_refptr<net::URLRequestContextGetter> getter, scoped_refptr<net::URLRequestContextGetter> getter,
scoped_refptr<util::Promise> promise) { util::Promise promise) {
GetCookieStore(getter)->FlushStore( GetCookieStore(getter)->FlushStore(
base::BindOnce(ResolvePromiseInUI, std::move(promise))); base::BindOnce(ResolvePromiseInUI, std::move(promise)));
} }
@ -225,7 +225,7 @@ void FlushCookieStoreOnIOThread(
// Sets cookie with |details| in IO thread. // Sets cookie with |details| in IO thread.
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter, void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
std::unique_ptr<base::DictionaryValue> details, std::unique_ptr<base::DictionaryValue> details,
scoped_refptr<util::Promise> promise) { util::Promise promise) {
std::string url, name, value, domain, path; std::string url, name, value, domain, path;
bool secure = false; bool secure = false;
bool http_only = false; bool http_only = false;
@ -297,7 +297,8 @@ Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context)
Cookies::~Cookies() {} Cookies::~Cookies() {}
v8::Local<v8::Promise> Cookies::Get(const base::DictionaryValue& filter) { v8::Local<v8::Promise> Cookies::Get(const base::DictionaryValue& filter) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
auto copy = base::DictionaryValue::From( auto copy = base::DictionaryValue::From(
base::Value::ToUniquePtrValue(filter.Clone())); base::Value::ToUniquePtrValue(filter.Clone()));
@ -305,26 +306,28 @@ v8::Local<v8::Promise> Cookies::Get(const base::DictionaryValue& filter) {
base::PostTaskWithTraits( base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO}, FROM_HERE, {BrowserThread::IO},
base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter), std::move(copy), base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter), std::move(copy),
promise)); std::move(promise)));
return promise->GetHandle(); return handle;
} }
v8::Local<v8::Promise> Cookies::Remove(const GURL& url, v8::Local<v8::Promise> Cookies::Remove(const GURL& url,
const std::string& name) { const std::string& name) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
auto* getter = browser_context_->GetRequestContext(); auto* getter = browser_context_->GetRequestContext();
base::PostTaskWithTraits( base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO}, FROM_HERE, {BrowserThread::IO},
base::BindOnce(RemoveCookieOnIO, base::RetainedRef(getter), url, name, base::BindOnce(RemoveCookieOnIO, base::RetainedRef(getter), url, name,
promise)); std::move(promise)));
return promise->GetHandle(); return handle;
} }
v8::Local<v8::Promise> Cookies::Set(const base::DictionaryValue& details) { v8::Local<v8::Promise> Cookies::Set(const base::DictionaryValue& details) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
auto copy = base::DictionaryValue::From( auto copy = base::DictionaryValue::From(
base::Value::ToUniquePtrValue(details.Clone())); base::Value::ToUniquePtrValue(details.Clone()));
@ -332,20 +335,22 @@ v8::Local<v8::Promise> Cookies::Set(const base::DictionaryValue& details) {
base::PostTaskWithTraits( base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO}, FROM_HERE, {BrowserThread::IO},
base::BindOnce(SetCookieOnIO, base::RetainedRef(getter), std::move(copy), base::BindOnce(SetCookieOnIO, base::RetainedRef(getter), std::move(copy),
promise)); std::move(promise)));
return promise->GetHandle(); return handle;
} }
v8::Local<v8::Promise> Cookies::FlushStore() { v8::Local<v8::Promise> Cookies::FlushStore() {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
auto* getter = browser_context_->GetRequestContext(); auto* getter = browser_context_->GetRequestContext();
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, base::PostTaskWithTraits(
base::BindOnce(FlushCookieStoreOnIOThread, FROM_HERE, {BrowserThread::IO},
base::RetainedRef(getter), promise)); base::BindOnce(FlushCookieStoreOnIOThread, base::RetainedRef(getter),
std::move(promise)));
return promise->GetHandle(); return handle;
} }
void Cookies::OnCookieChanged(const CookieDetails* details) { void Cookies::OnCookieChanged(const CookieDetails* details) {

View file

@ -65,21 +65,21 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
if (it == pending_requests_.end()) if (it == pending_requests_.end())
return; return;
scoped_refptr<atom::util::Promise> promise = it->second; atom::util::Promise promise = std::move(it->second);
pending_requests_.erase(it); pending_requests_.erase(it);
base::DictionaryValue* error = nullptr; base::DictionaryValue* error = nullptr;
if (dict->GetDictionary("error", &error)) { if (dict->GetDictionary("error", &error)) {
std::string message; std::string message;
error->GetString("message", &message); error->GetString("message", &message);
promise->RejectWithErrorMessage(message); promise.RejectWithErrorMessage(message);
} else { } else {
base::DictionaryValue* result_body = nullptr; base::DictionaryValue* result_body = nullptr;
base::DictionaryValue result; base::DictionaryValue result;
if (dict->GetDictionary("result", &result_body)) { if (dict->GetDictionary("result", &result_body)) {
result.Swap(result_body); result.Swap(result_body);
} }
promise->Resolve(result); promise.Resolve(result);
} }
} }
} }
@ -129,17 +129,18 @@ void Debugger::Detach() {
} }
v8::Local<v8::Promise> Debugger::SendCommand(mate::Arguments* args) { v8::Local<v8::Promise> Debugger::SendCommand(mate::Arguments* args) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); atom::util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
if (!agent_host_) { if (!agent_host_) {
promise->RejectWithErrorMessage("No target available"); promise.RejectWithErrorMessage("No target available");
return promise->GetHandle(); return handle;
} }
std::string method; std::string method;
if (!args->GetNext(&method)) { if (!args->GetNext(&method)) {
promise->RejectWithErrorMessage("Invalid method"); promise.RejectWithErrorMessage("Invalid method");
return promise->GetHandle(); return handle;
} }
base::DictionaryValue command_params; base::DictionaryValue command_params;
@ -147,7 +148,7 @@ v8::Local<v8::Promise> Debugger::SendCommand(mate::Arguments* args) {
base::DictionaryValue request; base::DictionaryValue request;
int request_id = ++previous_request_id_; int request_id = ++previous_request_id_;
pending_requests_[request_id] = promise; pending_requests_.emplace(request_id, std::move(promise));
request.SetInteger("id", request_id); request.SetInteger("id", request_id);
request.SetString("method", method); request.SetString("method", method);
if (!command_params.empty()) if (!command_params.empty())
@ -158,12 +159,12 @@ v8::Local<v8::Promise> Debugger::SendCommand(mate::Arguments* args) {
base::JSONWriter::Write(request, &json_args); base::JSONWriter::Write(request, &json_args);
agent_host_->DispatchProtocolMessage(this, json_args); agent_host_->DispatchProtocolMessage(this, json_args);
return promise->GetHandle(); return handle;
} }
void Debugger::ClearPendingRequests() { void Debugger::ClearPendingRequests() {
for (const auto& it : pending_requests_) for (auto& it : pending_requests_)
it.second->RejectWithErrorMessage("target closed while handling command"); it.second.RejectWithErrorMessage("target closed while handling command");
} }
// static // static

View file

@ -54,7 +54,7 @@ class Debugger : public mate::TrackableObject<Debugger>,
content::RenderFrameHost* new_rfh) override; content::RenderFrameHost* new_rfh) override;
private: private:
using PendingRequestMap = std::map<int, scoped_refptr<atom::util::Promise>>; using PendingRequestMap = std::map<int, atom::util::Promise>;
void Attach(mate::Arguments* args); void Attach(mate::Arguments* args);
bool IsAttached(); bool IsAttached();

View file

@ -22,9 +22,9 @@
namespace { namespace {
void OnGetFilePathToCompletedLog(scoped_refptr<atom::util::Promise> promise, void OnGetFilePathToCompletedLog(const atom::util::CopyablePromise& promise,
const base::FilePath& file_path) { const base::FilePath& file_path) {
promise->Resolve(file_path); promise.GetPromise().Resolve(file_path);
} }
} // namespace } // namespace
@ -97,16 +97,17 @@ std::string NetLog::GetCurrentlyLoggingPath() const {
} }
v8::Local<v8::Promise> NetLog::StopLogging(mate::Arguments* args) { v8::Local<v8::Promise> NetLog::StopLogging(mate::Arguments* args) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
if (IsCurrentlyLogging()) { if (IsCurrentlyLogging()) {
stop_callback_queue_.emplace_back(promise); stop_callback_queue_.emplace_back(std::move(promise));
net_log_writer_->StopNetLog(nullptr); net_log_writer_->StopNetLog(nullptr);
} else { } else {
promise->Resolve(base::FilePath()); promise.Resolve(base::FilePath());
} }
return promise->GetHandle(); return handle;
} }
void NetLog::OnNewState(const base::DictionaryValue& state) { void NetLog::OnNewState(const base::DictionaryValue& state) {
@ -117,8 +118,10 @@ void NetLog::OnNewState(const base::DictionaryValue& state) {
if (GetLoggingState() == "NOT_LOGGING") { if (GetLoggingState() == "NOT_LOGGING") {
for (auto& promise : stop_callback_queue_) { for (auto& promise : stop_callback_queue_) {
net_log_writer_->GetFilePathToCompletedLog( // TODO(zcbenz): Remove the use of CopyablePromise when the
base::Bind(&OnGetFilePathToCompletedLog, promise)); // GetFilePathToCompletedLog API accepts OnceCallback.
net_log_writer_->GetFilePathToCompletedLog(base::Bind(
&OnGetFilePathToCompletedLog, util::CopyablePromise(promise)));
} }
stop_callback_queue_.clear(); stop_callback_queue_.clear();
} }

View file

@ -47,7 +47,7 @@ class NetLog : public mate::TrackableObject<NetLog>,
private: private:
AtomBrowserContext* browser_context_; AtomBrowserContext* browser_context_;
net_log::NetExportFileWriter* net_log_writer_; net_log::NetExportFileWriter* net_log_writer_;
std::list<scoped_refptr<atom::util::Promise>> stop_callback_queue_; std::list<atom::util::Promise> stop_callback_queue_;
std::unique_ptr<base::DictionaryValue> net_log_state_; std::unique_ptr<base::DictionaryValue> net_log_state_;
DISALLOW_COPY_AND_ASSIGN(NetLog); DISALLOW_COPY_AND_ASSIGN(NetLog);

View file

@ -177,21 +177,22 @@ bool IsProtocolHandledInIO(
return is_handled; return is_handled;
} }
void PromiseCallback(scoped_refptr<util::Promise> promise, bool handled) { void PromiseCallback(util::Promise promise, bool handled) {
promise->Resolve(handled); promise.Resolve(handled);
} }
v8::Local<v8::Promise> Protocol::IsProtocolHandled(const std::string& scheme) { v8::Local<v8::Promise> Protocol::IsProtocolHandled(const std::string& scheme) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
auto* getter = static_cast<URLRequestContextGetter*>( auto* getter = static_cast<URLRequestContextGetter*>(
browser_context_->GetRequestContext()); browser_context_->GetRequestContext());
base::PostTaskWithTraitsAndReplyWithResult( base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {content::BrowserThread::IO}, FROM_HERE, {content::BrowserThread::IO},
base::Bind(&IsProtocolHandledInIO, base::RetainedRef(getter), scheme), base::BindOnce(&IsProtocolHandledInIO, base::RetainedRef(getter), scheme),
base::Bind(&PromiseCallback, promise)); base::BindOnce(&PromiseCallback, std::move(promise)));
return promise->GetHandle(); return handle;
} }
void Protocol::UninterceptProtocol(const std::string& scheme, void Protocol::UninterceptProtocol(const std::string& scheme,

View file

@ -457,19 +457,20 @@ bool SystemPreferences::CanPromptTouchID() {
return false; return false;
} }
void OnTouchIDCompleted(scoped_refptr<util::Promise> promise) { void OnTouchIDCompleted(util::Promise promise) {
promise->Resolve(); promise.Resolve();
} }
void OnTouchIDFailed(scoped_refptr<util::Promise> promise, void OnTouchIDFailed(util::Promise promise, const std::string& reason) {
const std::string& reason) { promise.RejectWithErrorMessage(reason);
promise->RejectWithErrorMessage(reason);
} }
v8::Local<v8::Promise> SystemPreferences::PromptTouchID( v8::Local<v8::Promise> SystemPreferences::PromptTouchID(
v8::Isolate* isolate, v8::Isolate* isolate,
const std::string& reason) { const std::string& reason) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate); util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
if (@available(macOS 10.12.2, *)) { if (@available(macOS 10.12.2, *)) {
base::scoped_nsobject<LAContext> context([[LAContext alloc] init]); base::scoped_nsobject<LAContext> context([[LAContext alloc] init]);
base::ScopedCFTypeRef<SecAccessControlRef> access_control = base::ScopedCFTypeRef<SecAccessControlRef> access_control =
@ -484,6 +485,7 @@ v8::Local<v8::Promise> SystemPreferences::PromptTouchID(
scoped_refptr<base::SequencedTaskRunner> runner = scoped_refptr<base::SequencedTaskRunner> runner =
base::SequencedTaskRunnerHandle::Get(); base::SequencedTaskRunnerHandle::Get();
__block util::Promise p = std::move(promise);
[context [context
evaluateAccessControl:access_control evaluateAccessControl:access_control
operation:LAAccessControlOperationUseKeySign operation:LAAccessControlOperationUseKeySign
@ -493,20 +495,20 @@ v8::Local<v8::Promise> SystemPreferences::PromptTouchID(
runner->PostTask( runner->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce( base::BindOnce(
&OnTouchIDFailed, promise, &OnTouchIDFailed, std::move(p),
std::string([error.localizedDescription std::string([error.localizedDescription
UTF8String]))); UTF8String])));
} else { } else {
runner->PostTask( runner->PostTask(FROM_HERE,
FROM_HERE, base::BindOnce(&OnTouchIDCompleted,
base::BindOnce(&OnTouchIDCompleted, promise)); std::move(p)));
} }
}]; }];
} else { } else {
promise->RejectWithErrorMessage( promise.RejectWithErrorMessage(
"This API is not available on macOS versions older than 10.12.2"); "This API is not available on macOS versions older than 10.12.2");
} }
return promise->GetHandle(); return handle;
} }
// static // static
@ -625,25 +627,27 @@ std::string SystemPreferences::GetMediaAccessStatus(
v8::Local<v8::Promise> SystemPreferences::AskForMediaAccess( v8::Local<v8::Promise> SystemPreferences::AskForMediaAccess(
v8::Isolate* isolate, v8::Isolate* isolate,
const std::string& media_type) { const std::string& media_type) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate); util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
if (auto type = ParseMediaType(media_type)) { if (auto type = ParseMediaType(media_type)) {
if (@available(macOS 10.14, *)) { if (@available(macOS 10.14, *)) {
__block util::Promise p = std::move(promise);
[AVCaptureDevice requestAccessForMediaType:type [AVCaptureDevice requestAccessForMediaType:type
completionHandler:^(BOOL granted) { completionHandler:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
promise->Resolve(!!granted); p.Resolve(!!granted);
}); });
}]; }];
} else { } else {
// access always allowed pre-10.14 Mojave // access always allowed pre-10.14 Mojave
promise->Resolve(true); promise.Resolve(true);
} }
} else { } else {
promise->RejectWithErrorMessage("Invalid media type"); promise.RejectWithErrorMessage("Invalid media type");
} }
return promise->GetHandle(); return handle;
} }
void SystemPreferences::RemoveUserDefault(const std::string& name) { void SystemPreferences::RemoveUserDefault(const std::string& name) {

View file

@ -241,12 +241,11 @@ namespace api {
namespace { namespace {
// Called when CapturePage is done. // Called when CapturePage is done.
void OnCapturePageDone(scoped_refptr<util::Promise> promise, void OnCapturePageDone(util::Promise promise, const SkBitmap& bitmap) {
const SkBitmap& bitmap) {
// Hack to enable transparency in captured image // Hack to enable transparency in captured image
// TODO(nitsakh) Remove hack once fixed in chromium // TODO(nitsakh) Remove hack once fixed in chromium
const_cast<SkBitmap&>(bitmap).setAlphaType(kPremul_SkAlphaType); const_cast<SkBitmap&>(bitmap).setAlphaType(kPremul_SkAlphaType);
promise->Resolve(gfx::Image::CreateFrom1xBitmap(bitmap)); promise.Resolve(gfx::Image::CreateFrom1xBitmap(bitmap));
} }
} // namespace } // namespace
@ -1302,14 +1301,12 @@ std::string WebContents::GetUserAgent() {
v8::Local<v8::Promise> WebContents::SavePage( v8::Local<v8::Promise> WebContents::SavePage(
const base::FilePath& full_file_path, const base::FilePath& full_file_path,
const content::SavePageType& save_type) { const content::SavePageType& save_type) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
auto* handler = new SavePageHandler(web_contents(), promise); v8::Local<v8::Promise> ret = promise.GetHandle();
const bool saveStarted = handler->Handle(full_file_path, save_type); auto* handler = new SavePageHandler(web_contents(), std::move(promise));
if (!saveStarted) handler->Handle(full_file_path, save_type);
promise->RejectWithErrorMessage("Failed to save the page"); return ret;
return promise->GetHandle();
} }
void WebContents::OpenDevTools(mate::Arguments* args) { void WebContents::OpenDevTools(mate::Arguments* args) {
@ -1506,10 +1503,11 @@ std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() {
v8::Local<v8::Promise> WebContents::PrintToPDF( v8::Local<v8::Promise> WebContents::PrintToPDF(
const base::DictionaryValue& settings) { const base::DictionaryValue& settings) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
PrintPreviewMessageHandler::FromWebContents(web_contents()) PrintPreviewMessageHandler::FromWebContents(web_contents())
->PrintToPDF(settings, promise); ->PrintToPDF(settings, std::move(promise));
return promise->GetHandle(); return handle;
} }
#endif #endif
@ -1780,15 +1778,16 @@ void WebContents::StartDrag(const mate::Dictionary& item,
v8::Local<v8::Promise> WebContents::CapturePage(mate::Arguments* args) { v8::Local<v8::Promise> WebContents::CapturePage(mate::Arguments* args) {
gfx::Rect rect; gfx::Rect rect;
scoped_refptr<util::Promise> promise = new util::Promise(isolate()); util::Promise promise(isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
// get rect arguments if they exist // get rect arguments if they exist
args->GetNext(&rect); args->GetNext(&rect);
auto* const view = web_contents()->GetRenderWidgetHostView(); auto* const view = web_contents()->GetRenderWidgetHostView();
if (!view) { if (!view) {
promise->Resolve(gfx::Image()); promise.Resolve(gfx::Image());
return promise->GetHandle(); return handle;
} }
// Capture full page if user doesn't specify a |rect|. // Capture full page if user doesn't specify a |rect|.
@ -1807,8 +1806,8 @@ v8::Local<v8::Promise> WebContents::CapturePage(mate::Arguments* args) {
bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); bitmap_size = gfx::ScaleToCeiledSize(view_size, scale);
view->CopyFromSurface(gfx::Rect(rect.origin(), view_size), bitmap_size, view->CopyFromSurface(gfx::Rect(rect.origin(), view_size), bitmap_size,
base::BindOnce(&OnCapturePageDone, promise)); base::BindOnce(&OnCapturePageDone, std::move(promise)));
return promise->GetHandle(); return handle;
} }
void WebContents::OnCursorChange(const content::WebCursor& cursor) { void WebContents::OnCursorChange(const content::WebCursor& cursor) {

View file

@ -3,6 +3,9 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "atom/browser/api/gpuinfo_manager.h" #include "atom/browser/api/gpuinfo_manager.h"
#include <utility>
#include "atom/browser/api/gpu_info_enumerator.h" #include "atom/browser/api/gpu_info_enumerator.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
@ -42,8 +45,8 @@ void GPUInfoManager::ProcessCompleteInfo() {
const auto result = EnumerateGPUInfo(gpu_data_manager_->GetGPUInfo()); const auto result = EnumerateGPUInfo(gpu_data_manager_->GetGPUInfo());
// We have received the complete information, resolve all promises that // We have received the complete information, resolve all promises that
// were waiting for this info. // were waiting for this info.
for (const auto& promise : complete_info_promise_set_) { for (auto& promise : complete_info_promise_set_) {
promise->Resolve(*result); promise.Resolve(*result);
} }
complete_info_promise_set_.clear(); complete_info_promise_set_.clear();
} }
@ -58,8 +61,8 @@ void GPUInfoManager::OnGpuInfoUpdate() {
} }
// Should be posted to the task runner // Should be posted to the task runner
void GPUInfoManager::CompleteInfoFetcher(scoped_refptr<util::Promise> promise) { void GPUInfoManager::CompleteInfoFetcher(util::Promise promise) {
complete_info_promise_set_.push_back(promise); complete_info_promise_set_.emplace_back(std::move(promise));
if (NeedsCompleteGpuInfoCollection()) { if (NeedsCompleteGpuInfoCollection()) {
gpu_data_manager_->RequestCompleteGpuInfoIfNeeded(); gpu_data_manager_->RequestCompleteGpuInfoIfNeeded();
@ -68,18 +71,18 @@ void GPUInfoManager::CompleteInfoFetcher(scoped_refptr<util::Promise> promise) {
} }
} }
void GPUInfoManager::FetchCompleteInfo(scoped_refptr<util::Promise> promise) { void GPUInfoManager::FetchCompleteInfo(util::Promise promise) {
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&GPUInfoManager::CompleteInfoFetcher, FROM_HERE, base::BindOnce(&GPUInfoManager::CompleteInfoFetcher,
base::Unretained(this), promise)); base::Unretained(this), std::move(promise)));
} }
// This fetches the info synchronously, so no need to post to the task queue. // This fetches the info synchronously, so no need to post to the task queue.
// There cannot be multiple promises as they are resolved synchronously. // There cannot be multiple promises as they are resolved synchronously.
void GPUInfoManager::FetchBasicInfo(scoped_refptr<util::Promise> promise) { void GPUInfoManager::FetchBasicInfo(util::Promise promise) {
gpu::GPUInfo gpu_info; gpu::GPUInfo gpu_info;
CollectBasicGraphicsInfo(&gpu_info); CollectBasicGraphicsInfo(&gpu_info);
promise->Resolve(*EnumerateGPUInfo(gpu_info)); promise.Resolve(*EnumerateGPUInfo(gpu_info));
} }
std::unique_ptr<base::DictionaryValue> GPUInfoManager::EnumerateGPUInfo( std::unique_ptr<base::DictionaryValue> GPUInfoManager::EnumerateGPUInfo(

View file

@ -25,8 +25,8 @@ class GPUInfoManager : public content::GpuDataManagerObserver {
GPUInfoManager(); GPUInfoManager();
~GPUInfoManager() override; ~GPUInfoManager() override;
bool NeedsCompleteGpuInfoCollection() const; bool NeedsCompleteGpuInfoCollection() const;
void FetchCompleteInfo(scoped_refptr<util::Promise> promise); void FetchCompleteInfo(util::Promise promise);
void FetchBasicInfo(scoped_refptr<util::Promise> promise); void FetchBasicInfo(util::Promise promise);
void OnGpuInfoUpdate() override; void OnGpuInfoUpdate() override;
private: private:
@ -34,12 +34,12 @@ class GPUInfoManager : public content::GpuDataManagerObserver {
gpu::GPUInfo gpu_info) const; gpu::GPUInfo gpu_info) const;
// These should be posted to the task queue // These should be posted to the task queue
void CompleteInfoFetcher(scoped_refptr<util::Promise> promise); void CompleteInfoFetcher(util::Promise promise);
void ProcessCompleteInfo(); void ProcessCompleteInfo();
// This set maintains all the promises that should be fulfilled // This set maintains all the promises that should be fulfilled
// once we have the complete information data // once we have the complete information data
std::vector<scoped_refptr<util::Promise>> complete_info_promise_set_; std::vector<util::Promise> complete_info_promise_set_;
content::GpuDataManager* gpu_data_manager_; content::GpuDataManager* gpu_data_manager_;
DISALLOW_COPY_AND_ASSIGN(GPUInfoManager); DISALLOW_COPY_AND_ASSIGN(GPUInfoManager);

View file

@ -5,6 +5,7 @@
#include "atom/browser/api/save_page_handler.h" #include "atom/browser/api/save_page_handler.h"
#include <string> #include <string>
#include <utility>
#include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_context.h"
#include "base/callback.h" #include "base/callback.h"
@ -16,8 +17,8 @@ namespace atom {
namespace api { namespace api {
SavePageHandler::SavePageHandler(content::WebContents* web_contents, SavePageHandler::SavePageHandler(content::WebContents* web_contents,
scoped_refptr<atom::util::Promise> promise) util::Promise promise)
: web_contents_(web_contents), promise_(promise) {} : web_contents_(web_contents), promise_(std::move(promise)) {}
SavePageHandler::~SavePageHandler() {} SavePageHandler::~SavePageHandler() {}
@ -43,17 +44,19 @@ bool SavePageHandler::Handle(const base::FilePath& full_path,
download_manager->RemoveObserver(this); download_manager->RemoveObserver(this);
// If initialization fails which means fail to create |DownloadItem|, we need // If initialization fails which means fail to create |DownloadItem|, we need
// to delete the |SavePageHandler| instance to avoid memory-leak. // to delete the |SavePageHandler| instance to avoid memory-leak.
if (!result) if (!result) {
promise_.RejectWithErrorMessage("Failed to save the page");
delete this; delete this;
}
return result; return result;
} }
void SavePageHandler::OnDownloadUpdated(download::DownloadItem* item) { void SavePageHandler::OnDownloadUpdated(download::DownloadItem* item) {
if (item->IsDone()) { if (item->IsDone()) {
if (item->GetState() == download::DownloadItem::COMPLETE) if (item->GetState() == download::DownloadItem::COMPLETE)
promise_->Resolve(); promise_.Resolve();
else else
promise_->RejectWithErrorMessage("Failed to save the page."); promise_.RejectWithErrorMessage("Failed to save the page.");
Destroy(item); Destroy(item);
} }
} }

View file

@ -30,7 +30,7 @@ class SavePageHandler : public content::DownloadManager::Observer,
public download::DownloadItem::Observer { public download::DownloadItem::Observer {
public: public:
SavePageHandler(content::WebContents* web_contents, SavePageHandler(content::WebContents* web_contents,
scoped_refptr<atom::util::Promise> promise); atom::util::Promise promise);
~SavePageHandler() override; ~SavePageHandler() override;
bool Handle(const base::FilePath& full_path, bool Handle(const base::FilePath& full_path,
@ -47,7 +47,7 @@ class SavePageHandler : public content::DownloadManager::Observer,
void OnDownloadUpdated(download::DownloadItem* item) override; void OnDownloadUpdated(download::DownloadItem* item) override;
content::WebContents* web_contents_; // weak content::WebContents* web_contents_; // weak
scoped_refptr<atom::util::Promise> promise_; atom::util::Promise promise_;
}; };
} // namespace api } // namespace api

View file

@ -165,14 +165,14 @@ void Browser::DidFinishLaunching(const base::DictionaryValue& launch_info) {
observer.OnFinishLaunching(launch_info); observer.OnFinishLaunching(launch_info);
} }
util::Promise* Browser::WhenReady(v8::Isolate* isolate) { const util::Promise& Browser::WhenReady(v8::Isolate* isolate) {
if (!ready_promise_) { if (!ready_promise_) {
ready_promise_ = new util::Promise(isolate); ready_promise_.reset(new util::Promise(isolate));
if (is_ready()) { if (is_ready()) {
ready_promise_->Resolve(); ready_promise_->Resolve();
} }
} }
return ready_promise_; return *ready_promise_;
} }
void Browser::OnAccessibilitySupportChanged() { void Browser::OnAccessibilitySupportChanged() {

View file

@ -253,7 +253,7 @@ class Browser : public WindowListObserver {
bool is_shutting_down() const { return is_shutdown_; } bool is_shutting_down() const { return is_shutdown_; }
bool is_quiting() const { return is_quiting_; } bool is_quiting() const { return is_quiting_; }
bool is_ready() const { return is_ready_; } bool is_ready() const { return is_ready_; }
util::Promise* WhenReady(v8::Isolate* isolate); const util::Promise& WhenReady(v8::Isolate* isolate);
protected: protected:
// Returns the version of application bundle or executable file. // Returns the version of application bundle or executable file.
@ -292,7 +292,7 @@ class Browser : public WindowListObserver {
int badge_count_ = 0; int badge_count_ = 0;
util::Promise* ready_promise_ = nullptr; std::unique_ptr<util::Promise> ready_promise_;
#if defined(OS_LINUX) || defined(OS_MACOSX) #if defined(OS_LINUX) || defined(OS_MACOSX)
base::DictionaryValue about_panel_options_; base::DictionaryValue about_panel_options_;

View file

@ -342,7 +342,9 @@ bool Browser::DockIsVisible() {
} }
v8::Local<v8::Promise> Browser::DockShow(v8::Isolate* isolate) { v8::Local<v8::Promise> Browser::DockShow(v8::Isolate* isolate) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate); util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
BOOL active = [[NSRunningApplication currentApplication] isActive]; BOOL active = [[NSRunningApplication currentApplication] isActive];
ProcessSerialNumber psn = {0, kCurrentProcess}; ProcessSerialNumber psn = {0, kCurrentProcess};
if (active) { if (active) {
@ -354,6 +356,7 @@ v8::Local<v8::Promise> Browser::DockShow(v8::Isolate* isolate) {
[app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
break; break;
} }
__block util::Promise p = std::move(promise);
dispatch_time_t one_ms = dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC); dispatch_time_t one_ms = dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC);
dispatch_after(one_ms, dispatch_get_main_queue(), ^{ dispatch_after(one_ms, dispatch_get_main_queue(), ^{
TransformProcessType(&psn, kProcessTransformToForegroundApplication); TransformProcessType(&psn, kProcessTransformToForegroundApplication);
@ -361,14 +364,14 @@ v8::Local<v8::Promise> Browser::DockShow(v8::Isolate* isolate) {
dispatch_after(one_ms, dispatch_get_main_queue(), ^{ dispatch_after(one_ms, dispatch_get_main_queue(), ^{
[[NSRunningApplication currentApplication] [[NSRunningApplication currentApplication]
activateWithOptions:NSApplicationActivateIgnoringOtherApps]; activateWithOptions:NSApplicationActivateIgnoringOtherApps];
promise->Resolve(); p.Resolve();
}); });
}); });
} else { } else {
TransformProcessType(&psn, kProcessTransformToForegroundApplication); TransformProcessType(&psn, kProcessTransformToForegroundApplication);
promise->Resolve(); promise.Resolve();
} }
return promise->GetHandle(); return handle;
} }
void Browser::DockSetMenu(AtomMenuModel* model) { void Browser::DockSetMenu(AtomMenuModel* model) {

View file

@ -143,10 +143,10 @@ void PrintPreviewMessageHandler::OnPrintPreviewCancelled(
void PrintPreviewMessageHandler::PrintToPDF( void PrintPreviewMessageHandler::PrintToPDF(
const base::DictionaryValue& options, const base::DictionaryValue& options,
scoped_refptr<atom::util::Promise> promise) { atom::util::Promise promise) {
int request_id; int request_id;
options.GetInteger(printing::kPreviewRequestID, &request_id); options.GetInteger(printing::kPreviewRequestID, &request_id);
promise_map_[request_id] = std::move(promise); promise_map_.emplace(request_id, std::move(promise));
auto* focused_frame = web_contents()->GetFocusedFrame(); auto* focused_frame = web_contents()->GetFocusedFrame();
auto* rfh = focused_frame && focused_frame->HasSelection() auto* rfh = focused_frame && focused_frame->HasSelection()
@ -155,12 +155,11 @@ void PrintPreviewMessageHandler::PrintToPDF(
rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options)); rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options));
} }
scoped_refptr<atom::util::Promise> PrintPreviewMessageHandler::GetPromise( util::Promise PrintPreviewMessageHandler::GetPromise(int request_id) {
int request_id) {
auto it = promise_map_.find(request_id); auto it = promise_map_.find(request_id);
DCHECK(it != promise_map_.end()); DCHECK(it != promise_map_.end());
auto promise = it->second; util::Promise promise = std::move(it->second);
promise_map_.erase(it); promise_map_.erase(it);
return promise; return promise;
@ -171,13 +170,13 @@ void PrintPreviewMessageHandler::ResolvePromise(
scoped_refptr<base::RefCountedMemory> data_bytes) { scoped_refptr<base::RefCountedMemory> data_bytes) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto promise = GetPromise(request_id); util::Promise promise = GetPromise(request_id);
v8::Isolate* isolate = promise->isolate(); v8::Isolate* isolate = promise.isolate();
mate::Locker locker(isolate); mate::Locker locker(isolate);
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
v8::Context::Scope context_scope( v8::Context::Scope context_scope(
v8::Local<v8::Context>::New(isolate, promise->GetContext())); v8::Local<v8::Context>::New(isolate, promise.GetContext()));
v8::Local<v8::Value> buffer = v8::Local<v8::Value> buffer =
node::Buffer::Copy(isolate, node::Buffer::Copy(isolate,
@ -185,14 +184,14 @@ void PrintPreviewMessageHandler::ResolvePromise(
data_bytes->size()) data_bytes->size())
.ToLocalChecked(); .ToLocalChecked();
promise->Resolve(buffer); promise.Resolve(buffer);
} }
void PrintPreviewMessageHandler::RejectPromise(int request_id) { void PrintPreviewMessageHandler::RejectPromise(int request_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto promise = GetPromise(request_id); util::Promise promise = GetPromise(request_id);
promise->RejectWithErrorMessage("Failed to generate PDF"); promise.RejectWithErrorMessage("Failed to generate PDF");
} }
WEB_CONTENTS_USER_DATA_KEY_IMPL(PrintPreviewMessageHandler) WEB_CONTENTS_USER_DATA_KEY_IMPL(PrintPreviewMessageHandler)

View file

@ -31,8 +31,7 @@ class PrintPreviewMessageHandler
public: public:
~PrintPreviewMessageHandler() override; ~PrintPreviewMessageHandler() override;
void PrintToPDF(const base::DictionaryValue& options, void PrintToPDF(const base::DictionaryValue& options, util::Promise promise);
scoped_refptr<atom::util::Promise> promise);
protected: protected:
// content::WebContentsObserver implementation. // content::WebContentsObserver implementation.
@ -56,13 +55,13 @@ class PrintPreviewMessageHandler
void OnPrintPreviewCancelled(int document_cookie, void OnPrintPreviewCancelled(int document_cookie,
const PrintHostMsg_PreviewIds& ids); const PrintHostMsg_PreviewIds& ids);
scoped_refptr<atom::util::Promise> GetPromise(int request_id); util::Promise GetPromise(int request_id);
void ResolvePromise(int request_id, void ResolvePromise(int request_id,
scoped_refptr<base::RefCountedMemory> data_bytes); scoped_refptr<base::RefCountedMemory> data_bytes);
void RejectPromise(int request_id); void RejectPromise(int request_id);
using PromiseMap = std::map<int, scoped_refptr<atom::util::Promise>>; using PromiseMap = std::map<int, atom::util::Promise>;
PromiseMap promise_map_; PromiseMap promise_map_;
base::WeakPtrFactory<PrintPreviewMessageHandler> weak_ptr_factory_; base::WeakPtrFactory<PrintPreviewMessageHandler> weak_ptr_factory_;

View file

@ -44,12 +44,12 @@ struct Converter<base::win::ShortcutOperation> {
namespace { namespace {
void OnOpenExternalFinished(scoped_refptr<atom::util::Promise> promise, void OnOpenExternalFinished(atom::util::Promise promise,
const std::string& error) { const std::string& error) {
if (error.empty()) if (error.empty())
promise->Resolve(); promise.Resolve();
else else
promise->RejectWithErrorMessage(error.c_str()); promise.RejectWithErrorMessage(error.c_str());
} }
bool OpenExternalSync( bool OpenExternalSync(
@ -78,8 +78,7 @@ v8::Local<v8::Promise> OpenExternal(
const GURL& url, const GURL& url,
#endif #endif
mate::Arguments* args) { mate::Arguments* args) {
scoped_refptr<atom::util::Promise> promise = atom::util::Promise promise(args->isolate());
new atom::util::Promise(args->isolate());
platform_util::OpenExternalOptions options; platform_util::OpenExternalOptions options;
if (args->Length() >= 2) { if (args->Length() >= 2) {
@ -90,10 +89,11 @@ v8::Local<v8::Promise> OpenExternal(
} }
} }
platform_util::OpenExternal(url, options, v8::Local<v8::Promise> handle = promise.GetHandle();
base::Bind(&OnOpenExternalFinished, promise)); platform_util::OpenExternal(
url, options,
return promise->GetHandle(); base::BindOnce(&OnOpenExternalFinished, std::move(promise)));
return handle;
} }
#if defined(OS_WIN) #if defined(OS_WIN)

View file

@ -17,7 +17,6 @@
#include "atom/common/heap_snapshot.h" #include "atom/common/heap_snapshot.h"
#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/promise_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/process/process.h" #include "base/process/process.h"
#include "base/process/process_handle.h" #include "base/process/process_handle.h"
@ -233,30 +232,31 @@ v8::Local<v8::Value> AtomBindings::GetSystemMemoryInfo(v8::Isolate* isolate,
// static // static
v8::Local<v8::Promise> AtomBindings::GetProcessMemoryInfo( v8::Local<v8::Promise> AtomBindings::GetProcessMemoryInfo(
v8::Isolate* isolate) { v8::Isolate* isolate) {
scoped_refptr<util::Promise> promise = new util::Promise(isolate); util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
if (mate::Locker::IsBrowserProcess() && !Browser::Get()->is_ready()) { if (mate::Locker::IsBrowserProcess() && !Browser::Get()->is_ready()) {
promise->RejectWithErrorMessage( promise.RejectWithErrorMessage(
"Memory Info is available only after app ready"); "Memory Info is available only after app ready");
return promise->GetHandle(); return handle;
} }
v8::Global<v8::Context> context(isolate, isolate->GetCurrentContext()); v8::Global<v8::Context> context(isolate, isolate->GetCurrentContext());
memory_instrumentation::MemoryInstrumentation::GetInstance() memory_instrumentation::MemoryInstrumentation::GetInstance()
->RequestGlobalDumpForPid(base::GetCurrentProcId(), ->RequestGlobalDumpForPid(
std::vector<std::string>(), base::GetCurrentProcId(), std::vector<std::string>(),
base::Bind(&AtomBindings::DidReceiveMemoryDump, base::BindOnce(&AtomBindings::DidReceiveMemoryDump,
std::move(context), promise)); std::move(context), std::move(promise)));
return promise->GetHandle(); return handle;
} }
// static // static
void AtomBindings::DidReceiveMemoryDump( void AtomBindings::DidReceiveMemoryDump(
const v8::Global<v8::Context>& context, v8::Global<v8::Context> context,
scoped_refptr<util::Promise> promise, util::Promise promise,
bool success, bool success,
std::unique_ptr<memory_instrumentation::GlobalMemoryDump> global_dump) { std::unique_ptr<memory_instrumentation::GlobalMemoryDump> global_dump) {
v8::Isolate* isolate = promise->isolate(); v8::Isolate* isolate = promise.isolate();
mate::Locker locker(isolate); mate::Locker locker(isolate);
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
v8::MicrotasksScope script_scope(isolate, v8::MicrotasksScope script_scope(isolate,
@ -265,7 +265,7 @@ void AtomBindings::DidReceiveMemoryDump(
v8::Local<v8::Context>::New(isolate, context)); v8::Local<v8::Context>::New(isolate, context));
if (!success) { if (!success) {
promise->RejectWithErrorMessage("Failed to create memory dump"); promise.RejectWithErrorMessage("Failed to create memory dump");
return; return;
} }
@ -280,13 +280,13 @@ void AtomBindings::DidReceiveMemoryDump(
#endif #endif
dict.Set("private", osdump.private_footprint_kb); dict.Set("private", osdump.private_footprint_kb);
dict.Set("shared", osdump.shared_footprint_kb); dict.Set("shared", osdump.shared_footprint_kb);
promise->Resolve(dict.GetHandle()); promise.Resolve(dict.GetHandle());
resolved = true; resolved = true;
break; break;
} }
} }
if (!resolved) { if (!resolved) {
promise->RejectWithErrorMessage( promise.RejectWithErrorMessage(
R"(Failed to find current process memory details in memory dump)"); R"(Failed to find current process memory details in memory dump)");
} }
} }

View file

@ -8,6 +8,7 @@
#include <list> #include <list>
#include <memory> #include <memory>
#include "atom/common/promise_util.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
@ -31,10 +32,6 @@ class Environment;
namespace atom { namespace atom {
namespace util {
class Promise;
}
class AtomBindings { class AtomBindings {
public: public:
explicit AtomBindings(uv_loop_t* loop); explicit AtomBindings(uv_loop_t* loop);
@ -72,8 +69,8 @@ class AtomBindings {
static void OnCallNextTick(uv_async_t* handle); static void OnCallNextTick(uv_async_t* handle);
static void DidReceiveMemoryDump( static void DidReceiveMemoryDump(
const v8::Global<v8::Context>& context, v8::Global<v8::Context> context,
scoped_refptr<util::Promise> promise, util::Promise promise,
bool success, bool success,
std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump); std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump);

View file

@ -19,7 +19,7 @@ class GURL;
namespace platform_util { namespace platform_util {
typedef base::Callback<void(const std::string&)> OpenExternalCallback; typedef base::OnceCallback<void(const std::string&)> OpenExternalCallback;
// Show the given file in a file manager. If possible, select the file. // Show the given file in a file manager. If possible, select the file.
// Must be called from the UI thread. // Must be called from the UI thread.
@ -52,7 +52,7 @@ void OpenExternal(
const GURL& url, const GURL& url,
#endif #endif
const OpenExternalOptions& options, const OpenExternalOptions& options,
const OpenExternalCallback& callback); OpenExternalCallback callback);
// Move a file to trash. // Move a file to trash.
bool MoveItemToTrash(const base::FilePath& full_path); bool MoveItemToTrash(const base::FilePath& full_path);

View file

@ -92,9 +92,9 @@ bool OpenExternal(const GURL& url, const OpenExternalOptions& options) {
void OpenExternal(const GURL& url, void OpenExternal(const GURL& url,
const OpenExternalOptions& options, const OpenExternalOptions& options,
const OpenExternalCallback& callback) { OpenExternalCallback callback) {
// TODO(gabriel): Implement async open if callback is specified // TODO(gabriel): Implement async open if callback is specified
callback.Run(OpenExternal(url, options) ? "" : "Failed to open"); std::move(callback).Run(OpenExternal(url, options) ? "" : "Failed to open");
} }
bool MoveItemToTrash(const base::FilePath& full_path) { bool MoveItemToTrash(const base::FilePath& full_path) {

View file

@ -106,19 +106,19 @@ bool OpenExternal(const GURL& url, const OpenExternalOptions& options) {
void OpenExternal(const GURL& url, void OpenExternal(const GURL& url,
const OpenExternalOptions& options, const OpenExternalOptions& options,
const OpenExternalCallback& callback) { OpenExternalCallback callback) {
NSURL* ns_url = net::NSURLWithGURL(url); NSURL* ns_url = net::NSURLWithGURL(url);
if (!ns_url) { if (!ns_url) {
callback.Run("Invalid URL"); std::move(callback).Run("Invalid URL");
return; return;
} }
__block OpenExternalCallback c = callback; __block OpenExternalCallback c = std::move(callback);
dispatch_async( dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__block std::string error = OpenURL(ns_url, options.activate); __block std::string error = OpenURL(ns_url, options.activate);
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
c.Run(error); std::move(c).Run(error);
}); });
}); });
} }

View file

@ -317,9 +317,9 @@ bool OpenExternal(const base::string16& url,
void OpenExternal(const base::string16& url, void OpenExternal(const base::string16& url,
const OpenExternalOptions& options, const OpenExternalOptions& options,
const OpenExternalCallback& callback) { OpenExternalCallback callback) {
// TODO(gabriel): Implement async open if callback is specified // TODO(gabriel): Implement async open if callback is specified
callback.Run(OpenExternal(url, options) ? "" : "Failed to open"); std::move(callback).Run(OpenExternal(url, options) ? "" : "Failed to open");
} }
bool MoveItemToTrash(const base::FilePath& path) { bool MoveItemToTrash(const base::FilePath& path) {

View file

@ -11,17 +11,21 @@ namespace atom {
namespace util { namespace util {
Promise::Promise(v8::Isolate* isolate) { Promise::Promise(v8::Isolate* isolate)
auto context = isolate->GetCurrentContext(); : Promise(isolate,
auto resolver = v8::Promise::Resolver::New(context).ToLocalChecked(); v8::Promise::Resolver::New(isolate->GetCurrentContext())
isolate_ = isolate; .ToLocalChecked()) {}
context_.Reset(isolate, context); Promise::Promise(v8::Isolate* isolate, v8::Local<v8::Promise::Resolver> handle)
resolver_.Reset(isolate, resolver); : isolate_(isolate),
} context_(isolate, isolate->GetCurrentContext()),
resolver_(isolate, handle) {}
Promise::~Promise() = default; Promise::~Promise() = default;
Promise::Promise(Promise&&) = default;
Promise& Promise::operator=(Promise&&) = default;
v8::Maybe<bool> Promise::RejectWithErrorMessage(const std::string& string) { v8::Maybe<bool> Promise::RejectWithErrorMessage(const std::string& string) {
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
v8::MicrotasksScope script_scope(isolate(), v8::MicrotasksScope script_scope(isolate(),
@ -42,16 +46,28 @@ v8::Local<v8::Promise> Promise::GetHandle() const {
return GetInner()->GetPromise(); return GetInner()->GetPromise();
} }
CopyablePromise::CopyablePromise(const Promise& promise)
: isolate_(promise.isolate()), handle_(isolate_, promise.GetInner()) {}
CopyablePromise::CopyablePromise(const CopyablePromise&) = default;
CopyablePromise::~CopyablePromise() = default;
Promise CopyablePromise::GetPromise() const {
return Promise(isolate_,
v8::Local<v8::Promise::Resolver>::New(isolate_, handle_));
}
} // namespace util } // namespace util
} // namespace atom } // namespace atom
namespace mate { namespace mate {
v8::Local<v8::Value> mate::Converter<atom::util::Promise*>::ToV8( v8::Local<v8::Value> mate::Converter<atom::util::Promise>::ToV8(
v8::Isolate*, v8::Isolate*,
atom::util::Promise* val) { const atom::util::Promise& val) {
return val->GetHandle(); return val.GetHandle();
} }
} // namespace mate } // namespace mate

View file

@ -16,16 +16,30 @@ namespace atom {
namespace util { namespace util {
class Promise : public base::RefCounted<Promise> { // A wrapper around the v8::Promise.
//
// This is a move-only type that should always be `std::move`d when passed to
// callbacks, and it should be destroyed on the same thread of creation.
class Promise {
public: public:
// Create a new promise.
explicit Promise(v8::Isolate* isolate); explicit Promise(v8::Isolate* isolate);
// Wrap an existing v8 promise.
Promise(v8::Isolate* isolate, v8::Local<v8::Promise::Resolver> handle);
~Promise();
// Support moving.
Promise(Promise&&);
Promise& operator=(Promise&&);
v8::Isolate* isolate() const { return isolate_; } v8::Isolate* isolate() const { return isolate_; }
v8::Local<v8::Context> GetContext() { v8::Local<v8::Context> GetContext() {
return v8::Local<v8::Context>::New(isolate_, context_); return v8::Local<v8::Context>::New(isolate_, context_);
} }
virtual v8::Local<v8::Promise> GetHandle() const; v8::Local<v8::Promise> GetHandle() const;
v8::Maybe<bool> Resolve() { v8::Maybe<bool> Resolve() {
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
@ -87,22 +101,40 @@ class Promise : public base::RefCounted<Promise> {
v8::Maybe<bool> RejectWithErrorMessage(const std::string& error); v8::Maybe<bool> RejectWithErrorMessage(const std::string& error);
protected:
virtual ~Promise();
friend class base::RefCounted<Promise>;
v8::Isolate* isolate_;
v8::Global<v8::Context> context_;
private: private:
friend class CopyablePromise;
v8::Local<v8::Promise::Resolver> GetInner() const { v8::Local<v8::Promise::Resolver> GetInner() const {
return resolver_.Get(isolate()); return resolver_.Get(isolate());
} }
v8::Isolate* isolate_;
v8::Global<v8::Context> context_;
v8::Global<v8::Promise::Resolver> resolver_; v8::Global<v8::Promise::Resolver> resolver_;
DISALLOW_COPY_AND_ASSIGN(Promise); DISALLOW_COPY_AND_ASSIGN(Promise);
}; };
// A wrapper of Promise that can be copied.
//
// This class should only be used when we have to pass Promise to a Chromium API
// that does not take OnceCallback.
class CopyablePromise {
public:
explicit CopyablePromise(const Promise& promise);
CopyablePromise(const CopyablePromise&);
~CopyablePromise();
Promise GetPromise() const;
private:
using CopyablePersistent =
v8::CopyablePersistentTraits<v8::Promise::Resolver>::CopyablePersistent;
v8::Isolate* isolate_;
CopyablePersistent handle_;
};
} // namespace util } // namespace util
} // namespace atom } // namespace atom
@ -110,9 +142,9 @@ class Promise : public base::RefCounted<Promise> {
namespace mate { namespace mate {
template <> template <>
struct Converter<atom::util::Promise*> { struct Converter<atom::util::Promise> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
atom::util::Promise* val); const atom::util::Promise& val);
// TODO(MarshallOfSound): Implement FromV8 to allow promise chaining // TODO(MarshallOfSound): Implement FromV8 to allow promise chaining
// in native land // in native land
// static bool FromV8(v8::Isolate* isolate, // static bool FromV8(v8::Isolate* isolate,

View file

@ -75,7 +75,7 @@ class Arguments {
} }
template<typename T> template<typename T>
void Return(T val) { void Return(const T& val) {
info_->GetReturnValue().Set(ConvertToV8(isolate_, val)); info_->GetReturnValue().Set(ConvertToV8(isolate_, val));
} }