download_db_conversions.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/download/database/download_db_conversions.h"
  5. #include <utility>
  6. #include "base/notreached.h"
  7. #include "base/pickle.h"
  8. #include "base/time/time.h"
  9. #include "components/download/public/common/download_features.h"
  10. #include "services/network/public/mojom/fetch_api.mojom-shared.h"
  11. namespace download {
  12. namespace {
  13. // Converts base::Time to a timpstamp in milliseconds.
  14. int64_t FromTimeToMilliseconds(base::Time time) {
  15. return time.ToDeltaSinceWindowsEpoch().InMilliseconds();
  16. }
  17. // Converts a time stamp in milliseconds to base::Time.
  18. base::Time FromMillisecondsToTime(int64_t time_ms) {
  19. return base::Time::FromDeltaSinceWindowsEpoch(base::Milliseconds(time_ms));
  20. }
  21. } // namespace
  22. DownloadEntry DownloadDBConversions::DownloadEntryFromProto(
  23. const download_pb::DownloadEntry& proto) {
  24. DownloadEntry entry;
  25. entry.guid = proto.guid();
  26. entry.request_origin = proto.request_origin();
  27. entry.download_source = DownloadSourceFromProto(proto.download_source());
  28. entry.ukm_download_id = proto.ukm_download_id();
  29. entry.bytes_wasted = proto.bytes_wasted();
  30. entry.fetch_error_body = proto.fetch_error_body();
  31. for (const auto& header : proto.request_headers()) {
  32. entry.request_headers.emplace_back(HttpRequestHeaderFromProto(header));
  33. }
  34. return entry;
  35. }
  36. download_pb::DownloadEntry DownloadDBConversions::DownloadEntryToProto(
  37. const DownloadEntry& entry) {
  38. download_pb::DownloadEntry proto;
  39. proto.set_guid(entry.guid);
  40. proto.set_request_origin(entry.request_origin);
  41. proto.set_download_source(DownloadSourceToProto(entry.download_source));
  42. proto.set_ukm_download_id(entry.ukm_download_id);
  43. proto.set_bytes_wasted(entry.bytes_wasted);
  44. proto.set_fetch_error_body(entry.fetch_error_body);
  45. for (const auto& header : entry.request_headers) {
  46. auto* proto_header = proto.add_request_headers();
  47. *proto_header = HttpRequestHeaderToProto(header);
  48. }
  49. return proto;
  50. }
  51. // static
  52. DownloadSource DownloadDBConversions::DownloadSourceFromProto(
  53. download_pb::DownloadSource download_source) {
  54. switch (download_source) {
  55. case download_pb::DownloadSource::UNKNOWN:
  56. return DownloadSource::UNKNOWN;
  57. case download_pb::DownloadSource::NAVIGATION:
  58. return DownloadSource::NAVIGATION;
  59. case download_pb::DownloadSource::DRAG_AND_DROP:
  60. return DownloadSource::DRAG_AND_DROP;
  61. case download_pb::DownloadSource::FROM_RENDERER:
  62. return DownloadSource::FROM_RENDERER;
  63. case download_pb::DownloadSource::EXTENSION_API:
  64. return DownloadSource::EXTENSION_API;
  65. case download_pb::DownloadSource::EXTENSION_INSTALLER:
  66. return DownloadSource::EXTENSION_INSTALLER;
  67. case download_pb::DownloadSource::INTERNAL_API:
  68. return DownloadSource::INTERNAL_API;
  69. case download_pb::DownloadSource::WEB_CONTENTS_API:
  70. return DownloadSource::WEB_CONTENTS_API;
  71. case download_pb::DownloadSource::OFFLINE_PAGE:
  72. return DownloadSource::OFFLINE_PAGE;
  73. case download_pb::DownloadSource::CONTEXT_MENU:
  74. return DownloadSource::CONTEXT_MENU;
  75. case download_pb::DownloadSource::RETRY:
  76. return DownloadSource::RETRY;
  77. case download_pb::DownloadSource::RETRY_FROM_BUBBLE:
  78. return DownloadSource::RETRY_FROM_BUBBLE;
  79. }
  80. NOTREACHED();
  81. return DownloadSource::UNKNOWN;
  82. }
  83. // static
  84. download_pb::DownloadSource DownloadDBConversions::DownloadSourceToProto(
  85. DownloadSource download_source) {
  86. switch (download_source) {
  87. case DownloadSource::UNKNOWN:
  88. return download_pb::DownloadSource::UNKNOWN;
  89. case DownloadSource::NAVIGATION:
  90. return download_pb::DownloadSource::NAVIGATION;
  91. case DownloadSource::DRAG_AND_DROP:
  92. return download_pb::DownloadSource::DRAG_AND_DROP;
  93. case DownloadSource::FROM_RENDERER:
  94. return download_pb::DownloadSource::FROM_RENDERER;
  95. case DownloadSource::EXTENSION_API:
  96. return download_pb::DownloadSource::EXTENSION_API;
  97. case DownloadSource::EXTENSION_INSTALLER:
  98. return download_pb::DownloadSource::EXTENSION_INSTALLER;
  99. case DownloadSource::INTERNAL_API:
  100. return download_pb::DownloadSource::INTERNAL_API;
  101. case DownloadSource::WEB_CONTENTS_API:
  102. return download_pb::DownloadSource::WEB_CONTENTS_API;
  103. case DownloadSource::OFFLINE_PAGE:
  104. return download_pb::DownloadSource::OFFLINE_PAGE;
  105. case DownloadSource::CONTEXT_MENU:
  106. return download_pb::DownloadSource::CONTEXT_MENU;
  107. case DownloadSource::RETRY:
  108. return download_pb::DownloadSource::RETRY;
  109. case DownloadSource::RETRY_FROM_BUBBLE:
  110. return download_pb::DownloadSource::RETRY_FROM_BUBBLE;
  111. }
  112. NOTREACHED();
  113. return download_pb::DownloadSource::UNKNOWN;
  114. }
  115. std::vector<DownloadEntry> DownloadDBConversions::DownloadEntriesFromProto(
  116. const download_pb::DownloadEntries& proto) {
  117. std::vector<DownloadEntry> entries;
  118. for (int i = 0; i < proto.entries_size(); i++)
  119. entries.push_back(DownloadEntryFromProto(proto.entries(i)));
  120. return entries;
  121. }
  122. download_pb::DownloadEntries DownloadDBConversions::DownloadEntriesToProto(
  123. const std::vector<DownloadEntry>& entries) {
  124. download_pb::DownloadEntries proto;
  125. for (size_t i = 0; i < entries.size(); i++) {
  126. download_pb::DownloadEntry* proto_entry = proto.add_entries();
  127. *proto_entry = DownloadEntryToProto(entries[i]);
  128. }
  129. return proto;
  130. }
  131. // static
  132. download_pb::HttpRequestHeader DownloadDBConversions::HttpRequestHeaderToProto(
  133. const std::pair<std::string, std::string>& header) {
  134. download_pb::HttpRequestHeader proto;
  135. if (header.first.empty())
  136. return proto;
  137. proto.set_key(header.first);
  138. proto.set_value(header.second);
  139. return proto;
  140. }
  141. // static
  142. std::pair<std::string, std::string>
  143. DownloadDBConversions::HttpRequestHeaderFromProto(
  144. const download_pb::HttpRequestHeader& proto) {
  145. if (proto.key().empty())
  146. return std::pair<std::string, std::string>();
  147. return std::make_pair(proto.key(), proto.value());
  148. }
  149. // static
  150. download_pb::InProgressInfo DownloadDBConversions::InProgressInfoToProto(
  151. const InProgressInfo& in_progress_info) {
  152. download_pb::InProgressInfo proto;
  153. for (size_t i = 0; i < in_progress_info.url_chain.size(); ++i)
  154. proto.add_url_chain(in_progress_info.url_chain[i].spec());
  155. proto.set_referrer_url(in_progress_info.referrer_url.spec());
  156. proto.set_serialized_embedder_download_data(
  157. in_progress_info.serialized_embedder_download_data);
  158. proto.set_tab_url(in_progress_info.tab_url.spec());
  159. proto.set_tab_referrer_url(in_progress_info.tab_referrer_url.spec());
  160. proto.set_fetch_error_body(in_progress_info.fetch_error_body);
  161. for (const auto& header : in_progress_info.request_headers) {
  162. auto* proto_header = proto.add_request_headers();
  163. *proto_header = HttpRequestHeaderToProto(header);
  164. }
  165. proto.set_etag(in_progress_info.etag);
  166. proto.set_last_modified(in_progress_info.last_modified);
  167. proto.set_mime_type(in_progress_info.mime_type);
  168. proto.set_original_mime_type(in_progress_info.original_mime_type);
  169. proto.set_total_bytes(in_progress_info.total_bytes);
  170. base::Pickle current_path;
  171. in_progress_info.current_path.WriteToPickle(&current_path);
  172. proto.set_current_path(current_path.data(), current_path.size());
  173. base::Pickle target_path;
  174. in_progress_info.target_path.WriteToPickle(&target_path);
  175. proto.set_target_path(target_path.data(), target_path.size());
  176. proto.set_received_bytes(in_progress_info.received_bytes);
  177. proto.set_start_time(
  178. in_progress_info.start_time.is_null()
  179. ? -1
  180. : FromTimeToMilliseconds(in_progress_info.start_time));
  181. proto.set_end_time(in_progress_info.end_time.is_null()
  182. ? -1
  183. : FromTimeToMilliseconds(in_progress_info.end_time));
  184. for (size_t i = 0; i < in_progress_info.received_slices.size(); ++i) {
  185. download_pb::ReceivedSlice* slice = proto.add_received_slices();
  186. slice->set_received_bytes(
  187. in_progress_info.received_slices[i].received_bytes);
  188. slice->set_offset(in_progress_info.received_slices[i].offset);
  189. slice->set_finished(in_progress_info.received_slices[i].finished);
  190. }
  191. proto.set_hash(in_progress_info.hash);
  192. proto.set_transient(in_progress_info.transient);
  193. proto.set_state(in_progress_info.state);
  194. proto.set_danger_type(in_progress_info.danger_type);
  195. proto.set_interrupt_reason(in_progress_info.interrupt_reason);
  196. proto.set_paused(in_progress_info.paused);
  197. proto.set_metered(in_progress_info.metered);
  198. proto.set_bytes_wasted(in_progress_info.bytes_wasted);
  199. proto.set_auto_resume_count(in_progress_info.auto_resume_count);
  200. // Fill in the output proto's |reroute_info| iff |in_progress_info|'s
  201. // |reroute_info| is initialized, because it has a required field and parsing
  202. // an uninitialized one to and from serialized strings would fail.
  203. if (in_progress_info.reroute_info.IsInitialized()) {
  204. *proto.mutable_reroute_info() = in_progress_info.reroute_info;
  205. }
  206. proto.set_credentials_mode(
  207. static_cast<int32_t>(in_progress_info.credentials_mode));
  208. proto.set_range_request_from(in_progress_info.range_request_from);
  209. proto.set_range_request_to(in_progress_info.range_request_to);
  210. return proto;
  211. }
  212. // static
  213. InProgressInfo DownloadDBConversions::InProgressInfoFromProto(
  214. const download_pb::InProgressInfo& proto) {
  215. InProgressInfo info;
  216. for (const auto& url : proto.url_chain())
  217. info.url_chain.emplace_back(url);
  218. info.referrer_url = GURL(proto.referrer_url());
  219. info.serialized_embedder_download_data =
  220. proto.serialized_embedder_download_data();
  221. info.tab_url = GURL(proto.tab_url());
  222. info.tab_referrer_url = GURL(proto.tab_referrer_url());
  223. info.fetch_error_body = proto.fetch_error_body();
  224. for (const auto& header : proto.request_headers())
  225. info.request_headers.emplace_back(HttpRequestHeaderFromProto(header));
  226. info.etag = proto.etag();
  227. info.last_modified = proto.last_modified();
  228. info.mime_type = proto.mime_type();
  229. info.original_mime_type = proto.original_mime_type();
  230. info.total_bytes = proto.total_bytes();
  231. base::PickleIterator current_path(
  232. base::Pickle(proto.current_path().data(), proto.current_path().size()));
  233. info.current_path.ReadFromPickle(&current_path);
  234. base::PickleIterator target_path(
  235. base::Pickle(proto.target_path().data(), proto.target_path().size()));
  236. info.target_path.ReadFromPickle(&target_path);
  237. info.received_bytes = proto.received_bytes();
  238. info.start_time = proto.start_time() == -1
  239. ? base::Time()
  240. : FromMillisecondsToTime(proto.start_time());
  241. info.end_time = proto.end_time() == -1
  242. ? base::Time()
  243. : FromMillisecondsToTime(proto.end_time());
  244. for (int i = 0; i < proto.received_slices_size(); ++i) {
  245. info.received_slices.emplace_back(proto.received_slices(i).offset(),
  246. proto.received_slices(i).received_bytes(),
  247. proto.received_slices(i).finished());
  248. }
  249. info.hash = proto.hash();
  250. info.transient = proto.transient();
  251. info.state = static_cast<DownloadItem::DownloadState>(proto.state());
  252. info.danger_type = static_cast<DownloadDangerType>(proto.danger_type());
  253. info.interrupt_reason =
  254. static_cast<DownloadInterruptReason>(proto.interrupt_reason());
  255. info.paused = proto.paused();
  256. info.metered = proto.metered();
  257. info.bytes_wasted = proto.bytes_wasted();
  258. info.auto_resume_count = proto.auto_resume_count();
  259. if (proto.has_reroute_info()) {
  260. info.reroute_info = proto.reroute_info();
  261. }
  262. if (proto.has_credentials_mode()) {
  263. info.credentials_mode = static_cast<::network::mojom::CredentialsMode>(
  264. proto.credentials_mode());
  265. }
  266. if (proto.has_range_request_from())
  267. info.range_request_from = proto.range_request_from();
  268. if (proto.has_range_request_to())
  269. info.range_request_to = proto.range_request_to();
  270. return info;
  271. }
  272. UkmInfo DownloadDBConversions::UkmInfoFromProto(
  273. const download_pb::UkmInfo& proto) {
  274. UkmInfo info;
  275. info.download_source = DownloadSourceFromProto(proto.download_source());
  276. info.ukm_download_id = proto.ukm_download_id();
  277. return info;
  278. }
  279. download_pb::UkmInfo DownloadDBConversions::UkmInfoToProto(
  280. const UkmInfo& info) {
  281. download_pb::UkmInfo proto;
  282. proto.set_download_source(DownloadSourceToProto(info.download_source));
  283. proto.set_ukm_download_id(info.ukm_download_id);
  284. return proto;
  285. }
  286. DownloadInfo DownloadDBConversions::DownloadInfoFromProto(
  287. const download_pb::DownloadInfo& proto) {
  288. DownloadInfo info;
  289. info.guid = proto.guid();
  290. info.id = proto.id();
  291. if (proto.has_ukm_info())
  292. info.ukm_info = UkmInfoFromProto(proto.ukm_info());
  293. if (proto.has_in_progress_info())
  294. info.in_progress_info = InProgressInfoFromProto(proto.in_progress_info());
  295. return info;
  296. }
  297. download_pb::DownloadInfo DownloadDBConversions::DownloadInfoToProto(
  298. const DownloadInfo& info) {
  299. download_pb::DownloadInfo proto;
  300. proto.set_guid(info.guid);
  301. proto.set_id(info.id);
  302. if (info.ukm_info.has_value()) {
  303. auto ukm_info = std::make_unique<download_pb::UkmInfo>(
  304. UkmInfoToProto(info.ukm_info.value()));
  305. proto.set_allocated_ukm_info(ukm_info.release());
  306. }
  307. if (info.in_progress_info.has_value()) {
  308. auto in_progress_info = std::make_unique<download_pb::InProgressInfo>(
  309. InProgressInfoToProto(info.in_progress_info.value()));
  310. proto.set_allocated_in_progress_info(in_progress_info.release());
  311. }
  312. return proto;
  313. }
  314. DownloadDBEntry DownloadDBConversions::DownloadDBEntryFromProto(
  315. const download_pb::DownloadDBEntry& proto) {
  316. DownloadDBEntry entry;
  317. if (proto.has_download_info())
  318. entry.download_info = DownloadInfoFromProto(proto.download_info());
  319. return entry;
  320. }
  321. download_pb::DownloadDBEntry DownloadDBConversions::DownloadDBEntryToProto(
  322. const DownloadDBEntry& info) {
  323. download_pb::DownloadDBEntry proto;
  324. if (info.download_info.has_value()) {
  325. auto download_info = std::make_unique<download_pb::DownloadInfo>(
  326. DownloadInfoToProto(info.download_info.value()));
  327. proto.set_allocated_download_info(download_info.release());
  328. }
  329. return proto;
  330. }
  331. DownloadDBEntry DownloadDBConversions::DownloadDBEntryFromDownloadEntry(
  332. const DownloadEntry& entry) {
  333. DownloadDBEntry db_entry;
  334. DownloadInfo download_info;
  335. download_info.guid = entry.guid;
  336. UkmInfo ukm_info(entry.download_source, entry.ukm_download_id);
  337. InProgressInfo in_progress_info;
  338. in_progress_info.fetch_error_body = entry.fetch_error_body;
  339. in_progress_info.request_headers = entry.request_headers;
  340. download_info.ukm_info = ukm_info;
  341. download_info.in_progress_info = in_progress_info;
  342. db_entry.download_info = download_info;
  343. return db_entry;
  344. }
  345. } // namespace download