diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 11aeab5928f3..41bfa5f26ced 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -533,12 +533,11 @@ int ImportIntoCertStore(CertificateManagerModel* model, } #endif -void OnIconDataAvailable(scoped_refptr promise, - gfx::Image* icon) { +void OnIconDataAvailable(util::Promise promise, gfx::Image* icon) { if (icon && !icon->IsEmpty()) { - promise->Resolve(*icon); + promise.Resolve(*icon); } else { - promise->RejectWithErrorMessage("Failed to get file icon."); + promise.RejectWithErrorMessage("Failed to get file icon."); } } @@ -1126,7 +1125,8 @@ JumpListResult App::SetJumpList(v8::Local val, v8::Local App::GetFileIcon(const base::FilePath& path, mate::Arguments* args) { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); base::FilePath normalized_path = path.NormalizePathSeparators(); IconLoader::IconSize icon_size; @@ -1143,13 +1143,14 @@ v8::Local App::GetFileIcon(const base::FilePath& path, gfx::Image* icon = icon_manager->LookupIconFromFilepath(normalized_path, icon_size); if (icon) { - promise->Resolve(*icon); + promise.Resolve(*icon); } else { - icon_manager->LoadIcon(normalized_path, icon_size, - base::Bind(&OnIconDataAvailable, promise), - &cancelable_task_tracker_); + icon_manager->LoadIcon( + normalized_path, icon_size, + base::BindOnce(&OnIconDataAvailable, std::move(promise)), + &cancelable_task_tracker_); } - return promise->GetHandle(); + return handle; } std::vector App::GetAppMetrics(v8::Isolate* isolate) { @@ -1198,30 +1199,30 @@ v8::Local App::GetGPUFeatureStatus(v8::Isolate* isolate) { v8::Local App::GetGPUInfo(v8::Isolate* isolate, const std::string& info_type) { auto* const gpu_data_manager = content::GpuDataManagerImpl::GetInstance(); - scoped_refptr promise = new util::Promise(isolate); + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); if (info_type != "basic" && info_type != "complete") { - promise->RejectWithErrorMessage( + promise.RejectWithErrorMessage( "Invalid info type. Use 'basic' or 'complete'"); - return promise->GetHandle(); + return handle; } std::string reason; if (!gpu_data_manager->GpuAccessAllowed(&reason)) { - promise->RejectWithErrorMessage("GPU access not allowed. Reason: " + - reason); - return promise->GetHandle(); + promise.RejectWithErrorMessage("GPU access not allowed. Reason: " + reason); + return handle; } auto* const info_mgr = GPUInfoManager::GetInstance(); if (info_type == "complete") { #if defined(OS_WIN) || defined(OS_MACOSX) - info_mgr->FetchCompleteInfo(promise); + info_mgr->FetchCompleteInfo(std::move(promise)); #else - info_mgr->FetchBasicInfo(promise); + info_mgr->FetchBasicInfo(std::move(promise)); #endif } 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) { diff --git a/atom/browser/api/atom_api_content_tracing.cc b/atom/browser/api/atom_api_content_tracing.cc index d3a1d3327cbf..d2875ce8d9d7 100644 --- a/atom/browser/api/atom_api_content_tracing.cc +++ b/atom/browser/api/atom_api_content_tracing.cc @@ -66,74 +66,73 @@ scoped_refptr GetTraceDataEndpoint( result_file_path, base::Bind(callback, result_file_path)); } -void OnRecordingStopped(scoped_refptr promise, +void OnRecordingStopped(const atom::util::CopyablePromise& promise, const base::FilePath& path) { - promise->Resolve(path); + promise.GetPromise().Resolve(path); } v8::Local StopRecording(v8::Isolate* isolate, const base::FilePath& path) { - scoped_refptr promise = new atom::util::Promise(isolate); + atom::util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); - TracingController::GetInstance()->StopTracing( - GetTraceDataEndpoint(path, base::Bind(&OnRecordingStopped, promise))); - - return promise->GetHandle(); + // TODO(zcbenz): Remove the use of CopyablePromise when the + // CreateFileEndpoint API accepts OnceCallback. + TracingController::GetInstance()->StopTracing(GetTraceDataEndpoint( + path, + base::Bind(&OnRecordingStopped, atom::util::CopyablePromise(promise)))); + return handle; } -void OnCategoriesAvailable(scoped_refptr promise, +void OnCategoriesAvailable(atom::util::Promise promise, const std::set& categories) { - promise->Resolve(categories); + promise.Resolve(categories); } v8::Local GetCategories(v8::Isolate* isolate) { - scoped_refptr promise = new atom::util::Promise(isolate); - bool success = TracingController::GetInstance()->GetCategories( - base::BindOnce(&OnCategoriesAvailable, promise)); + atom::util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); - if (!success) - promise->RejectWithErrorMessage("Could not get categories."); - - return promise->GetHandle(); + // Note: This method always succeeds. + TracingController::GetInstance()->GetCategories( + base::BindOnce(&OnCategoriesAvailable, std::move(promise))); + return handle; } -void OnTracingStarted(scoped_refptr promise) { - promise->Resolve(); +void OnTracingStarted(atom::util::Promise promise) { + promise.Resolve(); } v8::Local StartTracing( v8::Isolate* isolate, const base::trace_event::TraceConfig& trace_config) { - scoped_refptr promise = new atom::util::Promise(isolate); + atom::util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); - bool success = TracingController::GetInstance()->StartTracing( - trace_config, base::BindOnce(&OnTracingStarted, promise)); - - if (!success) - promise->RejectWithErrorMessage("Could not start tracing"); - - return promise->GetHandle(); + // Note: This method always succeeds. + TracingController::GetInstance()->StartTracing( + trace_config, base::BindOnce(&OnTracingStarted, std::move(promise))); + return handle; } -void OnTraceBufferUsageAvailable(scoped_refptr promise, +void OnTraceBufferUsageAvailable(atom::util::Promise promise, float percent_full, 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("value", approximate_count); - promise->Resolve(dict.GetHandle()); + promise.Resolve(dict.GetHandle()); } v8::Local GetTraceBufferUsage(v8::Isolate* isolate) { - scoped_refptr promise = new atom::util::Promise(isolate); - bool success = TracingController::GetInstance()->GetTraceBufferUsage( - base::BindOnce(&OnTraceBufferUsageAvailable, promise)); + atom::util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); - if (!success) - promise->RejectWithErrorMessage("Could not get trace buffer usage."); - - return promise->GetHandle(); + // Note: This method always succeeds. + TracingController::GetInstance()->GetTraceBufferUsage( + base::BindOnce(&OnTraceBufferUsageAvailable, std::move(promise))); + return handle; } void Initialize(v8::Local exports, diff --git a/atom/browser/api/atom_api_cookies.cc b/atom/browser/api/atom_api_cookies.cc index 6adff0110cba..a77de4c08670 100644 --- a/atom/browser/api/atom_api_cookies.cc +++ b/atom/browser/api/atom_api_cookies.cc @@ -136,29 +136,29 @@ inline net::CookieStore* GetCookieStore( return getter->GetURLRequestContext()->cookie_store(); } -void ResolvePromiseWithCookies(scoped_refptr promise, - net::CookieList cookieList) { - promise->Resolve(cookieList); +void ResolvePromiseWithCookies(util::Promise promise, + const net::CookieList& cookie_list) { + promise.Resolve(cookie_list); } -void ResolvePromise(scoped_refptr promise) { - promise->Resolve(); +void ResolvePromise(util::Promise promise) { + promise.Resolve(); } // Resolve |promise| in UI thread. -void ResolvePromiseInUI(scoped_refptr promise) { +void ResolvePromiseInUI(util::Promise promise) { base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, base::BindOnce(ResolvePromise, std::move(promise))); } // Run |callback| on UI thread. -void RunCallbackInUI(const base::Closure& callback) { - base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback); +void RunCallbackInUI(base::OnceClosure callback) { + base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, std::move(callback)); } // Remove cookies from |list| not matching |filter|, and pass it to |callback|. void FilterCookies(std::unique_ptr filter, - scoped_refptr promise, + util::Promise promise, const net::CookieList& list) { net::CookieList result; for (const auto& cookie : list) { @@ -174,50 +174,50 @@ void FilterCookies(std::unique_ptr filter, // Receives cookies matching |filter| in IO thread. void GetCookiesOnIO(scoped_refptr getter, std::unique_ptr filter, - scoped_refptr promise) { + util::Promise promise) { std::string url; filter->GetString("url", &url); 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. if (url.empty()) - GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback); + GetCookieStore(getter)->GetAllCookiesAsync(std::move(filtered_callback)); else - GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url), - filtered_callback); + GetCookieStore(getter)->GetAllCookiesForURLAsync( + GURL(url), std::move(filtered_callback)); } // Removes cookie with |url| and |name| in IO thread. void RemoveCookieOnIO(scoped_refptr getter, const GURL& url, const std::string& name, - scoped_refptr promise) { + util::Promise promise) { GetCookieStore(getter)->DeleteCookieAsync( url, name, base::BindOnce(ResolvePromiseInUI, std::move(promise))); } // Resolves/rejects the |promise| in UI thread. -void SettlePromiseInUI(scoped_refptr promise, - const std::string& errmsg) { +void SettlePromiseInUI(util::Promise promise, const std::string& errmsg) { if (errmsg.empty()) { - promise->Resolve(); + promise.Resolve(); } else { - promise->RejectWithErrorMessage(errmsg); + promise.RejectWithErrorMessage(errmsg); } } // Callback of SetCookie. -void OnSetCookie(scoped_refptr promise, bool success) { +void OnSetCookie(util::Promise promise, bool success) { 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. void FlushCookieStoreOnIOThread( scoped_refptr getter, - scoped_refptr promise) { + util::Promise promise) { GetCookieStore(getter)->FlushStore( base::BindOnce(ResolvePromiseInUI, std::move(promise))); } @@ -225,7 +225,7 @@ void FlushCookieStoreOnIOThread( // Sets cookie with |details| in IO thread. void SetCookieOnIO(scoped_refptr getter, std::unique_ptr details, - scoped_refptr promise) { + util::Promise promise) { std::string url, name, value, domain, path; bool secure = false; bool http_only = false; @@ -297,7 +297,8 @@ Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context) Cookies::~Cookies() {} v8::Local Cookies::Get(const base::DictionaryValue& filter) { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); auto copy = base::DictionaryValue::From( base::Value::ToUniquePtrValue(filter.Clone())); @@ -305,26 +306,28 @@ v8::Local Cookies::Get(const base::DictionaryValue& filter) { base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce(GetCookiesOnIO, base::RetainedRef(getter), std::move(copy), - promise)); + std::move(promise))); - return promise->GetHandle(); + return handle; } v8::Local Cookies::Remove(const GURL& url, const std::string& name) { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); auto* getter = browser_context_->GetRequestContext(); base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce(RemoveCookieOnIO, base::RetainedRef(getter), url, name, - promise)); + std::move(promise))); - return promise->GetHandle(); + return handle; } v8::Local Cookies::Set(const base::DictionaryValue& details) { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); auto copy = base::DictionaryValue::From( base::Value::ToUniquePtrValue(details.Clone())); @@ -332,20 +335,22 @@ v8::Local Cookies::Set(const base::DictionaryValue& details) { base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce(SetCookieOnIO, base::RetainedRef(getter), std::move(copy), - promise)); + std::move(promise))); - return promise->GetHandle(); + return handle; } v8::Local Cookies::FlushStore() { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); auto* getter = browser_context_->GetRequestContext(); - base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(FlushCookieStoreOnIOThread, - base::RetainedRef(getter), promise)); + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(FlushCookieStoreOnIOThread, base::RetainedRef(getter), + std::move(promise))); - return promise->GetHandle(); + return handle; } void Cookies::OnCookieChanged(const CookieDetails* details) { diff --git a/atom/browser/api/atom_api_debugger.cc b/atom/browser/api/atom_api_debugger.cc index d5ed58bed4d3..1016103fa3c8 100644 --- a/atom/browser/api/atom_api_debugger.cc +++ b/atom/browser/api/atom_api_debugger.cc @@ -65,21 +65,21 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host, if (it == pending_requests_.end()) return; - scoped_refptr promise = it->second; + atom::util::Promise promise = std::move(it->second); pending_requests_.erase(it); base::DictionaryValue* error = nullptr; if (dict->GetDictionary("error", &error)) { std::string message; error->GetString("message", &message); - promise->RejectWithErrorMessage(message); + promise.RejectWithErrorMessage(message); } else { base::DictionaryValue* result_body = nullptr; base::DictionaryValue result; if (dict->GetDictionary("result", &result_body)) { result.Swap(result_body); } - promise->Resolve(result); + promise.Resolve(result); } } } @@ -129,17 +129,18 @@ void Debugger::Detach() { } v8::Local Debugger::SendCommand(mate::Arguments* args) { - scoped_refptr promise = new util::Promise(isolate()); + atom::util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); if (!agent_host_) { - promise->RejectWithErrorMessage("No target available"); - return promise->GetHandle(); + promise.RejectWithErrorMessage("No target available"); + return handle; } std::string method; if (!args->GetNext(&method)) { - promise->RejectWithErrorMessage("Invalid method"); - return promise->GetHandle(); + promise.RejectWithErrorMessage("Invalid method"); + return handle; } base::DictionaryValue command_params; @@ -147,7 +148,7 @@ v8::Local Debugger::SendCommand(mate::Arguments* args) { base::DictionaryValue request; 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.SetString("method", method); if (!command_params.empty()) @@ -158,12 +159,12 @@ v8::Local Debugger::SendCommand(mate::Arguments* args) { base::JSONWriter::Write(request, &json_args); agent_host_->DispatchProtocolMessage(this, json_args); - return promise->GetHandle(); + return handle; } void Debugger::ClearPendingRequests() { - for (const auto& it : pending_requests_) - it.second->RejectWithErrorMessage("target closed while handling command"); + for (auto& it : pending_requests_) + it.second.RejectWithErrorMessage("target closed while handling command"); } // static diff --git a/atom/browser/api/atom_api_debugger.h b/atom/browser/api/atom_api_debugger.h index b44ab8721c85..291ecdc53b10 100644 --- a/atom/browser/api/atom_api_debugger.h +++ b/atom/browser/api/atom_api_debugger.h @@ -54,7 +54,7 @@ class Debugger : public mate::TrackableObject, content::RenderFrameHost* new_rfh) override; private: - using PendingRequestMap = std::map>; + using PendingRequestMap = std::map; void Attach(mate::Arguments* args); bool IsAttached(); diff --git a/atom/browser/api/atom_api_net_log.cc b/atom/browser/api/atom_api_net_log.cc index 793731738c1c..6f77dcac07c2 100644 --- a/atom/browser/api/atom_api_net_log.cc +++ b/atom/browser/api/atom_api_net_log.cc @@ -22,9 +22,9 @@ namespace { -void OnGetFilePathToCompletedLog(scoped_refptr promise, +void OnGetFilePathToCompletedLog(const atom::util::CopyablePromise& promise, const base::FilePath& file_path) { - promise->Resolve(file_path); + promise.GetPromise().Resolve(file_path); } } // namespace @@ -97,16 +97,17 @@ std::string NetLog::GetCurrentlyLoggingPath() const { } v8::Local NetLog::StopLogging(mate::Arguments* args) { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); if (IsCurrentlyLogging()) { - stop_callback_queue_.emplace_back(promise); + stop_callback_queue_.emplace_back(std::move(promise)); net_log_writer_->StopNetLog(nullptr); } else { - promise->Resolve(base::FilePath()); + promise.Resolve(base::FilePath()); } - return promise->GetHandle(); + return handle; } void NetLog::OnNewState(const base::DictionaryValue& state) { @@ -117,8 +118,10 @@ void NetLog::OnNewState(const base::DictionaryValue& state) { if (GetLoggingState() == "NOT_LOGGING") { for (auto& promise : stop_callback_queue_) { - net_log_writer_->GetFilePathToCompletedLog( - base::Bind(&OnGetFilePathToCompletedLog, promise)); + // TODO(zcbenz): Remove the use of CopyablePromise when the + // GetFilePathToCompletedLog API accepts OnceCallback. + net_log_writer_->GetFilePathToCompletedLog(base::Bind( + &OnGetFilePathToCompletedLog, util::CopyablePromise(promise))); } stop_callback_queue_.clear(); } diff --git a/atom/browser/api/atom_api_net_log.h b/atom/browser/api/atom_api_net_log.h index b71677a12867..360a0b324958 100644 --- a/atom/browser/api/atom_api_net_log.h +++ b/atom/browser/api/atom_api_net_log.h @@ -47,7 +47,7 @@ class NetLog : public mate::TrackableObject, private: AtomBrowserContext* browser_context_; net_log::NetExportFileWriter* net_log_writer_; - std::list> stop_callback_queue_; + std::list stop_callback_queue_; std::unique_ptr net_log_state_; DISALLOW_COPY_AND_ASSIGN(NetLog); diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 7f6514059031..05694fddf6cb 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -177,21 +177,22 @@ bool IsProtocolHandledInIO( return is_handled; } -void PromiseCallback(scoped_refptr promise, bool handled) { - promise->Resolve(handled); +void PromiseCallback(util::Promise promise, bool handled) { + promise.Resolve(handled); } v8::Local Protocol::IsProtocolHandled(const std::string& scheme) { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); auto* getter = static_cast( browser_context_->GetRequestContext()); base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {content::BrowserThread::IO}, - base::Bind(&IsProtocolHandledInIO, base::RetainedRef(getter), scheme), - base::Bind(&PromiseCallback, promise)); + base::BindOnce(&IsProtocolHandledInIO, base::RetainedRef(getter), scheme), + base::BindOnce(&PromiseCallback, std::move(promise))); - return promise->GetHandle(); + return handle; } void Protocol::UninterceptProtocol(const std::string& scheme, diff --git a/atom/browser/api/atom_api_system_preferences_mac.mm b/atom/browser/api/atom_api_system_preferences_mac.mm index 8d65153eab76..4ea8e2bcb2de 100644 --- a/atom/browser/api/atom_api_system_preferences_mac.mm +++ b/atom/browser/api/atom_api_system_preferences_mac.mm @@ -457,19 +457,20 @@ bool SystemPreferences::CanPromptTouchID() { return false; } -void OnTouchIDCompleted(scoped_refptr promise) { - promise->Resolve(); +void OnTouchIDCompleted(util::Promise promise) { + promise.Resolve(); } -void OnTouchIDFailed(scoped_refptr promise, - const std::string& reason) { - promise->RejectWithErrorMessage(reason); +void OnTouchIDFailed(util::Promise promise, const std::string& reason) { + promise.RejectWithErrorMessage(reason); } v8::Local SystemPreferences::PromptTouchID( v8::Isolate* isolate, const std::string& reason) { - scoped_refptr promise = new util::Promise(isolate); + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); + if (@available(macOS 10.12.2, *)) { base::scoped_nsobject context([[LAContext alloc] init]); base::ScopedCFTypeRef access_control = @@ -484,6 +485,7 @@ v8::Local SystemPreferences::PromptTouchID( scoped_refptr runner = base::SequencedTaskRunnerHandle::Get(); + __block util::Promise p = std::move(promise); [context evaluateAccessControl:access_control operation:LAAccessControlOperationUseKeySign @@ -493,20 +495,20 @@ v8::Local SystemPreferences::PromptTouchID( runner->PostTask( FROM_HERE, base::BindOnce( - &OnTouchIDFailed, promise, + &OnTouchIDFailed, std::move(p), std::string([error.localizedDescription UTF8String]))); } else { - runner->PostTask( - FROM_HERE, - base::BindOnce(&OnTouchIDCompleted, promise)); + runner->PostTask(FROM_HERE, + base::BindOnce(&OnTouchIDCompleted, + std::move(p))); } }]; } else { - promise->RejectWithErrorMessage( + promise.RejectWithErrorMessage( "This API is not available on macOS versions older than 10.12.2"); } - return promise->GetHandle(); + return handle; } // static @@ -625,25 +627,27 @@ std::string SystemPreferences::GetMediaAccessStatus( v8::Local SystemPreferences::AskForMediaAccess( v8::Isolate* isolate, const std::string& media_type) { - scoped_refptr promise = new util::Promise(isolate); + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); if (auto type = ParseMediaType(media_type)) { if (@available(macOS 10.14, *)) { + __block util::Promise p = std::move(promise); [AVCaptureDevice requestAccessForMediaType:type completionHandler:^(BOOL granted) { dispatch_async(dispatch_get_main_queue(), ^{ - promise->Resolve(!!granted); + p.Resolve(!!granted); }); }]; } else { // access always allowed pre-10.14 Mojave - promise->Resolve(true); + promise.Resolve(true); } } else { - promise->RejectWithErrorMessage("Invalid media type"); + promise.RejectWithErrorMessage("Invalid media type"); } - return promise->GetHandle(); + return handle; } void SystemPreferences::RemoveUserDefault(const std::string& name) { diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 6ea37533cd3d..26ee56082099 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -241,12 +241,11 @@ namespace api { namespace { // Called when CapturePage is done. -void OnCapturePageDone(scoped_refptr promise, - const SkBitmap& bitmap) { +void OnCapturePageDone(util::Promise promise, const SkBitmap& bitmap) { // Hack to enable transparency in captured image // TODO(nitsakh) Remove hack once fixed in chromium const_cast(bitmap).setAlphaType(kPremul_SkAlphaType); - promise->Resolve(gfx::Image::CreateFrom1xBitmap(bitmap)); + promise.Resolve(gfx::Image::CreateFrom1xBitmap(bitmap)); } } // namespace @@ -1302,14 +1301,12 @@ std::string WebContents::GetUserAgent() { v8::Local WebContents::SavePage( const base::FilePath& full_file_path, const content::SavePageType& save_type) { - scoped_refptr promise = new util::Promise(isolate()); - auto* handler = new SavePageHandler(web_contents(), promise); + util::Promise promise(isolate()); + v8::Local ret = promise.GetHandle(); - const bool saveStarted = handler->Handle(full_file_path, save_type); - if (!saveStarted) - promise->RejectWithErrorMessage("Failed to save the page"); - - return promise->GetHandle(); + auto* handler = new SavePageHandler(web_contents(), std::move(promise)); + handler->Handle(full_file_path, save_type); + return ret; } void WebContents::OpenDevTools(mate::Arguments* args) { @@ -1506,10 +1503,11 @@ std::vector WebContents::GetPrinterList() { v8::Local WebContents::PrintToPDF( const base::DictionaryValue& settings) { - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); PrintPreviewMessageHandler::FromWebContents(web_contents()) - ->PrintToPDF(settings, promise); - return promise->GetHandle(); + ->PrintToPDF(settings, std::move(promise)); + return handle; } #endif @@ -1780,15 +1778,16 @@ void WebContents::StartDrag(const mate::Dictionary& item, v8::Local WebContents::CapturePage(mate::Arguments* args) { gfx::Rect rect; - scoped_refptr promise = new util::Promise(isolate()); + util::Promise promise(isolate()); + v8::Local handle = promise.GetHandle(); // get rect arguments if they exist args->GetNext(&rect); auto* const view = web_contents()->GetRenderWidgetHostView(); if (!view) { - promise->Resolve(gfx::Image()); - return promise->GetHandle(); + promise.Resolve(gfx::Image()); + return handle; } // Capture full page if user doesn't specify a |rect|. @@ -1807,8 +1806,8 @@ v8::Local WebContents::CapturePage(mate::Arguments* args) { bitmap_size = gfx::ScaleToCeiledSize(view_size, scale); view->CopyFromSurface(gfx::Rect(rect.origin(), view_size), bitmap_size, - base::BindOnce(&OnCapturePageDone, promise)); - return promise->GetHandle(); + base::BindOnce(&OnCapturePageDone, std::move(promise))); + return handle; } void WebContents::OnCursorChange(const content::WebCursor& cursor) { diff --git a/atom/browser/api/gpuinfo_manager.cc b/atom/browser/api/gpuinfo_manager.cc index 4dda3eb5e128..dbc52f84aca4 100644 --- a/atom/browser/api/gpuinfo_manager.cc +++ b/atom/browser/api/gpuinfo_manager.cc @@ -3,6 +3,9 @@ // found in the LICENSE file. #include "atom/browser/api/gpuinfo_manager.h" + +#include + #include "atom/browser/api/gpu_info_enumerator.h" #include "base/memory/singleton.h" #include "base/threading/thread_task_runner_handle.h" @@ -42,8 +45,8 @@ void GPUInfoManager::ProcessCompleteInfo() { const auto result = EnumerateGPUInfo(gpu_data_manager_->GetGPUInfo()); // We have received the complete information, resolve all promises that // were waiting for this info. - for (const auto& promise : complete_info_promise_set_) { - promise->Resolve(*result); + for (auto& promise : complete_info_promise_set_) { + promise.Resolve(*result); } complete_info_promise_set_.clear(); } @@ -58,8 +61,8 @@ void GPUInfoManager::OnGpuInfoUpdate() { } // Should be posted to the task runner -void GPUInfoManager::CompleteInfoFetcher(scoped_refptr promise) { - complete_info_promise_set_.push_back(promise); +void GPUInfoManager::CompleteInfoFetcher(util::Promise promise) { + complete_info_promise_set_.emplace_back(std::move(promise)); if (NeedsCompleteGpuInfoCollection()) { gpu_data_manager_->RequestCompleteGpuInfoIfNeeded(); @@ -68,18 +71,18 @@ void GPUInfoManager::CompleteInfoFetcher(scoped_refptr promise) { } } -void GPUInfoManager::FetchCompleteInfo(scoped_refptr promise) { +void GPUInfoManager::FetchCompleteInfo(util::Promise promise) { base::ThreadTaskRunnerHandle::Get()->PostTask( 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. // There cannot be multiple promises as they are resolved synchronously. -void GPUInfoManager::FetchBasicInfo(scoped_refptr promise) { +void GPUInfoManager::FetchBasicInfo(util::Promise promise) { gpu::GPUInfo gpu_info; CollectBasicGraphicsInfo(&gpu_info); - promise->Resolve(*EnumerateGPUInfo(gpu_info)); + promise.Resolve(*EnumerateGPUInfo(gpu_info)); } std::unique_ptr GPUInfoManager::EnumerateGPUInfo( diff --git a/atom/browser/api/gpuinfo_manager.h b/atom/browser/api/gpuinfo_manager.h index 46955192203c..18749f6f562a 100644 --- a/atom/browser/api/gpuinfo_manager.h +++ b/atom/browser/api/gpuinfo_manager.h @@ -25,8 +25,8 @@ class GPUInfoManager : public content::GpuDataManagerObserver { GPUInfoManager(); ~GPUInfoManager() override; bool NeedsCompleteGpuInfoCollection() const; - void FetchCompleteInfo(scoped_refptr promise); - void FetchBasicInfo(scoped_refptr promise); + void FetchCompleteInfo(util::Promise promise); + void FetchBasicInfo(util::Promise promise); void OnGpuInfoUpdate() override; private: @@ -34,12 +34,12 @@ class GPUInfoManager : public content::GpuDataManagerObserver { gpu::GPUInfo gpu_info) const; // These should be posted to the task queue - void CompleteInfoFetcher(scoped_refptr promise); + void CompleteInfoFetcher(util::Promise promise); void ProcessCompleteInfo(); // This set maintains all the promises that should be fulfilled // once we have the complete information data - std::vector> complete_info_promise_set_; + std::vector complete_info_promise_set_; content::GpuDataManager* gpu_data_manager_; DISALLOW_COPY_AND_ASSIGN(GPUInfoManager); diff --git a/atom/browser/api/save_page_handler.cc b/atom/browser/api/save_page_handler.cc index 86c937835c64..654257681df9 100644 --- a/atom/browser/api/save_page_handler.cc +++ b/atom/browser/api/save_page_handler.cc @@ -5,6 +5,7 @@ #include "atom/browser/api/save_page_handler.h" #include +#include #include "atom/browser/atom_browser_context.h" #include "base/callback.h" @@ -16,8 +17,8 @@ namespace atom { namespace api { SavePageHandler::SavePageHandler(content::WebContents* web_contents, - scoped_refptr promise) - : web_contents_(web_contents), promise_(promise) {} + util::Promise promise) + : web_contents_(web_contents), promise_(std::move(promise)) {} SavePageHandler::~SavePageHandler() {} @@ -43,17 +44,19 @@ bool SavePageHandler::Handle(const base::FilePath& full_path, download_manager->RemoveObserver(this); // If initialization fails which means fail to create |DownloadItem|, we need // to delete the |SavePageHandler| instance to avoid memory-leak. - if (!result) + if (!result) { + promise_.RejectWithErrorMessage("Failed to save the page"); delete this; + } return result; } void SavePageHandler::OnDownloadUpdated(download::DownloadItem* item) { if (item->IsDone()) { if (item->GetState() == download::DownloadItem::COMPLETE) - promise_->Resolve(); + promise_.Resolve(); else - promise_->RejectWithErrorMessage("Failed to save the page."); + promise_.RejectWithErrorMessage("Failed to save the page."); Destroy(item); } } diff --git a/atom/browser/api/save_page_handler.h b/atom/browser/api/save_page_handler.h index b929bb53660c..51ef4e5320a4 100644 --- a/atom/browser/api/save_page_handler.h +++ b/atom/browser/api/save_page_handler.h @@ -30,7 +30,7 @@ class SavePageHandler : public content::DownloadManager::Observer, public download::DownloadItem::Observer { public: SavePageHandler(content::WebContents* web_contents, - scoped_refptr promise); + atom::util::Promise promise); ~SavePageHandler() override; bool Handle(const base::FilePath& full_path, @@ -47,7 +47,7 @@ class SavePageHandler : public content::DownloadManager::Observer, void OnDownloadUpdated(download::DownloadItem* item) override; content::WebContents* web_contents_; // weak - scoped_refptr promise_; + atom::util::Promise promise_; }; } // namespace api diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index e4962b12e862..8e5b3043088e 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -165,14 +165,14 @@ void Browser::DidFinishLaunching(const base::DictionaryValue& launch_info) { observer.OnFinishLaunching(launch_info); } -util::Promise* Browser::WhenReady(v8::Isolate* isolate) { +const util::Promise& Browser::WhenReady(v8::Isolate* isolate) { if (!ready_promise_) { - ready_promise_ = new util::Promise(isolate); + ready_promise_.reset(new util::Promise(isolate)); if (is_ready()) { ready_promise_->Resolve(); } } - return ready_promise_; + return *ready_promise_; } void Browser::OnAccessibilitySupportChanged() { diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 0f16c67ba8b9..9ee0b8848568 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -253,7 +253,7 @@ class Browser : public WindowListObserver { bool is_shutting_down() const { return is_shutdown_; } bool is_quiting() const { return is_quiting_; } bool is_ready() const { return is_ready_; } - util::Promise* WhenReady(v8::Isolate* isolate); + const util::Promise& WhenReady(v8::Isolate* isolate); protected: // Returns the version of application bundle or executable file. @@ -292,7 +292,7 @@ class Browser : public WindowListObserver { int badge_count_ = 0; - util::Promise* ready_promise_ = nullptr; + std::unique_ptr ready_promise_; #if defined(OS_LINUX) || defined(OS_MACOSX) base::DictionaryValue about_panel_options_; diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index ab757dc00002..2913a0687d59 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -342,7 +342,9 @@ bool Browser::DockIsVisible() { } v8::Local Browser::DockShow(v8::Isolate* isolate) { - scoped_refptr promise = new util::Promise(isolate); + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); + BOOL active = [[NSRunningApplication currentApplication] isActive]; ProcessSerialNumber psn = {0, kCurrentProcess}; if (active) { @@ -354,6 +356,7 @@ v8::Local Browser::DockShow(v8::Isolate* isolate) { [app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; break; } + __block util::Promise p = std::move(promise); dispatch_time_t one_ms = dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC); dispatch_after(one_ms, dispatch_get_main_queue(), ^{ TransformProcessType(&psn, kProcessTransformToForegroundApplication); @@ -361,14 +364,14 @@ v8::Local Browser::DockShow(v8::Isolate* isolate) { dispatch_after(one_ms, dispatch_get_main_queue(), ^{ [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps]; - promise->Resolve(); + p.Resolve(); }); }); } else { TransformProcessType(&psn, kProcessTransformToForegroundApplication); - promise->Resolve(); + promise.Resolve(); } - return promise->GetHandle(); + return handle; } void Browser::DockSetMenu(AtomMenuModel* model) { diff --git a/atom/browser/printing/print_preview_message_handler.cc b/atom/browser/printing/print_preview_message_handler.cc index 3d703695d563..c10c4649c265 100644 --- a/atom/browser/printing/print_preview_message_handler.cc +++ b/atom/browser/printing/print_preview_message_handler.cc @@ -143,10 +143,10 @@ void PrintPreviewMessageHandler::OnPrintPreviewCancelled( void PrintPreviewMessageHandler::PrintToPDF( const base::DictionaryValue& options, - scoped_refptr promise) { + atom::util::Promise promise) { int 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* rfh = focused_frame && focused_frame->HasSelection() @@ -155,12 +155,11 @@ void PrintPreviewMessageHandler::PrintToPDF( rfh->Send(new PrintMsg_PrintPreview(rfh->GetRoutingID(), options)); } -scoped_refptr PrintPreviewMessageHandler::GetPromise( - int request_id) { +util::Promise PrintPreviewMessageHandler::GetPromise(int request_id) { auto it = promise_map_.find(request_id); DCHECK(it != promise_map_.end()); - auto promise = it->second; + util::Promise promise = std::move(it->second); promise_map_.erase(it); return promise; @@ -171,13 +170,13 @@ void PrintPreviewMessageHandler::ResolvePromise( scoped_refptr data_bytes) { 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); v8::HandleScope handle_scope(isolate); v8::Context::Scope context_scope( - v8::Local::New(isolate, promise->GetContext())); + v8::Local::New(isolate, promise.GetContext())); v8::Local buffer = node::Buffer::Copy(isolate, @@ -185,14 +184,14 @@ void PrintPreviewMessageHandler::ResolvePromise( data_bytes->size()) .ToLocalChecked(); - promise->Resolve(buffer); + promise.Resolve(buffer); } void PrintPreviewMessageHandler::RejectPromise(int request_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - auto promise = GetPromise(request_id); - promise->RejectWithErrorMessage("Failed to generate PDF"); + util::Promise promise = GetPromise(request_id); + promise.RejectWithErrorMessage("Failed to generate PDF"); } WEB_CONTENTS_USER_DATA_KEY_IMPL(PrintPreviewMessageHandler) diff --git a/atom/browser/printing/print_preview_message_handler.h b/atom/browser/printing/print_preview_message_handler.h index 05fd0faa7da6..dfd96d5d57fa 100644 --- a/atom/browser/printing/print_preview_message_handler.h +++ b/atom/browser/printing/print_preview_message_handler.h @@ -31,8 +31,7 @@ class PrintPreviewMessageHandler public: ~PrintPreviewMessageHandler() override; - void PrintToPDF(const base::DictionaryValue& options, - scoped_refptr promise); + void PrintToPDF(const base::DictionaryValue& options, util::Promise promise); protected: // content::WebContentsObserver implementation. @@ -56,13 +55,13 @@ class PrintPreviewMessageHandler void OnPrintPreviewCancelled(int document_cookie, const PrintHostMsg_PreviewIds& ids); - scoped_refptr GetPromise(int request_id); + util::Promise GetPromise(int request_id); void ResolvePromise(int request_id, scoped_refptr data_bytes); void RejectPromise(int request_id); - using PromiseMap = std::map>; + using PromiseMap = std::map; PromiseMap promise_map_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/atom/common/api/atom_api_shell.cc b/atom/common/api/atom_api_shell.cc index a52dd74b8907..aa735ebd7618 100644 --- a/atom/common/api/atom_api_shell.cc +++ b/atom/common/api/atom_api_shell.cc @@ -44,12 +44,12 @@ struct Converter { namespace { -void OnOpenExternalFinished(scoped_refptr promise, +void OnOpenExternalFinished(atom::util::Promise promise, const std::string& error) { if (error.empty()) - promise->Resolve(); + promise.Resolve(); else - promise->RejectWithErrorMessage(error.c_str()); + promise.RejectWithErrorMessage(error.c_str()); } bool OpenExternalSync( @@ -78,8 +78,7 @@ v8::Local OpenExternal( const GURL& url, #endif mate::Arguments* args) { - scoped_refptr promise = - new atom::util::Promise(args->isolate()); + atom::util::Promise promise(args->isolate()); platform_util::OpenExternalOptions options; if (args->Length() >= 2) { @@ -90,10 +89,11 @@ v8::Local OpenExternal( } } - platform_util::OpenExternal(url, options, - base::Bind(&OnOpenExternalFinished, promise)); - - return promise->GetHandle(); + v8::Local handle = promise.GetHandle(); + platform_util::OpenExternal( + url, options, + base::BindOnce(&OnOpenExternalFinished, std::move(promise))); + return handle; } #if defined(OS_WIN) diff --git a/atom/common/api/atom_bindings.cc b/atom/common/api/atom_bindings.cc index 0382577ddd10..677427a670f1 100644 --- a/atom/common/api/atom_bindings.cc +++ b/atom/common/api/atom_bindings.cc @@ -17,7 +17,6 @@ #include "atom/common/heap_snapshot.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" -#include "atom/common/promise_util.h" #include "base/logging.h" #include "base/process/process.h" #include "base/process/process_handle.h" @@ -233,30 +232,31 @@ v8::Local AtomBindings::GetSystemMemoryInfo(v8::Isolate* isolate, // static v8::Local AtomBindings::GetProcessMemoryInfo( v8::Isolate* isolate) { - scoped_refptr promise = new util::Promise(isolate); + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); if (mate::Locker::IsBrowserProcess() && !Browser::Get()->is_ready()) { - promise->RejectWithErrorMessage( + promise.RejectWithErrorMessage( "Memory Info is available only after app ready"); - return promise->GetHandle(); + return handle; } v8::Global context(isolate, isolate->GetCurrentContext()); memory_instrumentation::MemoryInstrumentation::GetInstance() - ->RequestGlobalDumpForPid(base::GetCurrentProcId(), - std::vector(), - base::Bind(&AtomBindings::DidReceiveMemoryDump, - std::move(context), promise)); - return promise->GetHandle(); + ->RequestGlobalDumpForPid( + base::GetCurrentProcId(), std::vector(), + base::BindOnce(&AtomBindings::DidReceiveMemoryDump, + std::move(context), std::move(promise))); + return handle; } // static void AtomBindings::DidReceiveMemoryDump( - const v8::Global& context, - scoped_refptr promise, + v8::Global context, + util::Promise promise, bool success, std::unique_ptr global_dump) { - v8::Isolate* isolate = promise->isolate(); + v8::Isolate* isolate = promise.isolate(); mate::Locker locker(isolate); v8::HandleScope handle_scope(isolate); v8::MicrotasksScope script_scope(isolate, @@ -265,7 +265,7 @@ void AtomBindings::DidReceiveMemoryDump( v8::Local::New(isolate, context)); if (!success) { - promise->RejectWithErrorMessage("Failed to create memory dump"); + promise.RejectWithErrorMessage("Failed to create memory dump"); return; } @@ -280,13 +280,13 @@ void AtomBindings::DidReceiveMemoryDump( #endif dict.Set("private", osdump.private_footprint_kb); dict.Set("shared", osdump.shared_footprint_kb); - promise->Resolve(dict.GetHandle()); + promise.Resolve(dict.GetHandle()); resolved = true; break; } } if (!resolved) { - promise->RejectWithErrorMessage( + promise.RejectWithErrorMessage( R"(Failed to find current process memory details in memory dump)"); } } diff --git a/atom/common/api/atom_bindings.h b/atom/common/api/atom_bindings.h index b83d756e7d77..70b2382cd836 100644 --- a/atom/common/api/atom_bindings.h +++ b/atom/common/api/atom_bindings.h @@ -8,6 +8,7 @@ #include #include +#include "atom/common/promise_util.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" @@ -31,10 +32,6 @@ class Environment; namespace atom { -namespace util { -class Promise; -} - class AtomBindings { public: explicit AtomBindings(uv_loop_t* loop); @@ -72,8 +69,8 @@ class AtomBindings { static void OnCallNextTick(uv_async_t* handle); static void DidReceiveMemoryDump( - const v8::Global& context, - scoped_refptr promise, + v8::Global context, + util::Promise promise, bool success, std::unique_ptr dump); diff --git a/atom/common/platform_util.h b/atom/common/platform_util.h index da36f56b67ed..989cb206b739 100644 --- a/atom/common/platform_util.h +++ b/atom/common/platform_util.h @@ -19,7 +19,7 @@ class GURL; namespace platform_util { -typedef base::Callback OpenExternalCallback; +typedef base::OnceCallback OpenExternalCallback; // Show the given file in a file manager. If possible, select the file. // Must be called from the UI thread. @@ -52,7 +52,7 @@ void OpenExternal( const GURL& url, #endif const OpenExternalOptions& options, - const OpenExternalCallback& callback); + OpenExternalCallback callback); // Move a file to trash. bool MoveItemToTrash(const base::FilePath& full_path); diff --git a/atom/common/platform_util_linux.cc b/atom/common/platform_util_linux.cc index 55414633ce92..9505af167528 100644 --- a/atom/common/platform_util_linux.cc +++ b/atom/common/platform_util_linux.cc @@ -92,9 +92,9 @@ bool OpenExternal(const GURL& url, const OpenExternalOptions& options) { void OpenExternal(const GURL& url, const OpenExternalOptions& options, - const OpenExternalCallback& callback) { + OpenExternalCallback callback) { // 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) { diff --git a/atom/common/platform_util_mac.mm b/atom/common/platform_util_mac.mm index 8e073f5060cc..87d55bf21eb5 100644 --- a/atom/common/platform_util_mac.mm +++ b/atom/common/platform_util_mac.mm @@ -106,19 +106,19 @@ bool OpenExternal(const GURL& url, const OpenExternalOptions& options) { void OpenExternal(const GURL& url, const OpenExternalOptions& options, - const OpenExternalCallback& callback) { + OpenExternalCallback callback) { NSURL* ns_url = net::NSURLWithGURL(url); if (!ns_url) { - callback.Run("Invalid URL"); + std::move(callback).Run("Invalid URL"); return; } - __block OpenExternalCallback c = callback; + __block OpenExternalCallback c = std::move(callback); dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ __block std::string error = OpenURL(ns_url, options.activate); dispatch_async(dispatch_get_main_queue(), ^{ - c.Run(error); + std::move(c).Run(error); }); }); } diff --git a/atom/common/platform_util_win.cc b/atom/common/platform_util_win.cc index a19d74fc3009..6d2c3aa4aebc 100644 --- a/atom/common/platform_util_win.cc +++ b/atom/common/platform_util_win.cc @@ -317,9 +317,9 @@ bool OpenExternal(const base::string16& url, void OpenExternal(const base::string16& url, const OpenExternalOptions& options, - const OpenExternalCallback& callback) { + OpenExternalCallback callback) { // 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) { diff --git a/atom/common/promise_util.cc b/atom/common/promise_util.cc index bf4f9ecca848..82b05f06f02d 100644 --- a/atom/common/promise_util.cc +++ b/atom/common/promise_util.cc @@ -11,17 +11,21 @@ namespace atom { namespace util { -Promise::Promise(v8::Isolate* isolate) { - auto context = isolate->GetCurrentContext(); - auto resolver = v8::Promise::Resolver::New(context).ToLocalChecked(); - isolate_ = isolate; +Promise::Promise(v8::Isolate* isolate) + : Promise(isolate, + v8::Promise::Resolver::New(isolate->GetCurrentContext()) + .ToLocalChecked()) {} - context_.Reset(isolate, context); - resolver_.Reset(isolate, resolver); -} +Promise::Promise(v8::Isolate* isolate, v8::Local handle) + : isolate_(isolate), + context_(isolate, isolate->GetCurrentContext()), + resolver_(isolate, handle) {} Promise::~Promise() = default; +Promise::Promise(Promise&&) = default; +Promise& Promise::operator=(Promise&&) = default; + v8::Maybe Promise::RejectWithErrorMessage(const std::string& string) { v8::HandleScope handle_scope(isolate()); v8::MicrotasksScope script_scope(isolate(), @@ -42,16 +46,28 @@ v8::Local Promise::GetHandle() const { 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::New(isolate_, handle_)); +} + } // namespace util } // namespace atom namespace mate { -v8::Local mate::Converter::ToV8( +v8::Local mate::Converter::ToV8( v8::Isolate*, - atom::util::Promise* val) { - return val->GetHandle(); + const atom::util::Promise& val) { + return val.GetHandle(); } } // namespace mate diff --git a/atom/common/promise_util.h b/atom/common/promise_util.h index 3bdb71fb3f5f..5d57eae48ae4 100644 --- a/atom/common/promise_util.h +++ b/atom/common/promise_util.h @@ -16,16 +16,30 @@ namespace atom { namespace util { -class Promise : public base::RefCounted { +// 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: + // Create a new promise. explicit Promise(v8::Isolate* isolate); + // Wrap an existing v8 promise. + Promise(v8::Isolate* isolate, v8::Local handle); + + ~Promise(); + + // Support moving. + Promise(Promise&&); + Promise& operator=(Promise&&); + v8::Isolate* isolate() const { return isolate_; } v8::Local GetContext() { return v8::Local::New(isolate_, context_); } - virtual v8::Local GetHandle() const; + v8::Local GetHandle() const; v8::Maybe Resolve() { v8::HandleScope handle_scope(isolate()); @@ -87,22 +101,40 @@ class Promise : public base::RefCounted { v8::Maybe RejectWithErrorMessage(const std::string& error); - protected: - virtual ~Promise(); - friend class base::RefCounted; - v8::Isolate* isolate_; - v8::Global context_; - private: + friend class CopyablePromise; + v8::Local GetInner() const { return resolver_.Get(isolate()); } + v8::Isolate* isolate_; + v8::Global context_; v8::Global resolver_; 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::CopyablePersistent; + + v8::Isolate* isolate_; + CopyablePersistent handle_; +}; + } // namespace util } // namespace atom @@ -110,9 +142,9 @@ class Promise : public base::RefCounted { namespace mate { template <> -struct Converter { +struct Converter { static v8::Local ToV8(v8::Isolate* isolate, - atom::util::Promise* val); + const atom::util::Promise& val); // TODO(MarshallOfSound): Implement FromV8 to allow promise chaining // in native land // static bool FromV8(v8::Isolate* isolate, diff --git a/native_mate/native_mate/arguments.h b/native_mate/native_mate/arguments.h index 9198f289d6e1..99a7ef10f4d6 100644 --- a/native_mate/native_mate/arguments.h +++ b/native_mate/native_mate/arguments.h @@ -75,7 +75,7 @@ class Arguments { } template - void Return(T val) { + void Return(const T& val) { info_->GetReturnValue().Set(ConvertToV8(isolate_, val)); }