Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 18405)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 18406)
@@ -127,5 +127,8 @@
                )
             {
-                RTPrintf("(%ld/%ld) %ls %ld%% => %ld%%\n", ulOperation + 1, cOperations, bstrOperationDescription.raw(), ulCurrentOperationPercent, ulCurrentPercent);
+                LONG lSecsRem;
+                progress->COMGETTER(TimeRemaining)(&lSecsRem);
+
+                RTPrintf("(%ld/%ld) %ls %ld%% => %ld%% (%d s remaining)\n", ulOperation + 1, cOperations, bstrOperationDescription.raw(), ulCurrentOperationPercent, ulCurrentPercent, lSecsRem);
                 ulLastPercent = ulCurrentPercent;
                 ulLastOperationPercent = ulCurrentOperationPercent;
Index: /trunk/src/VBox/Main/ProgressImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ProgressImpl.cpp	(revision 18405)
+++ /trunk/src/VBox/Main/ProgressImpl.cpp	(revision 18406)
@@ -66,4 +66,7 @@
     m_ulCurrentOperationWeight =
     m_ulOperationPercent = 0;
+
+    // get creation timestamp
+    m_ullTimestamp = RTTimeMilliTS();
 
     return S_OK;
@@ -258,4 +261,59 @@
 }
 
+/**
+ * Internal helper to compute the total percent value based on the member values and
+ * returns it as a "double". This is used both by GetPercent (which returns it as a
+ * rounded ULONG) and GetTimeRemaining().
+ *
+ * Requires locking by the caller!
+ *
+ * @return fractional percentage as a double value.
+ */
+double ProgressBase::calcTotalPercent()
+{
+    // avoid division by zero
+    if (m_ulTotalOperationsWeight == 0)
+        return 0;
+
+    double dPercent = (    (double)m_ulOperationsCompletedWeight                                              // weight of operations that have been completed
+                         + ((double)m_ulOperationPercent * (double)m_ulCurrentOperationWeight / (double)100)  // plus partial weight of the current operation
+                      ) * (double)100 / (double)m_ulTotalOperationsWeight;
+
+    return dPercent;
+}
+
+STDMETHODIMP ProgressBase::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
+{
+    CheckComArgOutPointerValid(aTimeRemaining);
+
+    AutoCaller autoCaller(this);
+    CheckComRCReturnRC(autoCaller.rc());
+
+    AutoReadLock alock(this);
+
+    if (mCompleted)
+        *aTimeRemaining = 0;
+    else
+    {
+        double dPercentDone = calcTotalPercent();
+        if (dPercentDone < 1)
+            *aTimeRemaining = -1;       // unreliable, or avoid division by 0 below
+        else
+        {
+            uint64_t ullTimeNow = RTTimeMilliTS();
+            uint64_t ullTimeElapsed = ullTimeNow - m_ullTimestamp;
+            uint64_t ullTimeTotal = (uint64_t)(ullTimeElapsed / dPercentDone * 100);
+            uint64_t ullTimeRemaining = ullTimeTotal - ullTimeElapsed;
+
+//             Log(("ProgressBase::GetTimeRemaining: dPercentDone %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n",
+//                         (uint32_t)dPercentDone, ullTimeNow, ullTimeElapsed, ullTimeTotal, ullTimeRemaining));
+
+            *aTimeRemaining = (LONG)(ullTimeRemaining / 1000);
+        }
+    }
+
+    return S_OK;
+}
+
 STDMETHODIMP ProgressBase::COMGETTER(Percent)(ULONG *aPercent)
 {
@@ -271,8 +329,5 @@
     else
     {
-        ULONG ulPercent = (ULONG)(    (    (double)m_ulOperationsCompletedWeight                                              // weight of operations that have been completed
-                                         + ((double)m_ulOperationPercent * (double)m_ulCurrentOperationWeight / (double)100)  // plus partial weight of the current operation
-                                      ) * (double)100 / (double)m_ulTotalOperationsWeight
-                                 );
+        ULONG ulPercent = (ULONG)calcTotalPercent();
         // do not report 100% until we're really really done with everything as the Qt GUI dismisses progress dialogs in that case
         if (    ulPercent == 100
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 18405)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 18406)
@@ -7821,10 +7821,10 @@
   <interface
      name="IProgress" extends="$unknown"
-     uuid="ee1aa091-fda8-47a9-8f1c-4bba002a3229"
+     uuid="c4f94e6b-2273-446b-9539-4c05bb416fe7"
      wsmap="managed"
      >
     <desc>
-        The IProgress interface allows for monitoring the progress of
-        an asynchronous tasks within VirtualBox.
+        The IProgress interface is used to track and control
+        asynchronous tasks within VirtualBox.
 
         An instance of this is returned every time VirtualBox starts
@@ -7844,6 +7844,6 @@
         cancel the task by calling <link to="#cancel" />.
 
-        A task represented by IProgress can consist of one or more
-        sub-operations that run sequentially, one by one (see
+        A task represented by IProgress consists of either one or
+        several sub-operations that run sequentially, one by one (see
         <link to="#operation" /> and <link to="#operationCount" />).
         Every operation is identified by a number (starting from 0)
@@ -7854,4 +7854,5 @@
         percentage of completion of the task as a whole
         in <link to="#percent" />.
+
         Similarly, you can wait for the completion of a particular
         operation via <link to="#waitForOperationCompletion" /> or
@@ -7882,4 +7883,21 @@
         Returns 100 if <link to="#completed" /> is true.
       </desc>
+    </attribute>
+
+    <attribute name="timeRemaining" type="long" readonly="yes">
+        <desc>
+            Estimated remaining time until the operation completes, in
+            seconds.
+
+            Returns 0 if the task is complete.
+
+            Returns -1 if the time cannot be computed, in
+            particular if the current progress is 0.
+
+            The estimate will be unreliable for low progress
+            values. It will become more reliable as the task progresses;
+            it is not recommended to display an ETA before 10% of
+            a task have completed.
+        </desc>
     </attribute>
 
Index: /trunk/src/VBox/Main/include/ProgressImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ProgressImpl.h	(revision 18405)
+++ /trunk/src/VBox/Main/include/ProgressImpl.h	(revision 18406)
@@ -73,4 +73,5 @@
     STDMETHOD(COMGETTER(Cancelable)) (BOOL *aCancelable);
     STDMETHOD(COMGETTER(Percent)) (ULONG *aPercent);
+    STDMETHOD(COMGETTER(TimeRemaining)) (LONG *aTimeRemaining);
     STDMETHOD(COMGETTER(Completed)) (BOOL *aCompleted);
     STDMETHOD(COMGETTER(Canceled)) (BOOL *aCanceled);
@@ -91,4 +92,5 @@
     BOOL completed() const { return mCompleted; }
     HRESULT resultCode() const { return mResultCode; }
+    double calcTotalPercent();
 
 protected:
@@ -103,4 +105,6 @@
     const Guid mId;
     const Bstr mDescription;
+
+    uint64_t m_ullTimestamp;                        // progress object creation timestamp, for ETA computation
 
     /* The fields below are to be properly initalized by subclasses */
