123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- // Copyright (c) 2013 GitHub, Inc.
- // Use of this source code is governed by the MIT license that can be
- // found in the LICENSE file.
- #include "shell/browser/auto_updater.h"
- #include <string>
- #import <ReactiveCocoa/NSObject+RACPropertySubscribing.h>
- #import <ReactiveCocoa/RACCommand.h>
- #import <ReactiveCocoa/RACSignal.h>
- #import <Squirrel/Squirrel.h>
- #include "base/bind.h"
- #include "base/strings/sys_string_conversions.h"
- #include "base/time/time.h"
- #include "gin/arguments.h"
- #include "shell/browser/browser.h"
- #include "shell/common/gin_converters/value_converter_gin_adapter.h"
- #include "shell/common/gin_helper/dictionary.h"
- #include "shell/common/gin_helper/error_thrower.h"
- namespace auto_updater {
- namespace {
- // The gloal SQRLUpdater object.
- SQRLUpdater* g_updater = nil;
- } // namespace
- namespace {
- bool g_update_available = false;
- std::string update_url_ = ""; // NOLINT(runtime/string)
- } // namespace
- std::string AutoUpdater::GetFeedURL() {
- return update_url_;
- }
- // static
- void AutoUpdater::SetFeedURL(gin_helper::Arguments* args) {
- gin_helper::ErrorThrower thrower(args->isolate());
- gin_helper::Dictionary opts;
- std::string feed;
- HeaderMap requestHeaders;
- std::string serverType = "default";
- if (args->GetNext(&opts)) {
- if (!opts.Get("url", &feed)) {
- thrower.ThrowError(
- "Expected options object to contain a 'url' string property in "
- "setFeedUrl call");
- return;
- }
- opts.Get("headers", &requestHeaders);
- opts.Get("serverType", &serverType);
- if (serverType != "default" && serverType != "json") {
- thrower.ThrowError("Expected serverType to be 'default' or 'json'");
- return;
- }
- } else if (args->GetNext(&feed)) {
- args->GetNext(&requestHeaders);
- } else {
- thrower.ThrowError(
- "Expected an options object with a 'url' property to be provided");
- return;
- }
- Delegate* delegate = GetDelegate();
- if (!delegate)
- return;
- update_url_ = feed;
- NSURL* url = [NSURL URLWithString:base::SysUTF8ToNSString(feed)];
- NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:url];
- for (const auto& it : requestHeaders) {
- [urlRequest setValue:base::SysUTF8ToNSString(it.second)
- forHTTPHeaderField:base::SysUTF8ToNSString(it.first)];
- }
- if (g_updater)
- [g_updater release];
- // Initialize the SQRLUpdater.
- @try {
- if (serverType == "json") {
- NSString* nsAppVersion =
- base::SysUTF8ToNSString(electron::Browser::Get()->GetVersion());
- g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest
- forVersion:nsAppVersion];
- } else {
- // default
- g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest];
- }
- } @catch (NSException* error) {
- delegate->OnError(base::SysNSStringToUTF8(error.reason));
- return;
- }
- [[g_updater rac_valuesForKeyPath:@"state" observer:g_updater]
- subscribeNext:^(NSNumber* stateNumber) {
- int state = [stateNumber integerValue];
- // Dispatching the event on main thread.
- dispatch_async(dispatch_get_main_queue(), ^{
- if (state == SQRLUpdaterStateCheckingForUpdate)
- delegate->OnCheckingForUpdate();
- else if (state == SQRLUpdaterStateDownloadingUpdate)
- delegate->OnUpdateAvailable();
- });
- }];
- }
- // static
- void AutoUpdater::CheckForUpdates() {
- Delegate* delegate = GetDelegate();
- if (!delegate)
- return;
- [[[[g_updater.checkForUpdatesCommand execute:nil]
- // Send a `nil` after everything...
- concat:[RACSignal return:nil]]
- // But only take the first value. If an update is sent, we'll get that.
- // Otherwise, we'll get our inserted `nil` value.
- take:1]
- subscribeNext:^(SQRLDownloadedUpdate* downloadedUpdate) {
- if (downloadedUpdate) {
- g_update_available = true;
- SQRLUpdate* update = downloadedUpdate.update;
- // There is a new update that has been downloaded.
- delegate->OnUpdateDownloaded(
- base::SysNSStringToUTF8(update.releaseNotes),
- base::SysNSStringToUTF8(update.releaseName),
- base::Time::FromDoubleT(update.releaseDate.timeIntervalSince1970),
- base::SysNSStringToUTF8(update.updateURL.absoluteString));
- } else {
- g_update_available = false;
- // When the completed event is sent with no update, then we know there
- // is no update available.
- delegate->OnUpdateNotAvailable();
- }
- }
- error:^(NSError* error) {
- NSMutableString* failureString =
- [NSMutableString stringWithString:error.localizedDescription];
- if (error.localizedFailureReason) {
- [failureString appendString:@": "];
- [failureString appendString:error.localizedFailureReason];
- }
- if (error.localizedRecoverySuggestion) {
- if (![failureString hasSuffix:@"."])
- [failureString appendString:@"."];
- [failureString appendString:@" "];
- [failureString appendString:error.localizedRecoverySuggestion];
- }
- delegate->OnError(base::SysNSStringToUTF8(failureString), error.code,
- base::SysNSStringToUTF8(error.domain));
- }];
- }
- void AutoUpdater::QuitAndInstall() {
- Delegate* delegate = AutoUpdater::GetDelegate();
- if (g_update_available) {
- [[g_updater relaunchToInstallUpdate] subscribeError:^(NSError* error) {
- if (delegate)
- delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription),
- error.code, base::SysNSStringToUTF8(error.domain));
- }];
- } else {
- if (delegate)
- delegate->OnError("No update available, can't quit and install");
- }
- }
- } // namespace auto_updater
|