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
|
+} |