VirtualBox

Changeset 94643 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Apr 20, 2022 9:08:37 AM (3 years ago)
Author:
vboxsync
Message:

Main/Update check: Big overhaul of the API and functionality.

  • Now uses VBOX_WITH_UPDATE_AGENT to entirely disable the feature (enabled by default).
  • Main: Uses new (more abstract) API as proposed in the latest UML docs.
  • Main: Added support for several events.
  • Main: Added support for update severities, order and dependencies (all optional).
  • Settings/XML: Now has own "Updates" branch to also cover other updatable components (later); not part of the system properties anymore.
  • Prepared for GuestAdditions and ExtPack updates.
  • FE/Qt: Adapted to new API.
  • FE/VBoxManage: Adapted to new API; uses more uniform (common) synopsis "modify" and "list" for modifying and listing (showing) update settings.
  • Docs: Fixed various typos, extended documentation.

Work in progress. bugref:7983

Location:
trunk/src/VBox/Main/src-server
Files:
3 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/HostImpl.cpp

    r94597 r94643  
    4545#include "LoggingNew.h"
    4646#include "Performance.h"
    47 #include "HostUpdateImpl.h"
     47#ifdef VBOX_WITH_UPDATE_AGENT
     48# include "UpdateAgentImpl.h"
     49#endif
    4850
    4951#include "MediumImpl.h"
     
    250252    bool                    fPersistentConfigUpToDate;
    251253
    252     /** The reference to the update check handler singleton. */
    253     const ComObjPtr<HostUpdate> pHostUpdate;
     254#ifdef VBOX_WITH_UPDATE_AGENT
     255    /** Reference to the host update agent. */
     256    const ComObjPtr<HostUpdateAgent> pUpdateHost;
     257#endif
    254258};
    255259
     
    308312    m->hostDnsMonitorProxy.init(m->pParent);
    309313
    310     hrc = unconst(m->pHostUpdate).createObject();
     314#ifdef VBOX_WITH_UPDATE_AGENT
     315    hrc = unconst(m->pUpdateHost).createObject();
    311316    if (SUCCEEDED(hrc))
    312         hrc = m->pHostUpdate->init(m->pParent);
     317        hrc = m->pUpdateHost->init(m->pParent);
    313318    AssertComRCReturn(hrc, hrc);
     319#endif
    314320
    315321#if defined(RT_OS_WINDOWS)
     
    502508    m->hostDnsMonitorProxy.uninit();
    503509
    504     if (m->pHostUpdate)
    505     {
    506         m->pHostUpdate->uninit();
    507         unconst(m->pHostUpdate).setNull();
    508     }
     510#ifdef VBOX_WITH_UPDATE_AGENT
     511    if (m->pUpdateHost)
     512    {
     513        m->pUpdateHost->uninit();
     514        unconst(m->pUpdateHost).setNull();
     515    }
     516#endif
    509517
    510518#ifdef VBOX_WITH_USB
     
    19922000}
    19932001
    1994 
    1995 HRESULT Host::getUpdate(ComPtr<IHostUpdate> &aUpdate)
    1996 {
    1997     HRESULT hrc = m->pHostUpdate.queryInterfaceTo(aUpdate.asOutParam());
     2002HRESULT Host::getUpdateHost(ComPtr<IUpdateAgent> &aUpdate)
     2003{
     2004#ifdef VBOX_WITH_UPDATE_AGENT
     2005    HRESULT hrc = m->pUpdateHost.queryInterfaceTo(aUpdate.asOutParam());
    19982006    return hrc;
    1999 }
    2000 
     2007#else
     2008    RT_NOREF(aUpdate);
     2009    ReturnComNotImplemented();
     2010#endif
     2011}
     2012
     2013HRESULT Host::getUpdateExtPack(ComPtr<IUpdateAgent> &aUpdate)
     2014{
     2015    RT_NOREF(aUpdate);
     2016    ReturnComNotImplemented();
     2017}
     2018
     2019HRESULT Host::getUpdateGuestAdditions(ComPtr<IUpdateAgent> &aUpdate)
     2020{
     2021    RT_NOREF(aUpdate);
     2022    ReturnComNotImplemented();
     2023}
    20012024
    20022025HRESULT  Host::getHostDrives(std::vector<ComPtr<IHostDrive> > &aHostDrives)
     
    20672090HRESULT Host::i_saveSettings(settings::Host &data)
    20682091{
    2069 #ifdef VBOX_WITH_USB
    20702092    AutoCaller autoCaller(this);
    20712093    if (FAILED(autoCaller.rc()))
     
    20742096    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    20752097
     2098    HRESULT rc;
     2099
     2100#ifdef VBOX_WITH_USB
    20762101    data.llUSBDeviceFilters.clear();
    20772102    data.llUSBDeviceSources.clear();
     
    20872112    }
    20882113
    2089     return m->pUSBProxyService->i_saveSettings(data.llUSBDeviceSources);
     2114    rc = m->pUSBProxyService->i_saveSettings(data.llUSBDeviceSources);
     2115    ComAssertComRCRet(rc, rc);
    20902116#else
    20912117    RT_NOREF(data);
     2118#endif /* VBOX_WITH_USB */
     2119
     2120#ifdef VBOX_WITH_UPDATE_AGENT
     2121    rc = m->pUpdateHost->i_saveSettings(data.updateHost);
     2122    ComAssertComRCRet(rc, rc);
     2123    /** @todo Add handling for ExtPack and Guest Additions updates here later. See @bugref{7983}. */
     2124#endif
     2125
    20922126    return S_OK;
    2093 #endif /* VBOX_WITH_USB */
    2094 
    20952127}
    20962128
  • trunk/src/VBox/Main/src-server/SystemPropertiesImpl.cpp

    r94578 r94643  
    117117    m->fExclusiveHwVirt = true;
    118118#endif
    119 
    120     m->fVBoxUpdateEnabled = true;
    121     m->uVBoxUpdateCount = 0;
    122     m->uVBoxUpdateFrequency = 1; // daily is the default
    123     m->uVBoxUpdateTarget = VBoxUpdateTarget_Stable;
    124119
    125120    HRESULT rc = S_OK;
     
    18291824}
    18301825
    1831 HRESULT SystemProperties::getSupportedVBoxUpdateTargetTypes(std::vector<VBoxUpdateTarget_T> &aSupportedVBoxUpdateTargetTypes)
    1832 {
    1833     static const VBoxUpdateTarget_T aVBoxUpdateTargetTypes[] =
    1834     {
    1835         VBoxUpdateTarget_Stable,
    1836         VBoxUpdateTarget_AllReleases,
    1837         VBoxUpdateTarget_WithBetas
    1838     };
    1839     aSupportedVBoxUpdateTargetTypes.assign(aVBoxUpdateTargetTypes,
    1840                                            aVBoxUpdateTargetTypes + RT_ELEMENTS(aVBoxUpdateTargetTypes));
    1841     return S_OK;
    1842 }
    1843 
    18441826
    18451827// public methods only for internal purposes
     
    18771859
    18781860    m->strLanguageId     = data.strLanguageId;
    1879 
    1880     m->fVBoxUpdateEnabled               = data.fVBoxUpdateEnabled;
    1881     m->uVBoxUpdateFrequency             = data.uVBoxUpdateFrequency;
    1882     m->strVBoxUpdateLastCheckDate       = data.strVBoxUpdateLastCheckDate;
    1883     m->uVBoxUpdateTarget                = data.uVBoxUpdateTarget;
    1884     m->uVBoxUpdateCount                 = data.uVBoxUpdateCount;
    18851861
    18861862    rc = i_setAutostartDatabasePath(data.strAutostartDatabasePath);
     
    22282204}
    22292205
    2230 HRESULT SystemProperties::i_setVBoxUpdateLastCheckDate(const com::Utf8Str &aVBoxUpdateLastCheckDate)
    2231 {
    2232     m->strVBoxUpdateLastCheckDate = aVBoxUpdateLastCheckDate;
    2233 
    2234     return S_OK;
    2235 }
    2236 
    2237 HRESULT SystemProperties::getVBoxUpdateEnabled(BOOL *aVBoxUpdateEnabled)
    2238 {
    2239     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2240 
    2241     *aVBoxUpdateEnabled = m->fVBoxUpdateEnabled;
    2242 
    2243     return S_OK;
    2244 }
    2245 
    2246 HRESULT SystemProperties::setVBoxUpdateEnabled(BOOL aVBoxUpdateEnabled)
    2247 {
    2248     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2249     m->fVBoxUpdateEnabled = !!aVBoxUpdateEnabled;
    2250     alock.release();
    2251 
    2252     // VirtualBox::i_saveSettings() needs vbox write lock
    2253     AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
    2254     HRESULT rc = mParent->i_saveSettings();
    2255 
    2256     return rc;
    2257 }
    2258 
    2259 HRESULT SystemProperties::getVBoxUpdateCount(ULONG *aVBoxUpdateCount)
    2260 {
    2261     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2262 
    2263     *aVBoxUpdateCount = m->uVBoxUpdateCount;
    2264 
    2265     return S_OK;
    2266 }
    2267 
    2268 HRESULT SystemProperties::setVBoxUpdateCount(ULONG aVBoxUpdateCount)
    2269 {
    2270     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2271     m->uVBoxUpdateCount = aVBoxUpdateCount;
    2272     alock.release();
    2273 
    2274     // VirtualBox::i_saveSettings() needs vbox write lock
    2275     AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
    2276     HRESULT rc = mParent->i_saveSettings();
    2277 
    2278     return rc;
    2279 }
    2280 
    22812206HRESULT SystemProperties::getLanguageId(com::Utf8Str &aLanguageId)
    22822207{
     
    23382263}
    23392264
    2340 HRESULT SystemProperties::getVBoxUpdateFrequency(ULONG *aVBoxUpdateFrequency)
    2341 {
    2342     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2343 
    2344     *aVBoxUpdateFrequency = m->uVBoxUpdateFrequency;
    2345 
    2346     return S_OK;
    2347 }
    2348 
    2349 HRESULT SystemProperties::setVBoxUpdateFrequency(ULONG aVBoxUpdateFrequency)
    2350 {
    2351     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2352     m->uVBoxUpdateFrequency = aVBoxUpdateFrequency;
    2353     alock.release();
    2354 
    2355     // VirtualBox::i_saveSettings() needs vbox write lock
    2356     AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
    2357     HRESULT rc = mParent->i_saveSettings();
    2358 
    2359     return rc;
    2360 }
    2361 
    2362 HRESULT SystemProperties::getVBoxUpdateTarget(VBoxUpdateTarget_T *aVBoxUpdateTarget)
    2363 {
    2364     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2365     VBoxUpdateTarget_T enmTarget = *aVBoxUpdateTarget = (VBoxUpdateTarget_T)m->uVBoxUpdateTarget;
    2366     AssertMsgReturn(enmTarget == VBoxUpdateTarget_Stable ||
    2367                     enmTarget == VBoxUpdateTarget_AllReleases ||
    2368                     enmTarget == VBoxUpdateTarget_WithBetas,
    2369                     ("enmTarget=%d\n", enmTarget), E_UNEXPECTED);
    2370     return S_OK;
    2371 }
    2372 
    2373 HRESULT SystemProperties::setVBoxUpdateTarget(VBoxUpdateTarget_T aVBoxUpdateTarget)
    2374 {
    2375     /* Validate input. */
    2376     switch (aVBoxUpdateTarget)
    2377     {
    2378         case VBoxUpdateTarget_Stable:
    2379         case VBoxUpdateTarget_AllReleases:
    2380         case VBoxUpdateTarget_WithBetas:
    2381             break;
    2382         default:
    2383             return setError(E_INVALIDARG, tr("Invalid Target value: %d"), (int)aVBoxUpdateTarget);
    2384     }
    2385 
    2386     /* Set and write out settings. */
    2387     {
    2388         AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2389         m->uVBoxUpdateTarget = aVBoxUpdateTarget;
    2390     }
    2391     AutoWriteLock alock(mParent COMMA_LOCKVAL_SRC_POS); /* required for saving. */
    2392     return mParent->i_saveSettings();
    2393 }
    2394 
    2395 HRESULT SystemProperties::getVBoxUpdateLastCheckDate(com::Utf8Str &aVBoxUpdateLastCheckDate)
    2396 {
    2397     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2398     aVBoxUpdateLastCheckDate = m->strVBoxUpdateLastCheckDate;
    2399     return S_OK;
    2400 }
    2401 
    2402 HRESULT SystemProperties::setVBoxUpdateLastCheckDate(const com::Utf8Str &aVBoxUpdateLastCheckDate)
    2403 {
    2404     /*
    2405      * Validate input.
    2406      */
    2407     Utf8Str const *pLastCheckDate = &aVBoxUpdateLastCheckDate;
    2408     RTTIMESPEC TimeSpec;
    2409 
    2410     if (pLastCheckDate->isEmpty() || !RTTimeSpecFromString(&TimeSpec, pLastCheckDate->c_str()))
    2411         return setErrorBoth(E_INVALIDARG, VERR_INVALID_PARAMETER,
    2412                             tr("Invalid LastCheckDate value: '%s'. "
    2413                                "Must be in ISO 8601 format (e.g. 2020-05-11T21:13:39.348416000Z)"), pLastCheckDate->c_str());
    2414 
    2415     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2416     HRESULT rc = i_setVBoxUpdateLastCheckDate(aVBoxUpdateLastCheckDate);
    2417     alock.release();
    2418     if (SUCCEEDED(rc))
    2419     {
    2420         // VirtualBox::i_saveSettings() needs vbox write lock
    2421         AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
    2422         rc = mParent->i_saveSettings();
    2423     }
    2424 
    2425     return rc;
    2426 }
  • trunk/src/VBox/Main/src-server/UpdateAgentImpl.cpp

    r94550 r94643  
    11/* $Id$ */
    22/** @file
    3  * IHostUpdate COM class implementations.
     3 * IUpdateAgent COM class implementations.
    44 */
    55
     
    1717
    1818
    19 #define LOG_GROUP LOG_GROUP_MAIN_HOSTUPDATE
     19#define LOG_GROUP LOG_GROUP_MAIN_UPDATEAGENT
    2020
    2121#include <iprt/cpp/utils.h>
     
    3636
    3737#include "HostImpl.h"
    38 #include "HostUpdateImpl.h"
     38#include "UpdateAgentImpl.h"
    3939#include "ProgressImpl.h"
    4040#include "AutoCaller.h"
     
    4848////////////////////////////////////////////////////////////////////////////////
    4949//
    50 // HostUpdate private data definition
     50// UpdateAgent private data definition
    5151//
    5252////////////////////////////////////////////////////////////////////////////////
    5353
    54 #ifdef VBOX_WITH_HOST_UPDATE_CHECK
    55 
    56 class HostUpdate::UpdateCheckTask : public ThreadTask
     54class UpdateAgentTask : public ThreadTask
    5755{
    5856public:
    59     UpdateCheckTask(UpdateCheckType_T aCheckType, HostUpdate *aThat, Progress *aProgress)
    60         : m_checkType(aCheckType)
    61         , m_pHostUpdate(aThat)
    62         , m_ptrProgress(aProgress)
    63     {
    64         m_strTaskName = "UpdateCheckTask";
    65     }
    66     ~UpdateCheckTask() { }
     57    UpdateAgentTask(UpdateAgent *aThat, Progress *aProgress)
     58        : m_pParent(aThat)
     59        , m_pProgress(aProgress)
     60    {
     61        m_strTaskName = "UpdateAgentTask";
     62    }
     63    virtual ~UpdateAgentTask(void) { }
    6764
    6865private:
    69     void handler();
    70 
    71     UpdateCheckType_T m_checkType;
    72     HostUpdate *m_pHostUpdate;
    73 
     66    void handler(void);
     67
     68    /** Weak pointer to parent (update agent). */
     69    UpdateAgent         *m_pParent;
    7470    /** Smart pointer to the progress object for this job. */
    75     ComObjPtr<Progress> m_ptrProgress;
    76 
    77     friend class HostUpdate;  // allow member functions access to private data
     71    ComObjPtr<Progress>  m_pProgress;
     72
     73    friend class UpdateAgent;  // allow member functions access to private data
    7874};
    7975
    80 void HostUpdate::UpdateCheckTask::handler()
    81 {
    82     HostUpdate *pHostUpdate = this->m_pHostUpdate;
    83 
    84     LogFlowFuncEnter();
    85     LogFlowFunc(("HostUpdate %p\n", pHostUpdate));
    86 
    87     HRESULT rc = pHostUpdate->i_updateCheckTask(this);
    88 
    89     LogFlowFunc(("rc=%Rhrc\n", rc)); NOREF(rc);
    90     LogFlowFuncLeave();
    91 }
    92 
    93 Utf8Str HostUpdate::i_platformInfo()
     76void UpdateAgentTask::handler(void)
     77{
     78    UpdateAgent *pUpdateAgent = this->m_pParent;
     79    AssertPtr(pUpdateAgent);
     80
     81    HRESULT rc = pUpdateAgent->i_updateTask(this);
     82
     83    if (!m_pProgress.isNull())
     84        m_pProgress->i_notifyComplete(rc);
     85
     86    LogFlowFunc(("rc=%Rhrc\n", rc)); RT_NOREF(rc);
     87}
     88
     89
     90/*********************************************************************************************************************************
     91*   Update agent base class implementation                                                                                       *
     92*********************************************************************************************************************************/
     93UpdateAgent::UpdateAgent()
     94    : m_VirtualBox(NULL)
     95    , m(new settings::UpdateAgent)
     96{
     97}
     98
     99UpdateAgent::~UpdateAgent()
     100{
     101    delete m;
     102}
     103
     104HRESULT UpdateAgent::FinalConstruct()
     105{
     106    return BaseFinalConstruct();
     107}
     108
     109void UpdateAgent::FinalRelease()
     110{
     111    uninit();
     112
     113    BaseFinalRelease();
     114}
     115
     116HRESULT UpdateAgent::init(VirtualBox *aVirtualBox)
     117{
     118    // Enclose the state transition NotReady->InInit->Ready.
     119    AutoInitSpan autoInitSpan(this);
     120    AssertReturn(autoInitSpan.isOk(), E_FAIL);
     121
     122    /* Weak reference to a VirtualBox object */
     123    unconst(m_VirtualBox) = aVirtualBox;
     124
     125    autoInitSpan.setSucceeded();
     126    return S_OK;
     127}
     128
     129void UpdateAgent::uninit()
     130{
     131    // Enclose the state transition Ready->InUninit->NotReady.
     132    AutoUninitSpan autoUninitSpan(this);
     133    if (autoUninitSpan.uninitDone())
     134        return;
     135}
     136
     137HRESULT UpdateAgent::download(ComPtr<IProgress> &aProgress)
     138{
     139    RT_NOREF(aProgress);
     140
     141    return VBOX_E_NOT_SUPPORTED;
     142}
     143
     144HRESULT UpdateAgent::install(ComPtr<IProgress> &aProgress)
     145{
     146    RT_NOREF(aProgress);
     147
     148    return VBOX_E_NOT_SUPPORTED;
     149}
     150
     151HRESULT UpdateAgent::rollback(void)
     152{
     153    return S_OK; /* No-op by default. */
     154}
     155
     156HRESULT UpdateAgent::getName(com::Utf8Str &aName)
     157{
     158    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     159
     160    aName = mData.m_strName;
     161
     162    return S_OK;
     163}
     164
     165HRESULT UpdateAgent::getOrder(ULONG *aOrder)
     166{
     167    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     168
     169    *aOrder = 0; /* 0 means no order / disabled. */
     170
     171    return S_OK;
     172}
     173
     174HRESULT UpdateAgent::getDependsOn(std::vector<com::Utf8Str> &aDeps)
     175{
     176    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     177
     178    aDeps.resize(0); /* No dependencies by default. */
     179
     180    return S_OK;
     181}
     182
     183HRESULT UpdateAgent::getVersion(com::Utf8Str &aVer)
     184{
     185    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     186
     187    aVer = mData.m_lastResult.strVer;
     188
     189    return S_OK;
     190}
     191
     192HRESULT UpdateAgent::getDownloadUrl(com::Utf8Str &aUrl)
     193{
     194    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     195
     196    aUrl = mData.m_lastResult.strDownloadUrl;
     197
     198    return S_OK;
     199}
     200
     201
     202HRESULT UpdateAgent::getWebUrl(com::Utf8Str &aUrl)
     203{
     204    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     205
     206    aUrl = mData.m_lastResult.strWebUrl;
     207
     208    return S_OK;
     209}
     210
     211HRESULT UpdateAgent::getReleaseNotes(com::Utf8Str &aRelNotes)
     212{
     213    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     214
     215    aRelNotes = mData.m_lastResult.strReleaseNotes;
     216
     217    return S_OK;
     218}
     219
     220HRESULT UpdateAgent::getEnabled(BOOL *aEnabled)
     221{
     222    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     223
     224    *aEnabled = m->fEnabled;
     225
     226    return S_OK;
     227}
     228
     229HRESULT UpdateAgent::setEnabled(const BOOL aEnabled)
     230{
     231    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     232
     233    m->fEnabled = aEnabled;
     234
     235    return S_OK;
     236}
     237
     238
     239HRESULT UpdateAgent::getHidden(BOOL *aHidden)
     240{
     241    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     242
     243    *aHidden = mData.m_fHidden;
     244
     245    return S_OK;
     246}
     247
     248HRESULT UpdateAgent::getState(UpdateState_T *aState)
     249{
     250    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     251
     252    *aState = mData.m_enmState;
     253
     254    return S_OK;
     255}
     256
     257HRESULT UpdateAgent::getCheckFrequency(ULONG *aFreqSeconds)
     258{
     259    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     260
     261    *aFreqSeconds = m->uCheckFreqSeconds;
     262
     263    return S_OK;
     264}
     265
     266HRESULT UpdateAgent::setCheckFrequency(ULONG aFreqSeconds)
     267{
     268    if (aFreqSeconds < RT_SEC_1DAY) /* Don't allow more frequent checks for now. */
     269        return setError(E_INVALIDARG, tr("Frequency too small; one day is the minimum"));
     270
     271    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     272
     273    m->uCheckFreqSeconds = aFreqSeconds;
     274
     275    return S_OK;
     276}
     277
     278HRESULT UpdateAgent::getChannel(UpdateChannel_T *aChannel)
     279{
     280    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     281
     282    *aChannel = m->enmChannel;
     283
     284    return S_OK;
     285}
     286
     287HRESULT UpdateAgent::setChannel(UpdateChannel_T aChannel)
     288{
     289    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     290
     291    m->enmChannel = aChannel;
     292
     293    return S_OK;
     294}
     295
     296HRESULT UpdateAgent::getCheckCount(ULONG *aCount)
     297{
     298    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     299
     300    *aCount = m->uCheckCount;
     301
     302    return S_OK;
     303}
     304
     305HRESULT UpdateAgent::getRepositoryURL(com::Utf8Str &aRepo)
     306{
     307    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     308
     309    aRepo = m->strRepoUrl;
     310
     311    return S_OK;
     312}
     313
     314HRESULT UpdateAgent::setRepositoryURL(const com::Utf8Str &aRepo)
     315{
     316    if (!aRepo.startsWith("https://", com::Utf8Str::CaseInsensitive))
     317        return setError(E_INVALIDARG, tr("Invalid URL scheme specified; only https:// is supported."));
     318
     319    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     320
     321    m->strRepoUrl = aRepo;
     322
     323    return S_OK;
     324}
     325
     326HRESULT UpdateAgent::getProxyMode(ProxyMode_T *aMode)
     327{
     328    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     329
     330    *aMode = m->enmProxyMode;
     331
     332    return S_OK;
     333}
     334
     335HRESULT UpdateAgent::setProxyMode(ProxyMode_T aMode)
     336{
     337    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     338
     339    m->enmProxyMode = aMode;
     340
     341    return S_OK;
     342}
     343
     344HRESULT UpdateAgent::getProxyURL(com::Utf8Str &aAddress)
     345{
     346    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     347
     348    aAddress = m->strProxyUrl;
     349
     350    return S_OK;
     351}
     352
     353HRESULT UpdateAgent::setProxyURL(const com::Utf8Str &aAddress)
     354{
     355    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     356
     357    m->strProxyUrl = aAddress;
     358
     359    return S_OK;
     360}
     361
     362HRESULT UpdateAgent::getLastCheckDate(com::Utf8Str &aDate)
     363{
     364    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     365
     366    aDate = m->strLastCheckDate;
     367
     368    return S_OK;
     369}
     370
     371/* static */
     372Utf8Str UpdateAgent::i_getPlatformInfo(void)
    94373{
    95374    /* Prepare platform report: */
     
    255534}
    256535
    257 HRESULT HostUpdate::i_checkForVBoxUpdate()
    258 {
    259     // Default to no update required
    260     m_updateNeeded = FALSE;
     536HRESULT UpdateAgent::i_loadSettings(const settings::UpdateAgent &data)
     537{
     538    AutoCaller autoCaller(this);
     539    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     540
     541    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     542
     543    m->fEnabled          = data.fEnabled;
     544    m->enmChannel        = data.enmChannel;
     545    m->uCheckFreqSeconds = data.uCheckFreqSeconds;
     546    m->strRepoUrl        = data.strRepoUrl;
     547    m->enmProxyMode      = data.enmProxyMode;
     548    m->strProxyUrl       = data.strProxyUrl;
     549    m->strLastCheckDate  = data.strLastCheckDate;
     550    m->uCheckCount       = data.uCheckCount;
     551
     552    return S_OK;
     553}
     554
     555HRESULT UpdateAgent::i_saveSettings(settings::UpdateAgent &data)
     556{
     557    AutoCaller autoCaller(this);
     558    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     559
     560    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     561
     562    data = *m;
     563
     564    return S_OK;
     565}
     566
     567HRESULT UpdateAgent::i_setCheckCount(ULONG aCount)
     568{
     569    AutoCaller autoCaller(this);
     570    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     571
     572    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     573
     574    m->uCheckCount = aCount;
     575
     576    return S_OK;
     577}
     578
     579HRESULT UpdateAgent::i_setLastCheckDate(const com::Utf8Str &aDate)
     580{
     581    AutoCaller autoCaller(this);
     582    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     583
     584    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     585
     586    m->strLastCheckDate = aDate;
     587
     588    return S_OK;
     589}
     590
     591#if 0
     592HRESULT UpdateAgent::getUpdateCheckNeeded(BOOL *aUpdateCheckNeeded)
     593{
     594    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     595
     596    HRESULT rc;
     597    ComPtr<ISystemProperties> pSystemProperties;
     598    rc = m_VirtualBox->COMGETTER(SystemProperties)(pSystemProperties.asOutParam());
     599    if (FAILED(rc))
     600        return rc;
     601
     602    /*
     603     * Is update checking enabled?
     604     */
     605    BOOL fVBoxUpdateEnabled;
     606    rc = pSystemProperties->COMGETTER(VBoxUpdateEnabled)(&fVBoxUpdateEnabled);
     607    if (FAILED(rc))
     608        return rc;
     609
     610    if (!fVBoxUpdateEnabled)
     611    {
     612        *aUpdateCheckNeeded = false;
     613        return S_OK;
     614    }
     615
     616    /*
     617     * When was the last update?
     618     */
     619    Bstr strVBoxUpdateLastCheckDate;
     620    rc = pSystemProperties->COMGETTER(VBoxUpdateLastCheckDate)(strVBoxUpdateLastCheckDate.asOutParam());
     621    if (FAILED(rc))
     622        return rc;
     623
     624    // No prior update check performed so do so now
     625    if (strVBoxUpdateLastCheckDate.isEmpty())
     626    {
     627        *aUpdateCheckNeeded = true;
     628        return S_OK;
     629    }
     630
     631    // convert stored timestamp to time spec
     632    RTTIMESPEC LastCheckTime;
     633    if (!RTTimeSpecFromString(&LastCheckTime, Utf8Str(strVBoxUpdateLastCheckDate).c_str()))
     634    {
     635        *aUpdateCheckNeeded = true;
     636        return S_OK;
     637    }
     638
     639    /*
     640     * Compare last update with how often we are supposed to check for updates.
     641     */
     642    ULONG uVBoxUpdateFrequency = 0;  // value in days
     643    rc = pSystemProperties->COMGETTER(VBoxUpdateFrequency)(&uVBoxUpdateFrequency);
     644    if (FAILED(rc))
     645        return rc;
     646
     647    if (!uVBoxUpdateFrequency)
     648    {
     649        /* Consider config (enable, 0 day interval) as checking once but never again.
     650           We've already check since we've got a date. */
     651        *aUpdateCheckNeeded = false;
     652        return S_OK;
     653    }
     654    uint64_t const cSecsInXDays = uVBoxUpdateFrequency * RT_SEC_1DAY_64;
     655
     656    RTTIMESPEC TimeDiff;
     657    RTTimeSpecSub(RTTimeNow(&TimeDiff), &LastCheckTime);
     658
     659    LogRelFunc(("Checking if seconds since last check (%lld) >= Number of seconds in %lu day%s (%lld)\n",
     660                RTTimeSpecGetSeconds(&TimeDiff), uVBoxUpdateFrequency, uVBoxUpdateFrequency > 1 ? "s" : "", cSecsInXDays));
     661
     662    if (RTTimeSpecGetSeconds(&TimeDiff) >= (int64_t)cSecsInXDays)
     663        *aUpdateCheckNeeded = true;
     664
     665    return S_OK;
     666}
     667#endif
     668
     669
     670/*********************************************************************************************************************************
     671*   Host update implementation                                                                                                   *
     672*********************************************************************************************************************************/
     673
     674HostUpdateAgent::HostUpdateAgent(void)
     675{
     676}
     677
     678HostUpdateAgent::~HostUpdateAgent(void)
     679{
     680}
     681
     682
     683HRESULT HostUpdateAgent::FinalConstruct(void)
     684{
     685    return BaseFinalConstruct();
     686}
     687
     688void HostUpdateAgent::FinalRelease(void)
     689{
     690    uninit();
     691
     692    BaseFinalRelease();
     693}
     694
     695HRESULT HostUpdateAgent::init(VirtualBox *aVirtualBox)
     696{
     697    // Enclose the state transition NotReady->InInit->Ready.
     698    AutoInitSpan autoInitSpan(this);
     699    AssertReturn(autoInitSpan.isOk(), E_FAIL);
     700
     701    /* Weak reference to a VirtualBox object */
     702    unconst(m_VirtualBox) = aVirtualBox;
     703
     704    /* Initialize the bare minimum to get things going.
     705     ** @todo Add more stuff later here. */
     706    mData.m_strName = "VirtualBox";
     707    mData.m_fHidden = false;
     708
     709    /* Set default repository. */
     710    m->strRepoUrl = "https://update.virtualbox.org";
     711
     712    autoInitSpan.setSucceeded();
     713    return S_OK;
     714}
     715
     716void HostUpdateAgent::uninit()
     717{
     718    // Enclose the state transition Ready->InUninit->NotReady.
     719    AutoUninitSpan autoUninitSpan(this);
     720    if (autoUninitSpan.uninitDone())
     721        return;
     722}
     723
     724HRESULT HostUpdateAgent::check(ComPtr<IProgress> &aProgress)
     725{
     726    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     727
     728    ComObjPtr<Progress> pProgress;
     729    HRESULT rc = pProgress.createObject();
     730    if (FAILED(rc))
     731        return rc;
     732
     733    rc = pProgress->init(m_VirtualBox,
     734                         static_cast<IUpdateAgent*>(this),
     735                         tr("Checking for update for %s ...", this->mData.m_strName.c_str()),
     736                         TRUE /* aCancelable */);
     737    if (FAILED(rc))
     738        return rc;
     739
     740    /* initialize the worker task */
     741    UpdateAgentTask *pTask = new UpdateAgentTask(this, pProgress);
     742    rc = pTask->createThread();
     743    pTask = NULL;
     744    if (FAILED(rc))
     745        return rc;
     746
     747    return pProgress.queryInterfaceTo(aProgress.asOutParam());
     748}
     749
     750
     751/*********************************************************************************************************************************
     752*   Host update internal functions                                                                                               *
     753*********************************************************************************************************************************/
     754
     755DECLCALLBACK(HRESULT) HostUpdateAgent::i_updateTask(UpdateAgentTask *pTask)
     756{
     757    RT_NOREF(pTask);
    261758
    262759    // Following the sequence of steps in UIUpdateStepVirtualBox::sltStartStep()
    263     // Build up our query URL starting with the URL basename
    264     Utf8Str strUrl("https://update.virtualbox.org/query.php/?");
     760    // Build up our query URL starting with the configured repository.
     761    Utf8Str strUrl;
     762    strUrl.appendPrintf("%s/query.php/?", m->strRepoUrl.c_str());
     763
     764    // Add platform ID.
    265765    Bstr platform;
    266     HRESULT rc = mVirtualBox->COMGETTER(PackageType)(platform.asOutParam());
     766    HRESULT rc = m_VirtualBox->COMGETTER(PackageType)(platform.asOutParam());
    267767    AssertComRCReturn(rc, rc);
    268768    strUrl.appendPrintf("platform=%ls", platform.raw()); // e.g. SOLARIS_64BITS_GENERIC
     
    270770    // Get the complete current version string for the query URL
    271771    Bstr versionNormalized;
    272     rc = mVirtualBox->COMGETTER(VersionNormalized)(versionNormalized.asOutParam());
     772    rc = m_VirtualBox->COMGETTER(VersionNormalized)(versionNormalized.asOutParam());
    273773    AssertComRCReturn(rc, rc);
    274774    strUrl.appendPrintf("&version=%ls", versionNormalized.raw()); // e.g. 6.1.1
    275     // strUrl.appendPrintf("&version=6.0.12"); // comment out previous line and uncomment this one for testing
     775#ifdef DEBUG // Comment out previous line and uncomment this one for testing.
     776//  strUrl.appendPrintf("&version=6.0.12");
     777#endif
    276778
    277779    ULONG revision = 0;
    278     rc = mVirtualBox->COMGETTER(Revision)(&revision);
     780    rc = m_VirtualBox->COMGETTER(Revision)(&revision);
    279781    AssertComRCReturn(rc, rc);
    280782    strUrl.appendPrintf("_%u", revision); // e.g. 135618
    281783
    282     // acquire the System Properties interface
    283     ComPtr<ISystemProperties> ptrSystemProperties;
    284     rc = mVirtualBox->COMGETTER(SystemProperties)(ptrSystemProperties.asOutParam());
    285     AssertComRCReturn(rc, rc);
    286 
    287     // Update the VBoxUpdate setting 'VBoxUpdateLastCheckDate'
     784    // Update the last update check timestamp.
    288785    RTTIME Time;
    289786    RTTIMESPEC TimeNow;
    290787    char szTimeStr[RTTIME_STR_LEN];
    291788    RTTimeToString(RTTimeExplode(&Time, RTTimeNow(&TimeNow)), szTimeStr, sizeof(szTimeStr));
    292     LogRelFunc(("VBox updating UpdateDate with TimeString = %s\n", szTimeStr));
    293     rc = ptrSystemProperties->COMSETTER(VBoxUpdateLastCheckDate)(Bstr(szTimeStr).raw());
    294     AssertComRCReturn(rc, rc);
    295 
    296     // Update the queryURL and the VBoxUpdate setting 'VBoxUpdateCount'
    297     ULONG cVBoxUpdateCount = 0;
    298     rc = ptrSystemProperties->COMGETTER(VBoxUpdateCount)(&cVBoxUpdateCount);
    299     AssertComRCReturn(rc, rc);
    300 
    301     cVBoxUpdateCount++;
    302 
    303     rc = ptrSystemProperties->COMSETTER(VBoxUpdateCount)(cVBoxUpdateCount);
    304     AssertComRCReturn(rc, rc);
    305     strUrl.appendPrintf("&count=%u", cVBoxUpdateCount);
    306 
    307     // Update the query URL and the VBoxUpdate settings (if necessary) with the 'Target' information.
    308     VBoxUpdateTarget_T enmTarget = VBoxUpdateTarget_Stable; // default branch is 'stable'
    309     rc = ptrSystemProperties->COMGETTER(VBoxUpdateTarget)(&enmTarget);
    310     AssertComRCReturn(rc, rc);
    311 
    312     switch (enmTarget)
    313     {
    314         case VBoxUpdateTarget_AllReleases:
     789    LogRel2(("Update agent (%s): Setting last update check timestamp to '%s'\n", mData.m_strName.c_str(), szTimeStr));
     790
     791    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     792
     793    m->strLastCheckDate = szTimeStr;
     794    m->uCheckCount++;
     795
     796    strUrl.appendPrintf("&count=%RU32", m->uCheckCount);
     797
     798    alock.release();
     799
     800    // Update the query URL (if necessary) with the 'channel' information.
     801    switch (m->enmChannel)
     802    {
     803        case UpdateChannel_All:
    315804            strUrl.appendPrintf("&branch=allrelease"); // query.php expects 'allrelease' and not 'allreleases'
    316805            break;
    317         case VBoxUpdateTarget_WithBetas:
     806        case UpdateChannel_WithBetas:
    318807            strUrl.appendPrintf("&branch=withbetas");
    319808            break;
    320         case VBoxUpdateTarget_Stable:
     809        /** @todo Handle UpdateChannel_WithTesting once implemented on the backend. */
     810        case UpdateChannel_Stable:
     811            RT_FALL_THROUGH();
    321812        default:
    322813            strUrl.appendPrintf("&branch=stable");
     
    324815    }
    325816
    326     rc = ptrSystemProperties->COMSETTER(VBoxUpdateTarget)(enmTarget);
    327     AssertComRCReturn(rc, rc);
    328 
    329     LogRelFunc(("VBox update URL = %s\n", strUrl.c_str()));
     817    LogRel2(("Update agent (%s): Using URL '%s'\n", mData.m_strName.c_str(), strUrl.c_str()));
    330818
    331819    /*
     
    333821     */
    334822    Bstr version;
    335     rc = mVirtualBox->COMGETTER(Version)(version.asOutParam()); // e.g. 6.1.0_RC1
     823    rc = m_VirtualBox->COMGETTER(Version)(version.asOutParam()); // e.g. 6.1.0_RC1
    336824    AssertComRCReturn(rc, rc);
    337825
    338     Utf8StrFmt const strUserAgent("VirtualBox %ls <%s>", version.raw(), HostUpdate::i_platformInfo().c_str());
    339     LogRelFunc(("userAgent = %s\n", strUserAgent.c_str()));
     826    Utf8StrFmt const strUserAgent("VirtualBox %ls <%s>", version.raw(), UpdateAgent::i_getPlatformInfo().c_str());
     827    LogRel2(("Update agent (%s): Using user agent '%s'\n",  mData.m_strName.c_str(), strUserAgent.c_str()));
    340828
    341829    /*
     
    349837        try
    350838        {
    351             rc = i_checkForVBoxUpdateInner(hHttp, strUrl, strUserAgent, ptrSystemProperties);
     839            rc = i_checkForUpdateInner(hHttp, strUrl, strUserAgent);
    352840        }
    353841        catch (...)
     
    359847    }
    360848    else
    361         rc = setErrorVrc(vrc, tr("%s: RTHttpCreate() failed: %Rrc"), __FUNCTION__, vrc);
    362     return S_OK;
    363 }
    364 
    365 HRESULT HostUpdate::i_checkForVBoxUpdateInner(RTHTTP hHttp, Utf8Str const &strUrl, Utf8Str const &strUserAgent,
    366                                               ComPtr<ISystemProperties> const &ptrSystemProperties)
    367 {
    368     /// @todo Are there any other headers needed to be added first via RTHttpSetHeaders()?
     849        rc = setErrorVrc(vrc, tr("Update agent (%s): RTHttpCreate() failed: %Rrc"), mData.m_strName.c_str(), vrc);
     850
     851    return rc;
     852}
     853
     854HRESULT HostUpdateAgent::i_checkForUpdateInner(RTHTTP hHttp, Utf8Str const &strUrl, Utf8Str const &strUserAgent)
     855{
     856    /** @todo Are there any other headers needed to be added first via RTHttpSetHeaders()? */
    369857    int vrc = RTHttpAddHeader(hHttp, "User-Agent", strUserAgent.c_str(), strUserAgent.length(), RTHTTPADDHDR_F_BACK);
    370858    if (RT_FAILURE(vrc))
    371         return setErrorVrc(vrc, tr("%s: RTHttpAddHeader() failed: %Rrc (on User-Agent)"), __FUNCTION__, vrc);
     859        return setErrorVrc(vrc, tr("Update agent (%s): RTHttpAddHeader() failed: %Rrc (on User-Agent)"),
     860                                   mData.m_strName.c_str(), vrc);
    372861
    373862    /*
    374863     * Configure proxying.
    375864     */
    376     ProxyMode_T enmProxyMode;
    377     HRESULT rc = ptrSystemProperties->COMGETTER(ProxyMode)(&enmProxyMode);
    378     if (FAILED(rc))
    379         return setError(rc, tr("%s: ISystemProperties::proxyMode() failed: %Rrc"), __FUNCTION__, rc);
    380 
    381     if (enmProxyMode == ProxyMode_Manual)
    382     {
    383         Bstr strProxyURL;
    384         rc = ptrSystemProperties->COMGETTER(ProxyURL)(strProxyURL.asOutParam());
    385         if (FAILED(rc))
    386             return setError(rc, tr("%s: ISystemProperties::proxyURL() failed: %Rrc"), __FUNCTION__, rc);
    387         vrc = RTHttpSetProxyByUrl(hHttp, Utf8Str(strProxyURL).c_str());
     865    if (m->enmProxyMode == ProxyMode_Manual)
     866    {
     867        vrc = RTHttpSetProxyByUrl(hHttp, m->strProxyUrl.c_str());
    388868        if (RT_FAILURE(vrc))
    389             return setErrorVrc(vrc, tr("%s: RTHttpSetProxyByUrl() failed: %Rrc"), __FUNCTION__, vrc);
    390     }
    391     else if (enmProxyMode == ProxyMode_System)
     869            return setErrorVrc(vrc, tr("Update agent (%s): RTHttpSetProxyByUrl() failed: %Rrc"), mData.m_strName.c_str(), vrc);
     870    }
     871    else if (m->enmProxyMode == ProxyMode_System)
    392872    {
    393873        vrc = RTHttpUseSystemProxySettings(hHttp);
    394874        if (RT_FAILURE(vrc))
    395             return setErrorVrc(vrc, tr("%s: RTHttpUseSystemProxySettings() failed: %Rrc"), __FUNCTION__, vrc);
     875            return setErrorVrc(vrc, tr("Update agent (%s): RTHttpUseSystemProxySettings() failed: %Rrc"),
     876                                       mData.m_strName.c_str(), vrc);
    396877    }
    397878    else
    398         Assert(enmProxyMode == ProxyMode_NoProxy);
     879        Assert(m->enmProxyMode == ProxyMode_NoProxy);
    399880
    400881    /*
     
    405886    vrc = RTHttpGetBinary(hHttp, strUrl.c_str(), &pvResponse, &cbResponse);
    406887    if (RT_FAILURE(vrc))
    407         return setErrorVrc(vrc, tr("%s: RTHttpGetBinary() failed: %Rrc"), __FUNCTION__, vrc);
     888        return setErrorVrc(vrc, tr("Update agent (%s): RTHttpGetBinary() failed: %Rrc"), mData.m_strName.c_str(), vrc);
    408889
    409890    /* Note! We can do nothing that might throw exceptions till we call RTHttpFreeResponse! */
     
    432913    size_t const cchWord1 = (size_t)(pchResponse - pchWord1);
    433914
     915    HRESULT rc;
     916
     917    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     918
    434919    /* Decode the two word: */
    435920    static char const s_szUpToDate[] = "UPTODATE";
     
    437922        && memcmp(pchWord0, s_szUpToDate, sizeof(s_szUpToDate) - 1) == 0)
    438923    {
    439         m_updateNeeded = FALSE;
     924        mData.m_enmState = UpdateState_NotAvailable;
    440925        rc = S_OK;
    441926    }
    442927    else
    443928    {
     929        mData.m_enmState = UpdateState_Error; /* Play safe by default. */
     930
    444931        vrc = RTStrValidateEncodingEx(pchWord0, cchWord0, 0 /*fFlags*/);
    445932        if (RT_SUCCESS(vrc))
     
    448935        {
    449936            /** @todo Any additional sanity checks we could perform here? */
    450             rc = m_updateVersion.assignEx(pchWord0, cchWord0);
     937            rc = mData.m_lastResult.strVer.assignEx(pchWord0, cchWord0);
    451938            if (SUCCEEDED(rc))
     939                rc = mData.m_lastResult.strDownloadUrl.assignEx(pchWord1, cchWord1);
     940
     941            if (RT_SUCCESS(vrc))
    452942            {
    453                 rc = m_updateURL.assignEx(pchWord1, cchWord1);
    454                 if (SUCCEEDED(rc))
    455                     m_updateNeeded = TRUE;
     943                /** @todo Implement this on the backend first.
     944                 *        We also could do some guessing based on the installed version vs. reported update version? */
     945                mData.m_lastResult.enmSeverity = UpdateSeverity_Invalid;
     946                mData.m_enmState               = UpdateState_Available;
    456947            }
    457             LogRelFunc(("HTTP server reply = %.*s %.*s\n", cchWord0, pchWord0, cchWord1, pchWord1));
     948
     949            LogRel(("Update agent (%s): HTTP server replied: %.*s %.*s\n",
     950                    mData.m_strName.c_str(), cchWord0, pchWord0, cchWord1, pchWord1));
    458951        }
    459952        else
    460             rc = setErrorVrc(vrc, tr("Invalid server response: %Rrc (%.*Rhxs -- %.*Rhxs)"),
    461                              vrc, cchWord0, pchWord0, cchWord1, pchWord1);
     953            rc = setErrorVrc(vrc, tr("Update agent (%s): Invalid server response: %Rrc (%.*Rhxs -- %.*Rhxs)"),
     954                             mData.m_strName.c_str(), vrc, cchWord0, pchWord0, cchWord1, pchWord1);
    462955    }
    463956
     
    467960}
    468961
    469 HRESULT HostUpdate::i_updateCheckTask(UpdateCheckTask *pTask)
    470 {
    471     LogFlowFuncEnter();
    472     AutoCaller autoCaller(this);
    473     HRESULT hrc = autoCaller.rc();
    474     if (SUCCEEDED(hrc))
    475     {
    476         try
    477         {
    478             switch (pTask->m_checkType)
    479             {
    480                 case UpdateCheckType_VirtualBox:
    481                     hrc = i_checkForVBoxUpdate();
    482                     break;
    483 # if 0
    484                 case UpdateCheckType_ExtensionPack:
    485                     hrc = i_checkForExtPackUpdate();
    486                     break;
    487 
    488                 case UpdateCheckType_GuestAdditions:
    489                     hrc = i_checkForGuestAdditionsUpdate();
    490                     break;
    491 # endif
    492                 default:
    493                     hrc = setError(E_FAIL, tr("Update check type %d is not implemented"), pTask->m_checkType);
    494                     break;
    495             }
    496         }
    497         catch (...)
    498         {
    499             AssertFailed();
    500             hrc = E_UNEXPECTED;
    501         }
    502     }
    503 
    504     if (!pTask->m_ptrProgress.isNull())
    505         pTask->m_ptrProgress->i_notifyComplete(hrc);
    506 
    507     LogFlowFunc(("rc=%Rhrc\n", hrc));
    508     LogFlowFuncLeave();
    509     return hrc;
    510 }
    511 
    512 #endif /* VBOX_WITH_HOST_UPDATE_CHECK */
    513 
    514 
    515 ////////////////////////////////////////////////////////////////////////////////
    516 //
    517 // HostUpdate constructor / destructor
    518 //
    519 // ////////////////////////////////////////////////////////////////////////////////
    520 HostUpdate::HostUpdate()
    521     : mVirtualBox(NULL)
    522 {
    523 }
    524 
    525 HostUpdate::~HostUpdate()
    526 {
    527 }
    528 
    529 
    530 HRESULT HostUpdate::FinalConstruct()
    531 {
    532     return BaseFinalConstruct();
    533 }
    534 
    535 void HostUpdate::FinalRelease()
    536 {
    537     uninit();
    538 
    539     BaseFinalRelease();
    540 }
    541 
    542 HRESULT HostUpdate::init(VirtualBox *aVirtualBox)
    543 {
    544     // Enclose the state transition NotReady->InInit->Ready.
    545     AutoInitSpan autoInitSpan(this);
    546     AssertReturn(autoInitSpan.isOk(), E_FAIL);
    547 
    548     /* Weak reference to a VirtualBox object */
    549     unconst(mVirtualBox) = aVirtualBox;
    550 
    551     autoInitSpan.setSucceeded();
    552     return S_OK;
    553 }
    554 
    555 void HostUpdate::uninit()
    556 {
    557     // Enclose the state transition Ready->InUninit->NotReady.
    558     AutoUninitSpan autoUninitSpan(this);
    559     if (autoUninitSpan.uninitDone())
    560         return;
    561 }
    562 
    563 HRESULT HostUpdate::updateCheck(UpdateCheckType_T aCheckType,
    564                                 ComPtr<IProgress> &aProgress)
    565 {
    566 #ifdef VBOX_WITH_HOST_UPDATE_CHECK
    567     /* Validate input */
    568     switch (aCheckType)
    569     {
    570         case UpdateCheckType_VirtualBox:
    571             break;
    572         case UpdateCheckType_ExtensionPack:
    573             return setError(E_NOTIMPL, tr("UpdateCheckType::ExtensionPack is not implemented"));
    574         case UpdateCheckType_GuestAdditions:
    575             return setError(E_NOTIMPL, tr("UpdateCheckType::GuestAdditions is not implemented"));
    576         default:
    577             return setError(E_INVALIDARG, tr("Invalid aCheckType value %d"), aCheckType);
    578     }
    579 
    580     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    581 
    582     // Check whether VirtualBox updates have been disabled before spawning the task thread.
    583     ComPtr<ISystemProperties> pSystemProperties;
    584     HRESULT rc = mVirtualBox->COMGETTER(SystemProperties)(pSystemProperties.asOutParam());
    585     AssertComRCReturn(rc, rc);
    586 
    587     BOOL fVBoxUpdateEnabled = true;
    588     rc = pSystemProperties->COMGETTER(VBoxUpdateEnabled)(&fVBoxUpdateEnabled);
    589     AssertComRCReturn(rc, rc);
    590 
    591     /** @todo r=bird: Not sure if this makes sense, it should at least have a
    592      * better status code and a proper error message.  Also, isn't this really
    593      * something the caller should check?  Presumably the caller already check
    594      * whther this was a good time to perform an update check (i.e. the configured
    595      * time has elapsed since last check) ...
    596      *
    597      * It would make sense to allow performing a one-off update check even if the
    598      * automatic update checking is disabled, wouldn't it? */
    599     if (!fVBoxUpdateEnabled)
    600         return E_NOTIMPL;
    601 
    602     ComObjPtr<Progress> pProgress;
    603     rc = pProgress.createObject();
    604     if (FAILED(rc))
    605         return rc;
    606 
    607     rc = pProgress->init(mVirtualBox,
    608                          static_cast<IHostUpdate*>(this),
    609                          tr("Checking for software update..."),
    610                          TRUE /* aCancelable */);
    611     if (FAILED(rc))
    612         return rc;
    613 
    614     /* initialize the worker task */
    615     UpdateCheckTask *pTask = new UpdateCheckTask(aCheckType, this, pProgress);
    616     rc = pTask->createThread();
    617     pTask = NULL;
    618     if (FAILED(rc))
    619         return rc;
    620 
    621     rc = pProgress.queryInterfaceTo(aProgress.asOutParam());
    622 
    623     return rc;
    624 #else  /* !VBOX_WITH_HOST_UPDATE_CHECK */
    625     RT_NOREF(aCheckType, aProgress);
    626     return setError(E_NOTIMPL, tr("Update checking support was not compiled into this VirtualBox build"));
    627 #endif /* !VBOX_WITH_HOST_UPDATE_CHECK */
    628 }
    629 
    630 HRESULT HostUpdate::getUpdateVersion(com::Utf8Str &aUpdateVersion)
    631 {
    632     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    633 
    634     aUpdateVersion = m_updateVersion;
    635 
    636     return S_OK;
    637 }
    638 
    639 HRESULT HostUpdate::getUpdateURL(com::Utf8Str &aUpdateURL)
    640 {
    641     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    642 
    643     aUpdateURL = m_updateURL;
    644 
    645     return S_OK;
    646 }
    647 
    648 HRESULT HostUpdate::getUpdateResponse(BOOL *aUpdateNeeded)
    649 {
    650     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    651 
    652     *aUpdateNeeded = m_updateNeeded;
    653 
    654     return S_OK;
    655 }
    656 
    657 HRESULT HostUpdate::getUpdateCheckNeeded(BOOL *aUpdateCheckNeeded)
    658 {
    659     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    660 
    661     HRESULT rc;
    662     ComPtr<ISystemProperties> pSystemProperties;
    663     rc = mVirtualBox->COMGETTER(SystemProperties)(pSystemProperties.asOutParam());
    664     if (FAILED(rc))
    665         return rc;
    666 
    667     /*
    668      * Is update checking enabled?
    669      */
    670     BOOL fVBoxUpdateEnabled;
    671     rc = pSystemProperties->COMGETTER(VBoxUpdateEnabled)(&fVBoxUpdateEnabled);
    672     if (FAILED(rc))
    673         return rc;
    674 
    675     if (!fVBoxUpdateEnabled)
    676     {
    677         *aUpdateCheckNeeded = false;
    678         return S_OK;
    679     }
    680 
    681     /*
    682      * When was the last update?
    683      */
    684     Bstr strVBoxUpdateLastCheckDate;
    685     rc = pSystemProperties->COMGETTER(VBoxUpdateLastCheckDate)(strVBoxUpdateLastCheckDate.asOutParam());
    686     if (FAILED(rc))
    687         return rc;
    688 
    689     // No prior update check performed so do so now
    690     if (strVBoxUpdateLastCheckDate.isEmpty())
    691     {
    692         *aUpdateCheckNeeded = true;
    693         return S_OK;
    694     }
    695 
    696     // convert stored timestamp to time spec
    697     RTTIMESPEC LastCheckTime;
    698     if (!RTTimeSpecFromString(&LastCheckTime, Utf8Str(strVBoxUpdateLastCheckDate).c_str()))
    699     {
    700         *aUpdateCheckNeeded = true;
    701         return S_OK;
    702     }
    703 
    704     /*
    705      * Compare last update with how often we are supposed to check for updates.
    706      */
    707     ULONG uVBoxUpdateFrequency = 0;  // value in days
    708     rc = pSystemProperties->COMGETTER(VBoxUpdateFrequency)(&uVBoxUpdateFrequency);
    709     if (FAILED(rc))
    710         return rc;
    711 
    712     if (!uVBoxUpdateFrequency)
    713     {
    714         /* Consider config (enable, 0 day interval) as checking once but never again.
    715            We've already check since we've got a date. */
    716         *aUpdateCheckNeeded = false;
    717         return S_OK;
    718     }
    719     uint64_t const cSecsInXDays = uVBoxUpdateFrequency * RT_SEC_1DAY_64;
    720 
    721     RTTIMESPEC TimeDiff;
    722     RTTimeSpecSub(RTTimeNow(&TimeDiff), &LastCheckTime);
    723 
    724     LogRelFunc(("Checking if seconds since last check (%lld) >= Number of seconds in %lu day%s (%lld)\n",
    725                 RTTimeSpecGetSeconds(&TimeDiff), uVBoxUpdateFrequency, uVBoxUpdateFrequency > 1 ? "s" : "", cSecsInXDays));
    726 
    727     if (RTTimeSpecGetSeconds(&TimeDiff) >= (int64_t)cSecsInXDays)
    728         *aUpdateCheckNeeded = true;
    729 
    730     return S_OK;
    731 }
    732 
    733 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r94598 r94643  
    8080# include "PerformanceImpl.h"
    8181#endif /* VBOX_WITH_RESOURCE_USAGE_API */
     82#ifdef VBOX_WITH_UPDATE_AGENT
     83# include "UpdateAgentImpl.h"
     84#endif
    8285#include "EventImpl.h"
    8386#ifdef VBOX_WITH_EXTPACK
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette