PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/content/browser/content_index/content_index_database.cc

https://github.com/chromium/chromium
C++ | 667 lines | 537 code | 115 blank | 15 comment | 54 complexity | 3a53972ccbbe4f0aef155f1722c46a2b MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, Apache-2.0, BSD-3-Clause
  1. // Copyright 2019 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 "content/browser/content_index/content_index_database.h"
  5. #include <set>
  6. #include <string>
  7. #include "base/barrier_closure.h"
  8. #include "base/containers/cxx20_erase.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/time/time.h"
  11. #include "content/browser/background_fetch/storage/image_helpers.h"
  12. #include "content/browser/content_index/content_index.pb.h"
  13. #include "content/browser/content_index/content_index_metrics.h"
  14. #include "content/public/browser/browser_context.h"
  15. #include "content/public/browser/browser_task_traits.h"
  16. #include "content/public/browser/browser_thread.h"
  17. #include "third_party/abseil-cpp/absl/types/optional.h"
  18. #include "third_party/blink/public/common/storage_key/storage_key.h"
  19. #include "url/gurl.h"
  20. #include "url/origin.h"
  21. // TODO(crbug.com/973844): Move image utility functions to common library.
  22. using content::background_fetch::DeserializeIcon;
  23. using content::background_fetch::SerializeIcon;
  24. namespace content {
  25. namespace {
  26. constexpr char kEntryPrefix[] = "content_index:entry_";
  27. constexpr char kIconPrefix[] = "content_index:icon_";
  28. std::string EntryKey(const std::string& id) {
  29. return kEntryPrefix + id;
  30. }
  31. std::string IconsKey(const std::string& id) {
  32. return kIconPrefix + id;
  33. }
  34. std::string CreateSerializedContentEntry(
  35. const blink::mojom::ContentDescription& description,
  36. const GURL& launch_url,
  37. base::Time entry_time,
  38. bool is_top_level_context) {
  39. // Convert description.
  40. proto::ContentDescription description_proto;
  41. description_proto.set_id(description.id);
  42. description_proto.set_title(description.title);
  43. description_proto.set_description(description.description);
  44. description_proto.set_category(static_cast<int>(description.category));
  45. for (const auto& icon : description.icons) {
  46. auto* icon_proto = description_proto.add_icons();
  47. icon_proto->set_src(icon->src);
  48. if (icon->sizes)
  49. icon_proto->set_sizes(*icon->sizes);
  50. if (icon->type)
  51. icon_proto->set_type(*icon->type);
  52. }
  53. description_proto.set_launch_url(description.launch_url);
  54. // Create entry.
  55. proto::ContentEntry entry;
  56. *entry.mutable_description() = std::move(description_proto);
  57. entry.set_launch_url(launch_url.spec());
  58. entry.set_timestamp(entry_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
  59. entry.set_is_top_level_context(is_top_level_context);
  60. return entry.SerializeAsString();
  61. }
  62. blink::mojom::ContentDescriptionPtr DescriptionFromProto(
  63. const proto::ContentDescription& description) {
  64. // Validate.
  65. if (description.category() <
  66. static_cast<int>(blink::mojom::ContentCategory::kMinValue) ||
  67. description.category() >
  68. static_cast<int>(blink::mojom::ContentCategory::kMaxValue)) {
  69. return nullptr;
  70. }
  71. // Convert.
  72. auto result = blink::mojom::ContentDescription::New();
  73. result->id = description.id();
  74. result->title = description.title();
  75. result->description = description.description();
  76. result->category =
  77. static_cast<blink::mojom::ContentCategory>(description.category());
  78. for (const auto& icon : description.icons()) {
  79. auto mojo_icon = blink::mojom::ContentIconDefinition::New();
  80. mojo_icon->src = icon.src();
  81. if (icon.has_sizes())
  82. mojo_icon->sizes = icon.sizes();
  83. if (icon.has_type())
  84. mojo_icon->type = icon.type();
  85. result->icons.push_back(std::move(mojo_icon));
  86. }
  87. result->launch_url = description.launch_url();
  88. return result;
  89. }
  90. absl::optional<ContentIndexEntry> EntryFromSerializedProto(
  91. int64_t service_worker_registration_id,
  92. const std::string& serialized_proto) {
  93. proto::ContentEntry entry_proto;
  94. if (!entry_proto.ParseFromString(serialized_proto))
  95. return absl::nullopt;
  96. GURL launch_url(entry_proto.launch_url());
  97. if (!launch_url.is_valid())
  98. return absl::nullopt;
  99. auto description = DescriptionFromProto(entry_proto.description());
  100. base::Time registration_time = base::Time::FromDeltaSinceWindowsEpoch(
  101. base::Microseconds(entry_proto.timestamp()));
  102. return ContentIndexEntry(service_worker_registration_id,
  103. std::move(description), std::move(launch_url),
  104. registration_time,
  105. entry_proto.is_top_level_context());
  106. }
  107. } // namespace
  108. ContentIndexDatabase::ContentIndexDatabase(
  109. BrowserContext* browser_context,
  110. scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
  111. : provider_(browser_context->GetContentIndexProvider()),
  112. service_worker_context_(std::move(service_worker_context)) {
  113. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  114. }
  115. ContentIndexDatabase::~ContentIndexDatabase() = default;
  116. void ContentIndexDatabase::AddEntry(
  117. int64_t service_worker_registration_id,
  118. const url::Origin& origin,
  119. bool is_top_level_context,
  120. blink::mojom::ContentDescriptionPtr description,
  121. const std::vector<SkBitmap>& icons,
  122. const GURL& launch_url,
  123. blink::mojom::ContentIndexService::AddCallback callback) {
  124. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  125. if (blocked_origins_.count(origin)) {
  126. // TODO(crbug.com/973844): Does this need a more specific error?
  127. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR);
  128. content_index::RecordRegistrationBlocked(description->category);
  129. return;
  130. }
  131. scoped_refptr<ServiceWorkerRegistration> service_worker_registration =
  132. service_worker_context_->GetLiveRegistration(
  133. service_worker_registration_id);
  134. if (!service_worker_registration ||
  135. !service_worker_registration->active_version()) {
  136. std::move(callback).Run(blink::mojom::ContentIndexError::NO_SERVICE_WORKER);
  137. return;
  138. }
  139. if (!service_worker_registration->key().origin().IsSameOriginWith(origin)) {
  140. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR);
  141. return;
  142. }
  143. auto serialized_icons = std::make_unique<proto::SerializedIcons>();
  144. proto::SerializedIcons* serialized_icons_ptr = serialized_icons.get();
  145. auto barrier_closure = base::BarrierClosure(
  146. icons.size(),
  147. base::BindOnce(&ContentIndexDatabase::DidSerializeIcons,
  148. weak_ptr_factory_.GetWeakPtr(),
  149. service_worker_registration_id, origin,
  150. is_top_level_context, std::move(description), launch_url,
  151. std::move(serialized_icons), std::move(callback)));
  152. for (const auto& icon : icons) {
  153. SerializeIcon(icon,
  154. base::BindOnce(
  155. [](base::OnceClosure done_closure,
  156. proto::SerializedIcons* icons, std::string icon) {
  157. icons->add_icons()->set_icon(std::move(icon));
  158. std::move(done_closure).Run();
  159. },
  160. barrier_closure, serialized_icons_ptr));
  161. }
  162. }
  163. void ContentIndexDatabase::DidSerializeIcons(
  164. int64_t service_worker_registration_id,
  165. const url::Origin& origin,
  166. bool is_top_level_context,
  167. blink::mojom::ContentDescriptionPtr description,
  168. const GURL& launch_url,
  169. std::unique_ptr<proto::SerializedIcons> serialized_icons,
  170. blink::mojom::ContentIndexService::AddCallback callback) {
  171. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  172. base::Time entry_time = base::Time::Now();
  173. std::string entry_key = EntryKey(description->id);
  174. std::string icon_key = IconsKey(description->id);
  175. std::string entry_value = CreateSerializedContentEntry(
  176. *description, launch_url, entry_time, is_top_level_context);
  177. std::string icons_value = serialized_icons->SerializeAsString();
  178. // Entry to pass over to the provider.
  179. ContentIndexEntry entry(service_worker_registration_id,
  180. std::move(description), launch_url, entry_time,
  181. is_top_level_context);
  182. service_worker_context_->StoreRegistrationUserData(
  183. service_worker_registration_id, blink::StorageKey(origin),
  184. {{std::move(entry_key), std::move(entry_value)},
  185. {std::move(icon_key), std::move(icons_value)}},
  186. base::BindOnce(&ContentIndexDatabase::DidAddEntry,
  187. weak_ptr_factory_.GetWeakPtr(), std::move(callback),
  188. std::move(entry)));
  189. }
  190. void ContentIndexDatabase::DidAddEntry(
  191. blink::mojom::ContentIndexService::AddCallback callback,
  192. ContentIndexEntry entry,
  193. blink::ServiceWorkerStatusCode status) {
  194. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  195. content_index::RecordDatabaseOperationStatus("Add", status);
  196. if (status != blink::ServiceWorkerStatusCode::kOk) {
  197. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR);
  198. return;
  199. }
  200. std::move(callback).Run(blink::mojom::ContentIndexError::NONE);
  201. std::vector<ContentIndexEntry> entries;
  202. entries.push_back(std::move(entry));
  203. NotifyProviderContentAdded(std::move(entries));
  204. }
  205. void ContentIndexDatabase::DeleteEntry(
  206. int64_t service_worker_registration_id,
  207. const url::Origin& origin,
  208. const std::string& entry_id,
  209. blink::mojom::ContentIndexService::DeleteCallback callback) {
  210. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  211. DeleteEntryImpl(service_worker_registration_id, origin, entry_id,
  212. std::move(callback));
  213. }
  214. void ContentIndexDatabase::DeleteEntryImpl(
  215. int64_t service_worker_registration_id,
  216. const url::Origin& origin,
  217. const std::string& entry_id,
  218. blink::mojom::ContentIndexService::DeleteCallback callback) {
  219. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  220. scoped_refptr<ServiceWorkerRegistration> service_worker_registration =
  221. service_worker_context_->GetLiveRegistration(
  222. service_worker_registration_id);
  223. if (!service_worker_registration ||
  224. !service_worker_registration->key().origin().IsSameOriginWith(origin)) {
  225. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR);
  226. return;
  227. }
  228. service_worker_context_->ClearRegistrationUserData(
  229. service_worker_registration_id, {EntryKey(entry_id), IconsKey(entry_id)},
  230. base::BindOnce(&ContentIndexDatabase::DidDeleteEntry,
  231. weak_ptr_factory_.GetWeakPtr(),
  232. service_worker_registration_id, origin, entry_id,
  233. std::move(callback)));
  234. }
  235. void ContentIndexDatabase::DidDeleteEntry(
  236. int64_t service_worker_registration_id,
  237. const url::Origin& origin,
  238. const std::string& entry_id,
  239. blink::mojom::ContentIndexService::DeleteCallback callback,
  240. blink::ServiceWorkerStatusCode status) {
  241. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  242. content_index::RecordDatabaseOperationStatus("Delete", status);
  243. if (status != blink::ServiceWorkerStatusCode::kOk) {
  244. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR);
  245. return;
  246. }
  247. std::move(callback).Run(blink::mojom::ContentIndexError::NONE);
  248. NotifyProviderContentDeleted(service_worker_registration_id, origin,
  249. entry_id);
  250. }
  251. void ContentIndexDatabase::GetDescriptions(
  252. int64_t service_worker_registration_id,
  253. const url::Origin& origin,
  254. blink::mojom::ContentIndexService::GetDescriptionsCallback callback) {
  255. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  256. scoped_refptr<ServiceWorkerRegistration> service_worker_registration =
  257. service_worker_context_->GetLiveRegistration(
  258. service_worker_registration_id);
  259. if (!service_worker_registration ||
  260. !service_worker_registration->key().origin().IsSameOriginWith(origin)) {
  261. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR,
  262. /* descriptions= */ {});
  263. return;
  264. }
  265. service_worker_context_->GetRegistrationUserDataByKeyPrefix(
  266. service_worker_registration_id, kEntryPrefix,
  267. base::BindOnce(&ContentIndexDatabase::DidGetDescriptions,
  268. weak_ptr_factory_.GetWeakPtr(),
  269. service_worker_registration_id, std::move(callback)));
  270. }
  271. void ContentIndexDatabase::DidGetDescriptions(
  272. int64_t service_worker_registration_id,
  273. blink::mojom::ContentIndexService::GetDescriptionsCallback callback,
  274. const std::vector<std::string>& data,
  275. blink::ServiceWorkerStatusCode status) {
  276. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  277. content_index::RecordDatabaseOperationStatus("GetDescriptions", status);
  278. if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
  279. std::move(callback).Run(blink::mojom::ContentIndexError::NONE,
  280. /* descriptions= */ {});
  281. return;
  282. } else if (status != blink::ServiceWorkerStatusCode::kOk) {
  283. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR,
  284. /* descriptions= */ {});
  285. return;
  286. }
  287. std::vector<blink::mojom::ContentDescriptionPtr> descriptions;
  288. descriptions.reserve(data.size());
  289. for (const auto& serialized_entry : data) {
  290. proto::ContentEntry entry;
  291. if (!entry.ParseFromString(serialized_entry)) {
  292. ClearServiceWorkerDataOnCorruption(service_worker_registration_id);
  293. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR,
  294. /* descriptions= */ {});
  295. return;
  296. }
  297. auto description = DescriptionFromProto(entry.description());
  298. if (!description) {
  299. // Clear entry data.
  300. service_worker_context_->ClearRegistrationUserData(
  301. service_worker_registration_id,
  302. {EntryKey(entry.description().id()),
  303. IconsKey(entry.description().id())},
  304. base::BindOnce(&content_index::RecordDatabaseOperationStatus,
  305. "ClearCorruptedData"));
  306. continue;
  307. }
  308. descriptions.push_back(std::move(description));
  309. }
  310. std::move(callback).Run(blink::mojom::ContentIndexError::NONE,
  311. std::move(descriptions));
  312. }
  313. void ContentIndexDatabase::GetIcons(
  314. int64_t service_worker_registration_id,
  315. const std::string& description_id,
  316. ContentIndexContext::GetIconsCallback callback) {
  317. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  318. service_worker_context_->GetRegistrationUserData(
  319. service_worker_registration_id, {IconsKey(description_id)},
  320. base::BindOnce(&ContentIndexDatabase::DidGetSerializedIcons,
  321. weak_ptr_factory_.GetWeakPtr(),
  322. service_worker_registration_id, std::move(callback)));
  323. }
  324. void ContentIndexDatabase::DidGetSerializedIcons(
  325. int64_t service_worker_registration_id,
  326. ContentIndexContext::GetIconsCallback callback,
  327. const std::vector<std::string>& data,
  328. blink::ServiceWorkerStatusCode status) {
  329. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  330. content_index::RecordDatabaseOperationStatus("GetIcon", status);
  331. if (status != blink::ServiceWorkerStatusCode::kOk || data.empty()) {
  332. std::move(callback).Run({});
  333. return;
  334. }
  335. DCHECK_EQ(data.size(), 1u);
  336. proto::SerializedIcons serialized_icons;
  337. if (!serialized_icons.ParseFromString(data.front())) {
  338. ClearServiceWorkerDataOnCorruption(service_worker_registration_id);
  339. std::move(callback).Run({});
  340. return;
  341. }
  342. if (serialized_icons.icons_size() == 0u) {
  343. // There are no icons.
  344. std::move(callback).Run({});
  345. return;
  346. }
  347. auto icons = std::make_unique<std::vector<SkBitmap>>();
  348. std::vector<SkBitmap>* icons_ptr = icons.get();
  349. auto barrier_closure = base::BarrierClosure(
  350. serialized_icons.icons_size(),
  351. base::BindOnce(&ContentIndexDatabase::DidDeserializeIcons,
  352. weak_ptr_factory_.GetWeakPtr(), std::move(callback),
  353. std::move(icons)));
  354. for (auto& serialized_icon : *serialized_icons.mutable_icons()) {
  355. DeserializeIcon(base::WrapUnique(serialized_icon.release_icon()),
  356. base::BindOnce(
  357. [](base::OnceClosure done_closure,
  358. std::vector<SkBitmap>* icons, SkBitmap icon) {
  359. icons->push_back(std::move(icon));
  360. std::move(done_closure).Run();
  361. },
  362. barrier_closure, icons_ptr));
  363. }
  364. }
  365. void ContentIndexDatabase::DidDeserializeIcons(
  366. ContentIndexContext::GetIconsCallback callback,
  367. std::unique_ptr<std::vector<SkBitmap>> icons) {
  368. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  369. std::move(callback).Run(std::move(*icons));
  370. }
  371. void ContentIndexDatabase::GetAllEntries(
  372. ContentIndexContext::GetAllEntriesCallback callback) {
  373. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  374. service_worker_context_->GetUserDataForAllRegistrationsByKeyPrefix(
  375. kEntryPrefix,
  376. base::BindOnce(&ContentIndexDatabase::DidGetEntries,
  377. weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  378. }
  379. void ContentIndexDatabase::DidGetEntries(
  380. ContentIndexContext::GetAllEntriesCallback callback,
  381. const std::vector<std::pair<int64_t, std::string>>& user_data,
  382. blink::ServiceWorkerStatusCode status) {
  383. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  384. content_index::RecordDatabaseOperationStatus("GetAllEntries", status);
  385. if (status != blink::ServiceWorkerStatusCode::kOk) {
  386. std::move(callback).Run(blink::mojom::ContentIndexError::STORAGE_ERROR,
  387. /* entries= */ {});
  388. return;
  389. }
  390. if (user_data.empty()) {
  391. std::move(callback).Run(blink::mojom::ContentIndexError::NONE,
  392. /* entries= */ {});
  393. return;
  394. }
  395. std::vector<ContentIndexEntry> entries;
  396. entries.reserve(user_data.size());
  397. std::set<int64_t> corrupted_sw_ids;
  398. for (const auto& ud : user_data) {
  399. auto entry = EntryFromSerializedProto(ud.first, ud.second);
  400. if (!entry) {
  401. corrupted_sw_ids.insert(ud.first);
  402. continue;
  403. }
  404. entries.emplace_back(std::move(*entry));
  405. }
  406. if (!corrupted_sw_ids.empty()) {
  407. // Remove soon-to-be-deleted entries.
  408. base::EraseIf(entries, [&corrupted_sw_ids](const auto& entry) {
  409. return corrupted_sw_ids.count(entry.service_worker_registration_id);
  410. });
  411. for (int64_t service_worker_registration_id : corrupted_sw_ids)
  412. ClearServiceWorkerDataOnCorruption(service_worker_registration_id);
  413. }
  414. std::move(callback).Run(blink::mojom::ContentIndexError::NONE,
  415. std::move(entries));
  416. }
  417. void ContentIndexDatabase::GetEntry(
  418. int64_t service_worker_registration_id,
  419. const std::string& description_id,
  420. ContentIndexContext::GetEntryCallback callback) {
  421. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  422. service_worker_context_->GetRegistrationUserData(
  423. service_worker_registration_id, {EntryKey(description_id)},
  424. base::BindOnce(&ContentIndexDatabase::DidGetEntry,
  425. weak_ptr_factory_.GetWeakPtr(),
  426. service_worker_registration_id, std::move(callback)));
  427. }
  428. void ContentIndexDatabase::DidGetEntry(
  429. int64_t service_worker_registration_id,
  430. ContentIndexContext::GetEntryCallback callback,
  431. const std::vector<std::string>& data,
  432. blink::ServiceWorkerStatusCode status) {
  433. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  434. content_index::RecordDatabaseOperationStatus("GetEntry", status);
  435. if (status != blink::ServiceWorkerStatusCode::kOk) {
  436. std::move(callback).Run(absl::nullopt);
  437. return;
  438. }
  439. DCHECK_EQ(data.size(), 1u);
  440. std::move(callback).Run(
  441. EntryFromSerializedProto(service_worker_registration_id, data.front()));
  442. }
  443. void ContentIndexDatabase::ClearServiceWorkerDataOnCorruption(
  444. int64_t service_worker_registration_id) {
  445. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  446. service_worker_context_->ClearRegistrationUserDataByKeyPrefixes(
  447. service_worker_registration_id, {kEntryPrefix, kIconPrefix},
  448. base::BindOnce(&content_index::RecordDatabaseOperationStatus,
  449. "ClearCorruptedData"));
  450. }
  451. void ContentIndexDatabase::DeleteItem(int64_t service_worker_registration_id,
  452. const url::Origin& origin,
  453. const std::string& description_id) {
  454. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  455. DeleteEntryImpl(
  456. service_worker_registration_id, origin, description_id,
  457. base::BindOnce(&ContentIndexDatabase::DidDeleteItem,
  458. weak_ptr_factory_.GetWeakPtr(),
  459. service_worker_registration_id, origin, description_id));
  460. }
  461. void ContentIndexDatabase::DidDeleteItem(
  462. int64_t service_worker_registration_id,
  463. const url::Origin& origin,
  464. const std::string& description_id,
  465. blink::mojom::ContentIndexError error) {
  466. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  467. if (error != blink::mojom::ContentIndexError::NONE)
  468. return;
  469. service_worker_context_->FindReadyRegistrationForId(
  470. service_worker_registration_id, blink::StorageKey(origin),
  471. base::BindOnce(&ContentIndexDatabase::StartActiveWorkerForDispatch,
  472. weak_ptr_factory_.GetWeakPtr(), description_id));
  473. }
  474. void ContentIndexDatabase::StartActiveWorkerForDispatch(
  475. const std::string& description_id,
  476. blink::ServiceWorkerStatusCode service_worker_status,
  477. scoped_refptr<ServiceWorkerRegistration> registration) {
  478. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  479. content_index::RecordDisptachStatus("Find", service_worker_status);
  480. if (service_worker_status != blink::ServiceWorkerStatusCode::kOk)
  481. return;
  482. ServiceWorkerVersion* service_worker_version = registration->active_version();
  483. DCHECK(service_worker_version);
  484. service_worker_version->RunAfterStartWorker(
  485. ServiceWorkerMetrics::EventType::CONTENT_DELETE,
  486. base::BindOnce(&ContentIndexDatabase::DeliverMessageToWorker,
  487. weak_ptr_factory_.GetWeakPtr(),
  488. base::WrapRefCounted(service_worker_version),
  489. std::move(registration), description_id));
  490. }
  491. void ContentIndexDatabase::DeliverMessageToWorker(
  492. scoped_refptr<ServiceWorkerVersion> service_worker,
  493. scoped_refptr<ServiceWorkerRegistration> registration,
  494. const std::string& description_id,
  495. blink::ServiceWorkerStatusCode service_worker_status) {
  496. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  497. content_index::RecordDisptachStatus("Start", service_worker_status);
  498. if (service_worker_status != blink::ServiceWorkerStatusCode::kOk)
  499. return;
  500. // Don't allow DB operations while the `contentdelete` event is firing.
  501. // This is to prevent re-registering the deleted content within the event.
  502. BlockOrigin(service_worker->key().origin());
  503. int request_id = service_worker->StartRequest(
  504. ServiceWorkerMetrics::EventType::CONTENT_DELETE,
  505. base::BindOnce(&ContentIndexDatabase::DidDispatchEvent,
  506. weak_ptr_factory_.GetWeakPtr(),
  507. service_worker->key().origin()));
  508. service_worker->endpoint()->DispatchContentDeleteEvent(
  509. description_id, service_worker->CreateSimpleEventCallback(request_id));
  510. }
  511. void ContentIndexDatabase::DidDispatchEvent(
  512. const url::Origin& origin,
  513. blink::ServiceWorkerStatusCode service_worker_status) {
  514. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  515. content_index::RecordDisptachStatus("Dispatch", service_worker_status);
  516. UnblockOrigin(origin);
  517. }
  518. void ContentIndexDatabase::BlockOrigin(const url::Origin& origin) {
  519. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  520. blocked_origins_[origin]++;
  521. }
  522. void ContentIndexDatabase::UnblockOrigin(const url::Origin& origin) {
  523. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  524. DCHECK(blocked_origins_.count(origin));
  525. auto it = blocked_origins_.find(origin);
  526. if (it->second == 1)
  527. blocked_origins_.erase(it);
  528. else
  529. it->second--;
  530. }
  531. void ContentIndexDatabase::Shutdown() {
  532. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  533. provider_ = nullptr;
  534. }
  535. void ContentIndexDatabase::NotifyProviderContentAdded(
  536. std::vector<ContentIndexEntry> entries) {
  537. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  538. if (!provider_)
  539. return;
  540. for (auto& entry : entries)
  541. provider_->OnContentAdded(std::move(entry));
  542. }
  543. void ContentIndexDatabase::NotifyProviderContentDeleted(
  544. int64_t service_worker_registration_id,
  545. const url::Origin& origin,
  546. const std::string& entry_id) {
  547. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  548. if (!provider_)
  549. return;
  550. provider_->OnContentDeleted(service_worker_registration_id, origin, entry_id);
  551. }
  552. } // namespace content