Index: src/engine/Updater.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/engine/Updater.cpp |
@@ -0,0 +1,168 @@ |
+#include <functional> |
+#include <memory> |
+#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()> ThreadCallbackType; |
+ typedef std::function<void(HWND)> DialogCallbackType; |
+ |
+ const int DOWNLOAD_FAILED = 101; |
+ |
+ 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 |
+ std::auto_ptr<DialogCallbackType> callback(reinterpret_cast<DialogCallbackType*>(lParam)); |
+ (*callback)(hWnd); |
+ return TRUE; |
+ } |
+ case WM_COMMAND: |
+ { |
+ if (wParam == IDCANCEL) |
+ { |
+ EndDialog(hWnd, wParam); |
+ return TRUE; |
+ } |
+ break; |
+ } |
+ } |
+ return FALSE; |
+ } |
+ |
+ DWORD RunThread(LPVOID param) |
+ { |
+ std::auto_ptr<ThreadCallbackType> callback(reinterpret_cast<ThreadCallbackType*>(param)); |
+ (*callback)(); |
+ return 0; |
+ } |
+} |
+ |
+Updater::Updater(AdblockPlus::JsEnginePtr jsEngine, const std::string& url) |
+ : jsEngine(jsEngine), url(url), tempFile(GetAppDataPath() + L"\\update.exe") |
Oleksandr
2013/06/07 08:37:44
What if we decide we'd like to go with an MSI inst
Wladimir Palant
2013/06/07 12:46:56
Given the limitations of a pure MSI solution - we
|
+{ |
+} |
+ |
+void Updater::Update() |
+{ |
+ Debug("Update available: " + url); |
+ |
+ if (DialogBox(NULL, MAKEINTRESOURCE(IDD_UPDATEDIALOG), GetDesktopWindow(), |
+ reinterpret_cast<DLGPROC>(&UpdateDlgProc)) == IDOK) |
+ { |
+ Debug("User accepted update"); |
+ |
+ DialogCallbackType* callback = new DialogCallbackType(std::bind(&Updater::StartDownload, |
+ this, std::placeholders::_1)); |
+ int result = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DOWNLOADDIALOG), GetDesktopWindow(), |
+ reinterpret_cast<DLGPROC>(&DownloadDlgProc), |
+ reinterpret_cast<LPARAM>(callback)); |
+ if (result == DOWNLOAD_FAILED) |
+ { |
+ // 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)) |
Oleksandr
2013/06/07 08:37:44
Again, what if we download an msi? Then we'll need
|
+ { |
+ // 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; |
+ ThreadCallbackType* callback = new ThreadCallbackType(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, DOWNLOAD_FAILED); |
+ 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, DOWNLOAD_FAILED); |
+ return; |
+ } |
+ |
+ EndDialog(dialog, IDOK); |
+} |