Pass error as ErrorPtr into ErrorCallback

Usually ErrorCallback is the final destination for error.

Change-Id: I86298347a0db4cf82689cc47d5cd36705b54ce81
Reviewed-on: https://weave-review.googlesource.com/1301
Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/libweave/examples/ubuntu/curl_http_client.cc b/libweave/examples/ubuntu/curl_http_client.cc
index f8172bc..c058a9b 100644
--- a/libweave/examples/ubuntu/curl_http_client.cc
+++ b/libweave/examples/ubuntu/curl_http_client.cc
@@ -38,7 +38,7 @@
 void CurlHttpClient::PostError(const ErrorCallback& error_callback,
                                ErrorPtr error) {
   task_runner_->PostDelayedTask(
-      FROM_HERE, base::Bind(error_callback, base::Owned(error.release())), {});
+      FROM_HERE, base::Bind(error_callback, base::Passed(&error)), {});
 }
 
 void CurlHttpClient::SendRequest(Method method,
diff --git a/libweave/examples/ubuntu/event_http_client.cc b/libweave/examples/ubuntu/event_http_client.cc
index b24c075..8341a07 100644
--- a/libweave/examples/ubuntu/event_http_client.cc
+++ b/libweave/examples/ubuntu/event_http_client.cc
@@ -74,7 +74,8 @@
                        "request failed: %s",
                        evutil_socket_error_to_string(err));
     state->task_runner_->PostDelayedTask(
-        FROM_HERE, base::Bind(state->error_callback_, error.get()), {});
+        FROM_HERE, base::Bind(state->error_callback_, base::Passed(&error)),
+        {});
     return;
   }
   std::unique_ptr<EventHttpResponse> response{new EventHttpResponse()};
@@ -148,8 +149,8 @@
   Error::AddToPrintf(&error, FROM_HERE, "http_client", "request_failed",
                      "request failed: %s %s", EnumToString(method).c_str(),
                      url.c_str());
-  task_runner_->PostDelayedTask(FROM_HERE,
-                                base::Bind(error_callback, error.get()), {});
+  task_runner_->PostDelayedTask(
+      FROM_HERE, base::Bind(error_callback, base::Passed(&error)), {});
 }
 
 }  // namespace examples
diff --git a/libweave/examples/ubuntu/main.cc b/libweave/examples/ubuntu/main.cc
index 0891e01..e762791 100644
--- a/libweave/examples/ubuntu/main.cc
+++ b/libweave/examples/ubuntu/main.cc
@@ -225,7 +225,7 @@
   LOG(INFO) << "Device registered: " << device->GetSettings().cloud_id;
 }
 
-void RegisterDeviceError(const weave::Error* error) {
+void RegisterDeviceError(weave::ErrorPtr error) {
   LOG(ERROR) << "Fail to register device: " << error->GetMessage();
 }
 
diff --git a/libweave/examples/ubuntu/netlink_network.cc b/libweave/examples/ubuntu/netlink_network.cc
index d121fca..24d0996 100644
--- a/libweave/examples/ubuntu/netlink_network.cc
+++ b/libweave/examples/ubuntu/netlink_network.cc
@@ -106,8 +106,8 @@
     ErrorPtr error;
     Error::AddTo(&error, FROM_HERE, "tls", "tls_init_failed",
                  "Failed to initialize TLS stream.");
-    task_runner_->PostDelayedTask(FROM_HERE,
-                                  base::Bind(error_callback, error.get()), {});
+    task_runner_->PostDelayedTask(
+        FROM_HERE, base::Bind(error_callback, base::Passed(&error)), {});
   }
 }
 
diff --git a/libweave/examples/ubuntu/network_manager.cc b/libweave/examples/ubuntu/network_manager.cc
index 6d92949..ff54f0b 100644
--- a/libweave/examples/ubuntu/network_manager.cc
+++ b/libweave/examples/ubuntu/network_manager.cc
@@ -57,13 +57,12 @@
   callbacks_.push_back(callback);
 }
 
-void NetworkImpl::TryToConnect(
-    const std::string& ssid,
-    const std::string& passphrase,
-    int pid,
-    base::Time until,
-    const SuccessCallback& success_callback,
-    const ErrorCallback& error_callback) {
+void NetworkImpl::TryToConnect(const std::string& ssid,
+                               const std::string& passphrase,
+                               int pid,
+                               base::Time until,
+                               const SuccessCallback& success_callback,
+                               const ErrorCallback& error_callback) {
   if (pid) {
     int status = 0;
     if (pid == waitpid(pid, &status, WNOWAIT)) {
@@ -95,8 +94,7 @@
     Error::AddTo(&error, FROM_HERE, "wifi", "timeout",
                  "Timeout connecting to WiFI network.");
     task_runner_->PostDelayedTask(
-        FROM_HERE, base::Bind(error_callback, base::Owned(error.release())),
-        {});
+        FROM_HERE, base::Bind(error_callback, base::Passed(&error)), {});
     return;
   }
 
@@ -117,8 +115,7 @@
     ErrorPtr error;
     Error::AddTo(&error, FROM_HERE, "wifi", "busy", "Running Access Point.");
     task_runner_->PostDelayedTask(
-        FROM_HERE, base::Bind(error_callback, base::Owned(error.release())),
-        {});
+        FROM_HERE, base::Bind(error_callback, base::Passed(&error)), {});
     return;
   }
 
@@ -218,6 +215,8 @@
     ErrorPtr error;
     Error::AddTo(&error, FROM_HERE, "tls", "tls_init_failed",
                  "Failed to initialize TLS stream.");
+    task_runner_->PostDelayedTask(
+        FROM_HERE, base::Bind(error_callback, base::Passed(&error)), {});
   }
 }
 
diff --git a/libweave/examples/ubuntu/ssl_stream.cc b/libweave/examples/ubuntu/ssl_stream.cc
index 58626cc..e146d58 100644
--- a/libweave/examples/ubuntu/ssl_stream.cc
+++ b/libweave/examples/ubuntu/ssl_stream.cc
@@ -51,9 +51,8 @@
                "SSL error");
   task_runner_->PostDelayedTask(
       FROM_HERE,
-      base::Bind(
-          &SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(),
-          base::Bind(error_callback, base::Owned(weave_error.release()))),
+      base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(),
+                 base::Bind(error_callback, base::Passed(&weave_error))),
       {});
   return;
 }
@@ -100,9 +99,8 @@
                "SSL error");
   task_runner_->PostDelayedTask(
       FROM_HERE,
-      base::Bind(
-          &SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(),
-          base::Bind(error_callback, base::Owned(weave_error.release()))),
+      base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(),
+                 base::Bind(error_callback, base::Passed(&weave_error))),
       {});
   return;
 }
diff --git a/libweave/include/weave/error.h b/libweave/include/weave/error.h
index 67f923f..83b33b4 100644
--- a/libweave/include/weave/error.h
+++ b/libweave/include/weave/error.h
@@ -127,7 +127,7 @@
 };
 
 using SuccessCallback = base::Closure;
-using ErrorCallback = base::Callback<void(const Error* error)>;
+using ErrorCallback = base::Callback<void(ErrorPtr error)>;
 
 }  // namespace weave
 
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc
index 09c7014..6481481 100644
--- a/libweave/src/device_registration_info.cc
+++ b/libweave/src/device_registration_info.cc
@@ -98,9 +98,9 @@
   return AppendQueryParams(result, params);
 }
 
-void IgnoreCloudError(const Error*) {}
+void IgnoreCloudError(ErrorPtr) {}
 
-void IgnoreCloudErrorWithCallback(const base::Closure& cb, const Error*) {
+void IgnoreCloudErrorWithCallback(const base::Closure& cb, ErrorPtr) {
   cb.Run();
 }
 
@@ -134,11 +134,11 @@
       success_callback.Run(response);
     };
     auto on_error = [](int debug_id, const ErrorCallback& error_callback,
-                       const Error* error) {
+                       ErrorPtr error) {
       VLOG(1) << "Request failed, id=" << debug_id
               << ", reason: " << error->GetCode()
               << ", message: " << error->GetMessage();
-      error_callback.Run(error);
+      error_callback.Run(std::move(error));
     };
     transport_->SendRequest(method_, url_, GetFullHeaders(), data_,
                             base::Bind(on_success, debug_id, success_callback),
@@ -357,7 +357,7 @@
 
   ErrorPtr error;
   if (!VerifyRegistrationCredentials(&error)) {
-    error_callback.Run(error.get());
+    error_callback.Run(std::move(error));
     return;
   }
 
@@ -405,10 +405,8 @@
   oauth2_backoff_entry_->InformOfRequest(true);
   ErrorPtr error;
   auto json = ParseOAuthResponse(response, &error);
-  if (!json) {
-    error_callback->Run(error.get());
-    return;
-  }
+  if (!json)
+    return error_callback->Run(std::move(error));
 
   int expires_in = 0;
   if (!json->GetString("access_token", &access_token_) ||
@@ -417,8 +415,7 @@
     LOG(ERROR) << "Access token unavailable.";
     Error::AddTo(&error, FROM_HERE, kErrorDomainOAuth2,
                  "unexpected_server_response", "Access token unavailable");
-    error_callback->Run(error.get());
-    return;
+    return error_callback->Run(std::move(error));
   }
   access_token_expiration_ =
       base::Time::Now() + base::TimeDelta::FromSeconds(expires_in);
@@ -437,7 +434,7 @@
 void DeviceRegistrationInfo::OnRefreshAccessTokenError(
     const std::shared_ptr<base::Closure>& success_callback,
     const std::shared_ptr<ErrorCallback>& error_callback,
-    const Error* error) {
+    ErrorPtr error) {
   VLOG(1) << "Refresh access token failed";
   oauth2_backoff_entry_->InformOfRequest(false);
   RefreshAccessToken(*success_callback, *error_callback);
@@ -530,7 +527,7 @@
   ErrorPtr error;
   if (!VerifyRegistrationCredentials(&error)) {
     if (!error_callback.is_null())
-      error_callback.Run(error.get());
+      error_callback.Run(std::move(error));
     return;
   }
   DoCloudRequest(HttpClient::Method::kGet, GetDeviceURL(), nullptr,
@@ -546,11 +543,9 @@
 
 void DeviceRegistrationInfo::RegisterDeviceError(
     const std::shared_ptr<RegisterCallbacks>& callbacks,
-    const Error* error) {
-  ErrorPtr error_clone = error->Clone();
+    ErrorPtr error) {
   task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(callbacks->error_callback, base::Owned(error_clone.release())),
+      FROM_HERE, base::Bind(callbacks->error_callback, base::Passed(&error)),
       {});
 }
 
@@ -565,7 +560,7 @@
   std::unique_ptr<base::DictionaryValue> device_draft =
       BuildDeviceResource(&error);
   if (!device_draft)
-    return RegisterDeviceError(callbacks, error.get());
+    return RegisterDeviceError(callbacks, std::move(error));
 
   base::DictionaryValue req_json;
   req_json.SetString("id", ticket_id);
@@ -590,11 +585,11 @@
   ErrorPtr error;
   auto json_resp = ParseJsonResponse(response, &error);
   if (!json_resp)
-    return RegisterDeviceError(callbacks, error.get());
+    return RegisterDeviceError(callbacks, std::move(error));
 
   if (!IsSuccessful(response)) {
     ParseGCDError(json_resp.get(), &error);
-    return RegisterDeviceError(callbacks, error.get());
+    return RegisterDeviceError(callbacks, std::move(error));
   }
 
   std::string url =
@@ -613,10 +608,10 @@
   ErrorPtr error;
   auto json_resp = ParseJsonResponse(response, &error);
   if (!json_resp)
-    return RegisterDeviceError(callbacks, error.get());
+    return RegisterDeviceError(callbacks, std::move(error));
   if (!IsSuccessful(response)) {
     ParseGCDError(json_resp.get(), &error);
-    return RegisterDeviceError(callbacks, error.get());
+    return RegisterDeviceError(callbacks, std::move(error));
   }
 
   std::string auth_code;
@@ -629,7 +624,7 @@
       !device_draft_response->GetString("id", &cloud_id)) {
     Error::AddTo(&error, FROM_HERE, kErrorDomainGCD, "unexpected_response",
                  "Device account missing in response");
-    return RegisterDeviceError(callbacks, error.get());
+    return RegisterDeviceError(callbacks, std::move(error));
   }
 
   UpdateDeviceInfoTimestamp(*device_draft_response);
@@ -666,7 +661,7 @@
       access_token_.empty() || refresh_token.empty() || expires_in <= 0) {
     Error::AddTo(&error, FROM_HERE, kErrorDomainGCD, "unexpected_response",
                  "Device access_token missing in response");
-    return RegisterDeviceError(callbacks, error.get());
+    return RegisterDeviceError(callbacks, std::move(error));
   }
 
   access_token_expiration_ =
@@ -715,19 +710,17 @@
 
   ErrorPtr error;
   if (!VerifyRegistrationCredentials(&error)) {
-    data->error_callback.Run(error.get());
-    return;
+    return data->error_callback.Run(std::move(error));
   }
 
   if (cloud_backoff_entry_->ShouldRejectRequest()) {
     VLOG(1) << "Cloud request delayed for "
             << cloud_backoff_entry_->GetTimeUntilRelease()
             << " due to backoff policy";
-    task_runner_->PostDelayedTask(
+    return task_runner_->PostDelayedTask(
         FROM_HERE, base::Bind(&DeviceRegistrationInfo::SendCloudRequest,
                               AsWeakPtr(), data),
         cloud_backoff_entry_->GetTimeUntilRelease());
-    return;
   }
 
   RequestSender sender{data->method, data->url, http_client_};
@@ -765,9 +758,8 @@
   ErrorPtr error;
   auto json_resp = ParseJsonResponse(response, &error);
   if (!json_resp) {
-    data->error_callback.Run(error.get());
     cloud_backoff_entry_->InformOfRequest(true);
-    return;
+    return data->error_callback.Run(std::move(error));
   }
 
   if (!IsSuccessful(response)) {
@@ -775,12 +767,10 @@
     if (status_code == http::kForbidden &&
         error->HasError(kErrorDomainGCDServer, "rateLimitExceeded")) {
       // If we exceeded server quota, retry the request later.
-      RetryCloudRequest(data);
-      return;
+      return RetryCloudRequest(data);
     }
     cloud_backoff_entry_->InformOfRequest(true);
-    data->error_callback.Run(error.get());
-    return;
+    return data->error_callback.Run(std::move(error));
   }
 
   cloud_backoff_entry_->InformOfRequest(true);
@@ -790,7 +780,7 @@
 
 void DeviceRegistrationInfo::OnCloudRequestError(
     const std::shared_ptr<const CloudRequestData>& data,
-    const Error* error) {
+    ErrorPtr error) {
   RetryCloudRequest(data);
 }
 
@@ -809,12 +799,12 @@
 
 void DeviceRegistrationInfo::OnAccessTokenError(
     const std::shared_ptr<const CloudRequestData>& data,
-    const Error* error) {
-  CheckAccessTokenError(error);
-  data->error_callback.Run(error);
+    ErrorPtr error) {
+  CheckAccessTokenError(error->Clone());
+  data->error_callback.Run(std::move(error));
 }
 
-void DeviceRegistrationInfo::CheckAccessTokenError(const Error* error) {
+void DeviceRegistrationInfo::CheckAccessTokenError(ErrorPtr error) {
   if (error->HasError(kErrorDomainOAuth2, "invalid_grant"))
     MarkDeviceUnregistered();
 }
@@ -963,8 +953,7 @@
   std::unique_ptr<base::DictionaryValue> device_resource =
       BuildDeviceResource(&error);
   if (!device_resource) {
-    OnUpdateDeviceResourceError(error.get());
-    return;
+    return OnUpdateDeviceResourceError(std::move(error));
   }
 
   std::string url = GetDeviceURL(
@@ -1010,7 +999,7 @@
   StartQueuedUpdateDeviceResource();
 }
 
-void DeviceRegistrationInfo::OnUpdateDeviceResourceError(const Error* error) {
+void DeviceRegistrationInfo::OnUpdateDeviceResourceError(ErrorPtr error) {
   if (error->HasError(kErrorDomainGCDServer, "invalid_last_update_time_ms")) {
     // If the server rejected our previous request, retrieve the latest
     // timestamp from the server and retry.
@@ -1027,7 +1016,7 @@
   // over.
   auto callback_list = std::move(in_progress_resource_update_callbacks_);
   for (const auto& callback_pair : callback_list)
-    callback_pair.second.Run(error);
+    callback_pair.second.Run(error->Clone());
 
   StartQueuedUpdateDeviceResource();
 }
@@ -1045,9 +1034,9 @@
 }
 
 void DeviceRegistrationInfo::OnFetchCommandsError(const ErrorCallback& callback,
-                                                  const Error* error) {
+                                                  ErrorPtr error) {
   OnFetchCommandsReturned();
-  callback.Run(error);
+  callback.Run(std::move(error));
 }
 
 void DeviceRegistrationInfo::OnFetchCommandsReturned() {
@@ -1216,7 +1205,7 @@
   PublishStateUpdates();
 }
 
-void DeviceRegistrationInfo::OnPublishStateError(const Error* error) {
+void DeviceRegistrationInfo::OnPublishStateError(ErrorPtr error) {
   LOG(ERROR) << "Permanent failure while trying to update device state";
   device_state_update_pending_ = false;
 }
diff --git a/libweave/src/device_registration_info.h b/libweave/src/device_registration_info.h
index 1577cd4..a7f79b6 100644
--- a/libweave/src/device_registration_info.h
+++ b/libweave/src/device_registration_info.h
@@ -159,7 +159,7 @@
   void OnRefreshAccessTokenError(
       const std::shared_ptr<base::Closure>& success_callback,
       const std::shared_ptr<ErrorCallback>& error_callback,
-      const Error* error);
+      ErrorPtr error);
 
   // Parse the OAuth response, and sets registration status to
   // kInvalidCredentials if our registration is no longer valid.
@@ -195,20 +195,20 @@
       const std::shared_ptr<const CloudRequestData>& data,
       const provider::HttpClient::Response& response);
   void OnCloudRequestError(const std::shared_ptr<const CloudRequestData>& data,
-                           const Error* error);
+                           ErrorPtr error);
   void RetryCloudRequest(const std::shared_ptr<const CloudRequestData>& data);
   void OnAccessTokenRefreshed(
       const std::shared_ptr<const CloudRequestData>& data);
   void OnAccessTokenError(const std::shared_ptr<const CloudRequestData>& data,
-                          const Error* error);
-  void CheckAccessTokenError(const Error* error);
+                          ErrorPtr error);
+  void CheckAccessTokenError(ErrorPtr error);
 
   void UpdateDeviceResource(const base::Closure& on_success,
                             const ErrorCallback& on_failure);
   void StartQueuedUpdateDeviceResource();
   // Success/failure callbacks for UpdateDeviceResource().
   void OnUpdateDeviceResourceSuccess(const base::DictionaryValue& device_info);
-  void OnUpdateDeviceResourceError(const Error* error);
+  void OnUpdateDeviceResourceError(ErrorPtr error);
 
   // Callback from GetDeviceInfo() to retrieve the device resource timestamp
   // and retry UpdateDeviceResource() call.
@@ -227,7 +227,7 @@
   void OnFetchCommandsSuccess(
       const base::Callback<void(const base::ListValue&)>& callback,
       const base::DictionaryValue& json);
-  void OnFetchCommandsError(const ErrorCallback& callback, const Error* error);
+  void OnFetchCommandsError(const ErrorCallback& callback, ErrorPtr error);
   // Called when FetchCommands completes (with either success or error).
   // This method reschedules any pending/queued fetch requests.
   void OnFetchCommandsReturned();
@@ -247,7 +247,7 @@
   void PublishStateUpdates();
   void OnPublishStateSuccess(StateChangeQueueInterface::UpdateID update_id,
                              const base::DictionaryValue& reply);
-  void OnPublishStateError(const Error* error);
+  void OnPublishStateError(ErrorPtr error);
 
   // If unrecoverable error occurred (e.g. error parsing command instance),
   // notify the server that the command is aborted by the device.
@@ -277,7 +277,7 @@
 
   struct RegisterCallbacks;
   void RegisterDeviceError(const std::shared_ptr<RegisterCallbacks>& callbacks,
-                           const Error* error);
+                           ErrorPtr error);
   void RegisterDeviceOnTicketSent(
       const std::string& ticket_id,
       const std::shared_ptr<RegisterCallbacks>& callbacks,
diff --git a/libweave/src/device_registration_info_unittest.cc b/libweave/src/device_registration_info_unittest.cc
index 49c4ccb..6d00a51 100644
--- a/libweave/src/device_registration_info_unittest.cc
+++ b/libweave/src/device_registration_info_unittest.cc
@@ -172,9 +172,9 @@
   bool RefreshAccessToken(ErrorPtr* error) const {
     bool succeeded = false;
     auto on_success = [&succeeded]() { succeeded = true; };
-    auto on_failure = [&error](const Error* in_error) {
+    auto on_failure = [&error](ErrorPtr in_error) {
       if (error)
-        *error = in_error->Clone();
+        *error = std::move(in_error);
     };
     dev_reg_->RefreshAccessToken(base::Bind(on_success),
                                  base::Bind(on_failure));
@@ -342,9 +342,7 @@
     EXPECT_EQ(test_data::kDeviceId, id);
     succeeded = true;
   };
-  auto on_failure = [](const Error* error) {
-    FAIL() << "Should not be called";
-  };
+  auto on_failure = [](ErrorPtr error) { FAIL() << "Should not be called"; };
   dev_reg_->GetDeviceInfo(base::Bind(on_success), base::Bind(on_failure));
   EXPECT_TRUE(succeeded);
 }
@@ -514,7 +512,7 @@
         EXPECT_EQ(test_data::kRobotAccountEmail,
                   dev_reg_->GetSettings().robot_account);
       }),
-      base::Bind([](const Error* error) { ADD_FAILURE(); }));
+      base::Bind([](ErrorPtr error) { ADD_FAILURE(); }));
   task_runner_.Run();
   EXPECT_TRUE(done);
 }
diff --git a/libweave/src/notification/xmpp_channel.cc b/libweave/src/notification/xmpp_channel.cc
index fae2022..0d22286 100644
--- a/libweave/src/notification/xmpp_channel.cc
+++ b/libweave/src/notification/xmpp_channel.cc
@@ -302,7 +302,7 @@
   ScheduleRegularPing();
 }
 
-void XmppChannel::OnSslError(const Error* error) {
+void XmppChannel::OnSslError(ErrorPtr error) {
   LOG(ERROR) << "TLS handshake failed. Restarting XMPP connection";
   backoff_entry_.InformOfRequest(false);
 
@@ -352,12 +352,12 @@
       base::Bind(&XmppChannel::OnReadError, task_ptr_factory_.GetWeakPtr()));
 }
 
-void XmppChannel::OnReadError(const Error* error) {
+void XmppChannel::OnReadError(ErrorPtr error) {
   read_pending_ = false;
   Restart();
 }
 
-void XmppChannel::OnWriteError(const Error* error) {
+void XmppChannel::OnWriteError(ErrorPtr error) {
   write_pending_ = false;
   Restart();
 }
diff --git a/libweave/src/notification/xmpp_channel.h b/libweave/src/notification/xmpp_channel.h
index 27e1f1b..814b2a5 100644
--- a/libweave/src/notification/xmpp_channel.h
+++ b/libweave/src/notification/xmpp_channel.h
@@ -98,14 +98,14 @@
 
   void CreateSslSocket();
   void OnSslSocketReady(std::unique_ptr<Stream> stream);
-  void OnSslError(const Error* error);
+  void OnSslError(ErrorPtr error);
 
   void WaitForMessage();
 
   void OnMessageRead(size_t size);
   void OnMessageSent();
-  void OnReadError(const Error* error);
-  void OnWriteError(const Error* error);
+  void OnReadError(ErrorPtr error);
+  void OnWriteError(ErrorPtr error);
   void Restart();
   void CloseStream();
 
diff --git a/libweave/src/privet/cloud_delegate.cc b/libweave/src/privet/cloud_delegate.cc
index 83cb6fb..3df5b86 100644
--- a/libweave/src/privet/cloud_delegate.cc
+++ b/libweave/src/privet/cloud_delegate.cc
@@ -166,12 +166,12 @@
       Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
                          errors::kInvalidParams, "Invalid role: '%s'",
                          str_scope.c_str());
-      return error_callback.Run(error.get());
+      return error_callback.Run(std::move(error));
     }
 
     std::string id;
     if (!command_manager_->AddCommand(command, role, &id, &error))
-      return error_callback.Run(error.get());
+      return error_callback.Run(std::move(error));
 
     command_owners_[id] = user_info.user_id();
     success_callback.Run(*command_manager_->FindCommand(id)->ToJson());
@@ -185,7 +185,7 @@
     ErrorPtr error;
     auto command = GetCommandInternal(id, user_info, &error);
     if (!command)
-      return error_callback.Run(error.get());
+      return error_callback.Run(std::move(error));
     success_callback.Run(*command->ToJson());
   }
 
@@ -197,7 +197,7 @@
     ErrorPtr error;
     auto command = GetCommandInternal(id, user_info, &error);
     if (!command || !command->Cancel(&error))
-      return error_callback.Run(error.get());
+      return error_callback.Run(std::move(error));
     success_callback.Run(*command->ToJson());
   }
 
@@ -298,7 +298,7 @@
 
   void RegisterDeviceError(const std::string& ticket_id,
                            const base::Time& deadline,
-                           const Error* error) {
+                           ErrorPtr error) {
     // Registration failed. Retry with backoff.
     backoff_entry_.InformOfRequest(false);
     task_runner_->PostDelayedTask(
diff --git a/libweave/src/privet/privet_handler.cc b/libweave/src/privet/privet_handler.cc
index 297af73..702104d 100644
--- a/libweave/src/privet/privet_handler.cc
+++ b/libweave/src/privet/privet_handler.cc
@@ -203,7 +203,7 @@
 }
 
 void OnCommandRequestFailed(const PrivetHandler::RequestCallback& callback,
-                            const Error* error) {
+                            ErrorPtr error) {
   if (error->HasError("gcd", "unknown_command")) {
     ErrorPtr new_error = error->Clone();
     Error::AddTo(&new_error, FROM_HERE, errors::kDomain, errors::kNotFound,
diff --git a/libweave/src/privet/privet_handler_unittest.cc b/libweave/src/privet/privet_handler_unittest.cc
index 6829984..42dd956 100644
--- a/libweave/src/privet/privet_handler_unittest.cc
+++ b/libweave/src/privet/privet_handler_unittest.cc
@@ -24,6 +24,7 @@
 using testing::Invoke;
 using testing::Return;
 using testing::SetArgPointee;
+using testing::WithArgs;
 
 namespace weave {
 namespace privet {
@@ -669,7 +670,9 @@
   ErrorPtr error;
   Error::AddTo(&error, FROM_HERE, errors::kDomain, "notFound", "");
   EXPECT_CALL(cloud_, GetCommand(_, _, _, _))
-      .WillOnce(RunCallback<3>(error.get()));
+      .WillOnce(WithArgs<3>(Invoke([&error](const ErrorCallback& callback) {
+        callback.Run(std::move(error));
+      })));
 
   EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
                HandleRequest("/privet/v3/commands/status", "{'id': '15'}"));
@@ -688,7 +691,9 @@
   ErrorPtr error;
   Error::AddTo(&error, FROM_HERE, errors::kDomain, "notFound", "");
   EXPECT_CALL(cloud_, CancelCommand(_, _, _, _))
-      .WillOnce(RunCallback<3>(error.get()));
+      .WillOnce(WithArgs<3>(Invoke([&error](const ErrorCallback& callback) {
+        callback.Run(std::move(error));
+      })));
 
   EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
                HandleRequest("/privet/v3/commands/cancel", "{'id': '11'}"));
diff --git a/libweave/src/privet/wifi_bootstrap_manager.cc b/libweave/src/privet/wifi_bootstrap_manager.cc
index e67e016..b4b0153 100644
--- a/libweave/src/privet/wifi_bootstrap_manager.cc
+++ b/libweave/src/privet/wifi_bootstrap_manager.cc
@@ -106,11 +106,10 @@
                             tasks_weak_factory_.GetWeakPtr()));
 }
 
-void WifiBootstrapManager::OnConnectError(const Error* error) {
-  ErrorPtr new_error = error ? error->Clone() : nullptr;
-  Error::AddTo(&new_error, FROM_HERE, errors::kDomain, errors::kInvalidState,
+void WifiBootstrapManager::OnConnectError(ErrorPtr error) {
+  Error::AddTo(&error, FROM_HERE, errors::kDomain, errors::kInvalidState,
                "Failed to connect to provided network");
-  setup_state_ = SetupState{std::move(new_error)};
+  setup_state_ = SetupState{std::move(error)};
   StartBootstrapping();
 }
 
diff --git a/libweave/src/privet/wifi_bootstrap_manager.h b/libweave/src/privet/wifi_bootstrap_manager.h
index 6423b9d..390af31 100644
--- a/libweave/src/privet/wifi_bootstrap_manager.h
+++ b/libweave/src/privet/wifi_bootstrap_manager.h
@@ -88,7 +88,7 @@
   // were temporary.
   void OnBootstrapTimeout();
   void OnConnectSuccess(const std::string& ssid);
-  void OnConnectError(const Error* error);
+  void OnConnectError(ErrorPtr error);
   void OnConnectivityChange();
   void OnMonitorTimeout();
   void UpdateConnectionState();
diff --git a/libweave/src/streams_unittest.cc b/libweave/src/streams_unittest.cc
index 9b1f339..3cef6f0 100644
--- a/libweave/src/streams_unittest.cc
+++ b/libweave/src/streams_unittest.cc
@@ -27,7 +27,7 @@
     done = true;
     EXPECT_EQ(test_data, destination.GetData());
   });
-  auto on_error = base::Bind([](const Error* error) { ADD_FAILURE(); });
+  auto on_error = base::Bind([](ErrorPtr error) { ADD_FAILURE(); });
   StreamCopier copier{&source, &destination};
   copier.Copy(on_success, on_error);
 
diff --git a/libweave/src/weave_unittest.cc b/libweave/src/weave_unittest.cc
index 5e15212..8d87229 100644
--- a/libweave/src/weave_unittest.cc
+++ b/libweave/src/weave_unittest.cc
@@ -338,7 +338,7 @@
                       task_runner_.Break();
                       EXPECT_EQ("CLOUD_ID", device_->GetSettings().cloud_id);
                     }),
-                    base::Bind([](const Error* error) { ADD_FAILURE(); }));
+                    base::Bind([](ErrorPtr error) { ADD_FAILURE(); }));
   task_runner_.Run();
   EXPECT_TRUE(done);
 }