| Index: src/engine/Updater.cpp |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/src/engine/Updater.cpp |
| @@ -0,0 +1,155 @@ |
| +#include <functional> |
| +#include <sstream> |
| +#include <AdblockPlus/FileSystem.h> |
| +#include <AdblockPlus/WebRequest.h> |
| + |
| +#include "../shared/Utils.h" |
| +#include "Debug.h" |
| +#include "Resource.h" |
| +#include "Updater.h" |
| + |
| +namespace |
| +{ |
| + typedef std::function<void()> CallbackType; |
| + |
| + LRESULT CALLBACK UpdateDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
| + { |
| + switch (msg) |
| + { |
| + case WM_INITDIALOG: |
| + // TODO: Localize dialog strings |
| + return TRUE; |
| + case WM_COMMAND: |
| + if (wParam == IDOK || wParam == IDCANCEL) |
| + { |
| + EndDialog(hWnd, wParam); |
| + return TRUE; |
| + } |
| + break; |
| + } |
| + |
| + return FALSE; |
| + } |
| + |
| + LRESULT CALLBACK DownloadDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
| + { |
| + // TODO: Indicate progress |
| + |
| + switch (msg) |
| + { |
| + case WM_INITDIALOG: |
| + // TODO: Localize dialog strings |
| + reinterpret_cast<Updater*>(lParam)->StartDownload(hWnd); |
| + return TRUE; |
| + case WM_COMMAND: |
| + if (wParam == IDCANCEL) |
| + { |
| + EndDialog(hWnd, wParam); |
| + return TRUE; |
| + } |
| + break; |
| + } |
| + return FALSE; |
| + } |
| + |
| + DWORD RunThread(LPVOID param) |
| + { |
| + CallbackType* callback = reinterpret_cast<CallbackType*>(param); |
|
Felix Dahlke
2013/06/06 17:44:00
I'd use an auto_ptr. What if there's an exception
|
| + (*callback)(); |
| + delete callback; |
| + return 0; |
| + } |
| +} |
| + |
| +Updater::Updater(AdblockPlus::JsEnginePtr jsEngine, const std::string& url) |
| + : jsEngine(jsEngine), url(url), tempFile(GetAppDataPath() + L"\\update.exe") |
| +{ |
| +} |
| + |
| +void Updater::StartUpdate() |
| +{ |
| + Debug("Update available: " + url); |
| + |
| + if (DialogBox(NULL, MAKEINTRESOURCE(IDD_UPDATEDIALOG), GetDesktopWindow(), |
| + reinterpret_cast<DLGPROC>(&UpdateDlgProc)) == IDOK) |
| + { |
| + Debug("User accepted update"); |
| + |
| + int result = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DOWNLOADDIALOG), GetDesktopWindow(), |
| + reinterpret_cast<DLGPROC>(&DownloadDlgProc), |
| + reinterpret_cast<LPARAM>(this)); |
| + if (result == -1) |
| + { |
| + // TODO: Localize |
| + MessageBoxW(NULL, L"Download failed", L"Downloading update", 0); |
| + } |
| + if (result != IDOK) |
| + return; |
| + |
| + PROCESS_INFORMATION pi; |
| + STARTUPINFO si; |
| + ::ZeroMemory(&si, sizeof(si)); |
| + si.cb = sizeof(si); |
| + si.wShowWindow = FALSE; |
| + |
| + if (!::CreateProcessW(tempFile.c_str(), NULL, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi)) |
| + { |
| + // TODO: Localize |
| + MessageBoxW(NULL, L"Failed to run updater", L"Downloading update", 0); |
| + DebugLastError("Creating updater process failed"); |
| + return; |
| + } |
| + ::CloseHandle(pi.hProcess); |
| + ::CloseHandle(pi.hThread); |
| + } |
| +} |
| + |
| +void Updater::StartDownload(HWND dialog) |
| +{ |
| + this->dialog = dialog; |
| + CallbackType* callback = new CallbackType(std::bind(&Updater::RunDownload, this)); |
| + ::CreateThread(NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(&RunThread), |
| + callback, 0, NULL); |
| +} |
| + |
| +void Updater::RunDownload() |
| +{ |
| + AdblockPlus::ServerResponse response = jsEngine->GetWebRequest()->GET(url, AdblockPlus::HeaderList()); |
| + if (response.status != AdblockPlus::WebRequest::NS_OK || |
| + response.responseStatus != 200) |
| + { |
| + std::stringstream ss; |
| + ss << "Update download failed (status: " << response.status << ", "; |
| + ss << "response: " << response.responseStatus << ")"; |
| + Debug(ss.str()); |
| + |
| + EndDialog(dialog, -1); |
|
Felix Dahlke
2013/06/06 17:44:00
How about using a constant for this result? downlo
|
| + return; |
| + } |
| + |
| + AdblockPlus::FileSystemPtr fileSystem = jsEngine->GetFileSystem(); |
| + std::string utfTempFile = ToUtf8String(tempFile); |
| + try |
| + { |
| + // Remove left-overs from previous update attempts |
| + fileSystem->Remove(utfTempFile); |
| + } |
| + catch (const std::exception&) |
| + { |
| + } |
| + |
| + try |
| + { |
| + std::tr1::shared_ptr<std::istream> fileData(new std::istringstream(response.responseText)); |
| + fileSystem->Write(utfTempFile, fileData); |
| + } |
| + catch (const std::exception& e) |
| + { |
| + DebugException(e); |
| + EndDialog(dialog, -1); |
| + return; |
| + } |
| + |
| + EndDialog(dialog, IDOK); |
| + return; |
|
Felix Dahlke
2013/06/06 17:44:00
Not really necessary
|
| +} |