ScopeLogger();
CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+ // Prevent to call finished, cancelled or failed function more than once
+ if (DOWNLOAD_STATE_COMPLETED == downCbPtr->state ||
+ DOWNLOAD_STATE_CANCELED == downCbPtr->state ||
+ DOWNLOAD_STATE_FAILED == downCbPtr->state) {
+ LoggerD("Already finished job, not calling callback for %d state", downCbPtr->state);
+ return;
+ }
+
downCbPtr->state = state;
downCbPtr->downloadId = download_id;
out["fullPath"] = picojson::value(common::FilesystemProvider::Create().GetVirtualPath(fullPath));
Instance::PostMessage(downCbPtr->instance, picojson::value(out).serialize().c_str());
- downCbPtr->instance->download_callbacks.erase(callback_id);
- delete (downCbPtr);
-
+ // downCbPtr is freed in destructor, it prevent from crash if OnFinished state
+ // was called after OnCanceled or OnFailed
free(fullPath);
return FALSE;
out["callbackId"] = picojson::value(static_cast<double>(callback_id));
Instance::PostMessage(downCbPtr->instance, picojson::value(out).serialize().c_str());
- downCbPtr->instance->download_callbacks.erase(callback_id);
- delete (downCbPtr);
-
+ // downCbPtr is freed in destructor, it prevent from crash if OnFinished state
+ // was called after OnFinished or OnFailed
return FALSE;
}
out["callbackId"] = picojson::value(static_cast<double>(downCbPtr->callbackId));
Instance::PostMessage(downCbPtr->instance, picojson::value(out).serialize().c_str());
- downCbPtr->instance->download_callbacks.erase(callback_id);
- delete (downCbPtr);
-
+ // downCbPtr is freed in destructor, it prevent from crash if OnFinished state
+ // was called after OnFinished or OnCanceled
return FALSE;
}