Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

file_downloader.cpp 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
  2. *
  3. * Copyright (C) 1995-2011 Opera Software ASA. All rights reserved.
  4. *
  5. * This file is part of the Opera web browser.
  6. * It may not be distributed under any circumstances.
  7. *
  8. * Per Arne Vollan (pav)
  9. */
  10. #include "core/pch.h"
  11. #ifdef AUTO_UPDATE_SUPPORT
  12. #include "adjunct/autoupdate/file_downloader.h"
  13. #include "adjunct/autoupdate/statusxmldownloader.h"
  14. #include "modules/prefs/prefsmanager/collections/pc_ui.h"
  15. #include "modules/url/url2.h"
  16. #include "modules/windowcommander/src/TransferManager.h"
  17. #include "modules/util/opfile/opfile.h"
  18. ////////////////////////////////////////////////////////////////////////////////////////////////
  19. ////////////////////////////////////////////////////////////////////////////////////////////////
  20. /// ///
  21. /// FileDownloader ///
  22. /// ///
  23. ////////////////////////////////////////////////////////////////////////////////////////////////
  24. ////////////////////////////////////////////////////////////////////////////////////////////////
  25. FileDownloader::FileDownloader()
  26. : m_transferItem(NULL),
  27. m_listener(NULL),
  28. m_url_status(TRANSFER_INITIAL),
  29. m_download_started(FALSE)
  30. {
  31. }
  32. ////////////////////////////////////////////////////////////////////////////////////////////////
  33. FileDownloader::~FileDownloader()
  34. {
  35. if (m_transferItem)
  36. {
  37. m_transferItem->SetTransferListener(NULL);
  38. }
  39. g_main_message_handler->UnsetCallBack(this, MSG_HEADER_LOADED);
  40. g_main_message_handler->UnsetCallBack(this, MSG_URL_MOVED);
  41. }
  42. ////////////////////////////////////////////////////////////////////////////////////////////////
  43. OP_STATUS FileDownloader::StartDownload(const OpStringC &url, const OpStringC &target_filename)
  44. {
  45. OpStatus::Ignore(m_url_string.Set(url));
  46. // Hold the downloaded filename
  47. m_file_name.Set(target_filename);
  48. // Set initial status
  49. m_url_status = TRANSFER_INITIAL;
  50. if(m_transferItem)
  51. {
  52. if(m_transferItem->GetURL() && m_transferItem->GetURL()->GetAttribute(URL::KLoadStatus, TRUE) == URL_LOADED)
  53. {
  54. m_url_status = TRANSFER_DONE;
  55. OnProgress(m_transferItem, TRANSFER_DONE);
  56. return OpStatus::OK;
  57. }
  58. BOOL ret = m_transferItem->Continue();
  59. return ret? OpStatus::OK : OpStatus::ERR;
  60. }
  61. // Create the transfer object
  62. BOOL already_created = FALSE;
  63. RETURN_IF_ERROR(g_transferManager->GetTransferItem(&m_transferItem, url.CStr(), &already_created));
  64. if (m_transferItem)
  65. {
  66. static_cast<TransferItem*>(m_transferItem)->SetShowTransfer(FALSE);
  67. URL* url = m_transferItem->GetURL();
  68. if (url)
  69. {
  70. // Set the listener and start the download
  71. m_transferItem->SetTransferListener(this);
  72. m_download_url = *url;
  73. url->SetAttribute(URL::KOverrideRedirectDisabled, TRUE);
  74. g_main_message_handler->SetCallBack(this, MSG_HEADER_LOADED, url->Id());
  75. g_main_message_handler->SetCallBack(this, MSG_URL_MOVED, url->Id());
  76. m_download_started = TRUE;
  77. if(already_created)
  78. {
  79. if(m_transferItem->GetURL()->GetAttribute(URL::KLoadStatus, TRUE) == URL_LOADED)
  80. {
  81. m_url_status = TRANSFER_DONE;
  82. OnProgress(m_transferItem, TRANSFER_DONE);
  83. return OpStatus::OK;
  84. }
  85. static_cast<TransferItem*>(m_transferItem)->ResetStatus();
  86. BOOL ret = m_transferItem->Continue();
  87. if(ret)
  88. {
  89. return OpStatus::OK;
  90. }
  91. }
  92. DeleteDownloadedFile();
  93. if(url->Load(g_main_message_handler, URL()) == COMM_LOADING)
  94. {
  95. return OpStatus::OK;
  96. }
  97. }
  98. }
  99. return OpStatus::ERR;
  100. }
  101. ////////////////////////////////////////////////////////////////////////////////////////////////
  102. OP_STATUS FileDownloader::StopDownload()
  103. {
  104. if(m_transferItem)
  105. {
  106. m_transferItem->Stop();
  107. }
  108. m_download_started = FALSE;
  109. return OpStatus::OK;
  110. }
  111. ////////////////////////////////////////////////////////////////////////////////////////////////
  112. BOOL FileDownloader::Downloaded() const
  113. {
  114. return m_url_status == TRANSFER_DONE;
  115. }
  116. ////////////////////////////////////////////////////////////////////////////////////////////////
  117. BOOL FileDownloader::DownloadFailed() const
  118. {
  119. return m_url_status == TRANSFER_ABORTED || m_url_status == TRANSFER_FAILED;
  120. }
  121. ////////////////////////////////////////////////////////////////////////////////////////////////
  122. OpFileLength FileDownloader::GetFileSize()
  123. {
  124. OP_ASSERT(m_transferItem);
  125. // The downloaded file size may come from the server that is hosting it, the size is then sent in
  126. // the HTTP headers. It may also be overrided by a class that implements the GetOverridedFileLength()
  127. // method.
  128. // In case we get a size from the HTTP server, we prefer that, since we trust it is valid. However in case
  129. // there are no HTTP headers with the size, we try to use the size coming from the override.
  130. OpFileLength size_from_url = m_transferItem->GetSize();
  131. if (0 == size_from_url)
  132. return GetOverridedFileLength();
  133. else
  134. return size_from_url;
  135. }
  136. OpFileLength FileDownloader::GetHaveSize()
  137. {
  138. if (m_transferItem)
  139. return m_transferItem->GetHaveSize();
  140. return 0;
  141. }
  142. void FileDownloader::OnProgress(OpTransferItem* transferItem, TransferStatus status)
  143. {
  144. OP_ASSERT(transferItem == m_transferItem);
  145. m_url_status = status;
  146. switch (status)
  147. {
  148. case TRANSFER_PROGRESS:
  149. {
  150. OpFileLength total_size = GetFileSize();
  151. OpFileLength downloaded_size = transferItem->GetHaveSize();
  152. // It may happen that the size returned by GetFileSize() comes from the override and that the
  153. // overrided size is smaller than the download size. In that case we return the greater value
  154. // so that the caller never receives an update about a progress that is greater than 100%.
  155. if (downloaded_size > total_size)
  156. total_size = downloaded_size;
  157. double kbps = transferItem->GetKbps();
  158. unsigned long time_estimate = transferItem->GetTimeEstimate();
  159. if(m_listener)
  160. {
  161. m_listener->OnFileDownloadProgress(this, total_size, downloaded_size, kbps, time_estimate);
  162. }
  163. break;
  164. }
  165. case TRANSFER_DONE:
  166. {
  167. // Reset the KOverrideRedirectDisabled
  168. transferItem->GetURL()->SetAttribute(URL::KOverrideRedirectDisabled, FALSE);
  169. if(m_listener)
  170. {
  171. OpFileLength total_size = GetFileSize();
  172. OpFileLength downloaded_size = transferItem->GetHaveSize();
  173. // It may happen that the size returned by GetFileSize() comes from the override and that the
  174. // overrided size is smaller than the download size. In that case we return the greater value
  175. // so that the caller never receives an update about a progress that is greater than 100%.
  176. if (downloaded_size > total_size)
  177. total_size = downloaded_size;
  178. double kbps = transferItem->GetKbps();
  179. unsigned long time_estimate = 0;
  180. m_listener->OnFileDownloadProgress(this, total_size, downloaded_size, kbps, time_estimate);
  181. m_listener->OnFileDownloadDone(this, total_size);
  182. }
  183. break;
  184. }
  185. case TRANSFER_ABORTED:
  186. {
  187. if(m_listener)
  188. {
  189. m_listener->OnFileDownloadAborted(this);
  190. }
  191. break;
  192. }
  193. case TRANSFER_FAILED:
  194. {
  195. // Reset the KOverrideRedirectDisabled
  196. transferItem->GetURL()->SetAttribute(URL::KOverrideRedirectDisabled, FALSE);
  197. if(m_listener)
  198. {
  199. m_listener->OnFileDownloadFailed(this);
  200. }
  201. break;
  202. }
  203. }
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////////////////////
  206. void FileDownloader::OnRedirect(OpTransferItem* transferItem, URL* redirect_from, URL* redirect_to)
  207. {
  208. }
  209. ////////////////////////////////////////////////////////////////////////////////////////////////
  210. void FileDownloader::HandleCallback(OpMessage msg, MH_PARAM_1 par1, MH_PARAM_2 par2)
  211. {
  212. switch(msg)
  213. {
  214. case MSG_URL_MOVED:
  215. {
  216. g_main_message_handler->UnsetCallBack(this, MSG_HEADER_LOADED);
  217. g_main_message_handler->UnsetCallBack(this, MSG_URL_MOVED);
  218. g_main_message_handler->SetCallBack(this, MSG_HEADER_LOADED, par2);
  219. g_main_message_handler->SetCallBack(this, MSG_URL_MOVED, par2);
  220. URL moved_url;
  221. moved_url = m_download_url.GetAttribute(URL::KMovedToURL, TRUE);
  222. m_download_url = moved_url;
  223. break;
  224. }
  225. case MSG_HEADER_LOADED:
  226. {
  227. g_main_message_handler->UnsetCallBack(this, MSG_HEADER_LOADED);
  228. g_main_message_handler->UnsetCallBack(this, MSG_URL_MOVED);
  229. m_download_url.LoadToFile(m_file_name);
  230. OpString url;
  231. url.Set(m_download_url.GetUniName(TRUE, PASSWORD_HIDDEN));
  232. if(m_url_string.Compare(url) != 0)
  233. {
  234. StatusXMLDownloaderHolder::ReplaceRedirectedFileURLs(m_url_string, url);
  235. }
  236. break;
  237. }
  238. }
  239. }
  240. ////////////////////////////////////////////////////////////////////////////////////////////////
  241. void FileDownloader::CleanUp()
  242. {
  243. if(m_transferItem)
  244. {
  245. g_transferManager->ReleaseTransferItem(m_transferItem);
  246. m_transferItem = NULL;
  247. }
  248. }
  249. ////////////////////////////////////////////////////////////////////////////////////////////////
  250. OP_STATUS FileDownloader::DeleteDownloadedFile()
  251. {
  252. OpFile f;
  253. RETURN_IF_ERROR(f.Construct(m_file_name.CStr(), OPFILE_ABSOLUTE_FOLDER));
  254. return f.Delete(FALSE);
  255. }
  256. ////////////////////////////////////////////////////////////////////////////////////////////////
  257. #endif //AUTO_UPDATE_SUPPORT