| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifdef UNSAFE_BUFFERS_BUILD |
| // TODO(crbug.com/40285824): Remove this and convert code to safer constructs. |
| #pragma allow_unsafe_buffers |
| #endif |
| |
| #include "components/browsing_topics/common/semantic_tree.h" |
| |
| #include <map> |
| #include <set> |
| #include <variant> |
| |
| #include "base/check.h" |
| #include "base/check_op.h" |
| #include "base/containers/flat_set.h" |
| #include "base/containers/span.h" |
| #include "base/memory/raw_span.h" |
| #include "base/no_destructor.h" |
| #include "base/notreached.h" |
| #include "components/strings/grit/components_strings.h" |
| #include "third_party/blink/public/common/features.h" |
| |
| namespace browsing_topics { |
| |
| namespace { |
| |
| using RepresentativenessMap = |
| std::map<int, std::variant<int, std::pair<int, int>>>; |
| |
| constexpr size_t kInitialNumTopics = 349; |
| |
| constexpr Topic kNullTopic = Topic(0); |
| |
| // kChildToParent stores the first parent for each topic. This data structure |
| // was chosen to reduce the binary size, since most topics have at most one |
| // parent. Additional parents are added in GetParentTopics. |
| const uint16_t kChildToFirstParent[] = { |
| 0, 1, 1, 352, 1, 1, 1, 7, 352, 1, 1, 1, 12, 12, 12, |
| 12, 12, 12, 12, 12, 12, 12, 1, 23, 23, 23, 23, 23, 23, 23, |
| 23, 23, 23, 33, 33, 33, 23, 23, 23, 23, 40, 1, 1, 1, 363, |
| 45, 45, 45, 48, 45, 45, 45, 1, 53, 53, 53, 0, 57, 57, 57, |
| 57, 57, 62, 62, 62, 62, 62, 62, 62, 62, 62, 377, 62, 62, 62, |
| 377, 76, 377, 57, 57, 57, 57, 57, 83, 57, 0, 86, 86, 383, 385, |
| 88, 88, 385, 88, 388, 86, 86, 97, 86, 0, 100, 100, 0, 103, 104, |
| 103, 106, 103, 103, 103, 110, 110, 403, 103, 114, 103, 103, 117, 103, 103, |
| 103, 103, 103, 103, 103, 0, 126, 420, 126, 129, 129, 129, 129, 420, 420, |
| 126, 126, 137, 126, 126, 442, 140, 140, 442, 140, 140, 140, 140, 0, 149, |
| 150, 447, 149, 153, 149, 155, 447, 149, 158, 158, 158, 158, 158, 149, 164, |
| 164, 164, 164, 164, 447, 447, 0, 172, 173, 173, 175, 176, 173, 172, 0, |
| 180, 180, 180, 183, 183, 183, 183, 183, 183, 183, 183, 183, 180, 180, 180, |
| 0, 196, 196, 196, 196, 196, 201, 201, 196, 196, 196, 0, 519, 207, 207, |
| 207, 207, 207, 519, 0, 215, 530, 530, 215, 215, 215, 215, 215, 533, 215, |
| 0, 226, 227, 227, 227, 227, 231, 227, 227, 227, 226, 236, 236, 0, 239, |
| 239, 241, 0, 243, 243, 243, 243, 243, 243, 0, 250, 250, 250, 0, 254, |
| 255, 255, 255, 258, 258, 258, 254, 0, 263, 263, 265, 265, 265, 265, 265, |
| 263, 0, 272, 272, 0, 275, 275, 275, 0, 279, 279, 281, 279, 279, 279, |
| 279, 279, 279, 0, 289, 572, 289, 292, 572, 601, 572, 601, 572, 0, 299, |
| 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 312, 299, 299, |
| 299, 299, 299, 299, 299, 299, 299, 299, 621, 299, 299, 620, 299, 299, 299, |
| 299, 0, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 344, |
| 344, 344, 344, 332, 1, 1, 1, 352, 352, 352, 352, 352, 12, 23, 33, |
| 1, 361, 1, 363, 363, 363, 363, 53, 57, 57, 57, 57, 62, 62, 67, |
| 62, 62, 81, 81, 86, 380, 86, 88, 383, 88, 385, 88, 88, 97, 389, |
| 97, 97, 97, 97, 99, 100, 100, 100, 100, 100, 100, 103, 103, 103, 404, |
| 404, 404, 404, 408, 404, 103, 103, 103, 103, 103, 415, 103, 103, 103, 126, |
| 420, 420, 126, 129, 424, 424, 424, 129, 129, 129, 129, 431, 129, 126, 434, |
| 126, 137, 137, 140, 439, 439, 140, 442, 149, 444, 444, 149, 447, 447, 172, |
| 450, 450, 450, 450, 450, 450, 450, 457, 450, 172, 172, 172, 462, 462, 180, |
| 183, 183, 180, 196, 196, 196, 201, 207, 473, 473, 475, 475, 475, 207, 210, |
| 210, 207, 482, 482, 482, 482, 482, 487, 482, 482, 211, 211, 211, 211, 211, |
| 211, 211, 207, 498, 207, 213, 213, 207, 503, 503, 503, 207, 507, 508, 508, |
| 507, 507, 507, 507, 507, 515, 515, 515, 207, 519, 519, 521, 207, 207, 215, |
| 525, 215, 215, 528, 215, 530, 215, 215, 533, 533, 533, 227, 227, 227, 227, |
| 227, 227, 227, 227, 227, 227, 226, 238, 238, 238, 238, 238, 238, 238, 238, |
| 238, 238, 238, 236, 239, 243, 254, 258, 272, 272, 565, 565, 567, 565, 272, |
| 570, 289, 572, 572, 572, 575, 572, 577, 578, 577, 577, 577, 572, 583, 572, |
| 585, 585, 585, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 298, 298, |
| 289, 289, 289, 289, 604, 604, 289, 289, 299, 299, 299, 611, 611, 611, 611, |
| 611, 611, 611, 611, 299, 299, 340, 343, 332, 332, 332, 626, 626, 626}; |
| |
| static_assert(SemanticTree::kNumTopics == std::size(kChildToFirstParent)); |
| |
| // TaxonomyUpdate represents the incremental change from one taxonomy to the |
| // next. The structure assumes that a topic won't be added back after being |
| // deleted. It can be modified to support that use case by adding a field of |
| // IDs that are reintroduced. |
| struct TaxonomyUpdate { |
| // The number of topics in the new taxonomy. |
| const size_t taxonomy_size; |
| // The maximum topic ID in the new taxonomy. |
| const size_t max_topic_id; |
| // A map from the new or renamed topic ids to their associated localized name |
| // message ID. |
| base::flat_map<uint16_t, uint16_t> renamed_topics; |
| // The topics that have been deleted since the prior taxonomy version. |
| const base::raw_span<const uint16_t> deleted_topics; |
| }; |
| |
| const uint16_t kDeletedTopicsV2[] = { |
| 2, 3, 5, 6, 7, 8, 10, 11, 14, 16, 17, 22, 34, 35, 37, |
| 38, 39, 40, 41, 42, 43, 44, 45, 49, 54, 55, 58, 61, 77, 79, |
| 80, 85, 87, 98, 105, 106, 107, 108, 109, 110, 111, 112, 114, 115, 116, |
| 117, 118, 119, 120, 121, 122, 123, 124, 125, 127, 130, 133, 136, 138, 139, |
| 142, 143, 145, 146, 147, 148, 155, 156, 165, 166, 167, 168, 169, 174, 175, |
| 178, 179, 181, 182, 188, 189, 190, 193, 195, 197, 198, 199, 200, 203, 204, |
| 205, 206, 216, 219, 220, 221, 222, 223, 225, 228, 232, 235, 240, 241, 244, |
| 246, 248, 251, 252, 255, 256, 257, 261, 262, 266, 269, 270, 271, 273, 274, |
| 275, 276, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 290, 292, |
| 302, 305, 306, 307, 308, 311, 312, 313, 314, 316, 318, 319, 320, 326, 329, |
| 330, 331, 333, 339, 342, 344, 346, 347, 348, 349}; |
| |
| const TaxonomyUpdate* GetTaxonomyUpdateForTaxonomy2() { |
| static base::NoDestructor<TaxonomyUpdate> taxonomy_update([] { |
| TaxonomyUpdate ret = { |
| .taxonomy_size = 469, |
| .max_topic_id = 629, |
| .deleted_topics = base::span(kDeletedTopicsV2), |
| }; |
| for (uint16_t i = 350; i <= 629; ++i) { |
| ret.renamed_topics[i] = |
| IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V2_TOPIC_ID_350 + i - 350; |
| } |
| return ret; |
| }()); |
| return taxonomy_update.get(); |
| } |
| |
| // Each incremental taxonomy update after taxonomy 1. |
| const std::vector<const TaxonomyUpdate*>& GetTaxonomyUpdates() { |
| static const base::NoDestructor<std::vector<const TaxonomyUpdate*>> |
| kTaxonomyUpdates{{GetTaxonomyUpdateForTaxonomy2()}}; |
| return *kTaxonomyUpdates; |
| } |
| |
| // Stores pre-computed results from GetTopicsInTaxonomy for each |
| // TaxonomyUpdate. |
| std::vector<std::vector<Topic>>& GetTopicsForEachTaxonomyUpdate() { |
| static base::NoDestructor<std::vector<std::vector<Topic>>> |
| topics_in_taxonomies(GetTaxonomyUpdates().size()); |
| return *topics_in_taxonomies; |
| } |
| |
| static_assert(IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V1_TOPIC_ID_349 - |
| IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V1_TOPIC_ID_1 + 1 == |
| kInitialNumTopics); |
| |
| // These asserts also have a side-effect of preventing unused resource |
| // removal from removing them. |
| #define ASSERT_RESOURCE_ID_TAXONOMY_1(num) \ |
| static_assert(IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V1_TOPIC_ID_##num - \ |
| IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V1_TOPIC_ID_1 + 1 == \ |
| num) |
| #define ASSERT_RESOURCE_ID_TAXONOMY_2(num) \ |
| static_assert(IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V2_TOPIC_ID_##num - \ |
| IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V2_TOPIC_ID_350 + \ |
| 350 == \ |
| num) |
| ASSERT_RESOURCE_ID_TAXONOMY_1(2); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(3); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(4); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(5); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(6); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(7); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(8); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(9); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(10); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(11); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(12); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(13); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(14); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(15); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(16); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(17); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(18); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(19); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(20); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(21); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(22); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(23); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(24); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(25); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(26); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(27); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(28); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(29); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(30); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(31); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(32); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(33); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(34); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(35); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(36); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(37); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(38); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(39); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(40); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(41); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(42); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(43); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(44); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(45); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(46); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(47); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(48); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(49); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(50); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(51); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(52); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(53); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(54); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(55); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(56); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(57); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(58); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(59); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(60); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(61); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(62); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(63); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(64); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(65); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(66); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(67); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(68); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(69); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(70); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(71); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(72); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(73); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(74); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(75); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(76); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(77); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(78); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(79); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(80); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(81); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(82); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(83); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(84); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(85); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(86); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(87); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(88); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(89); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(90); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(91); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(92); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(93); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(94); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(95); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(96); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(97); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(98); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(99); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(100); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(101); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(102); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(103); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(104); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(105); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(106); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(107); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(108); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(109); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(110); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(111); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(112); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(113); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(114); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(115); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(116); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(117); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(118); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(119); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(120); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(121); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(122); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(123); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(124); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(125); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(126); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(127); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(128); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(129); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(130); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(131); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(132); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(133); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(134); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(135); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(136); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(137); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(138); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(139); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(140); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(141); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(142); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(143); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(144); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(145); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(146); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(147); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(148); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(149); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(150); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(151); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(152); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(153); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(154); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(155); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(156); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(157); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(158); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(159); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(160); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(161); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(162); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(163); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(164); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(165); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(166); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(167); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(168); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(169); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(170); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(171); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(172); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(173); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(174); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(175); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(176); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(177); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(178); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(179); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(180); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(181); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(182); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(183); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(184); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(185); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(186); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(187); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(188); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(189); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(190); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(191); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(192); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(193); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(194); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(195); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(196); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(197); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(198); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(199); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(200); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(201); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(202); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(203); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(204); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(205); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(206); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(207); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(208); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(209); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(210); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(211); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(212); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(213); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(214); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(215); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(216); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(217); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(218); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(219); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(220); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(221); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(222); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(223); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(224); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(225); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(226); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(227); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(228); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(229); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(230); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(231); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(232); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(233); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(234); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(235); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(236); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(237); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(238); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(239); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(240); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(241); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(242); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(243); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(244); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(245); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(246); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(247); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(248); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(249); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(250); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(251); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(252); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(253); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(254); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(255); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(256); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(257); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(258); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(259); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(260); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(261); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(262); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(263); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(264); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(265); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(266); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(267); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(268); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(269); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(270); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(271); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(272); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(273); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(274); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(275); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(276); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(277); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(278); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(279); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(280); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(281); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(282); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(283); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(284); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(285); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(286); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(287); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(288); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(289); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(290); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(291); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(292); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(293); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(294); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(295); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(296); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(297); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(298); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(299); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(300); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(301); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(302); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(303); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(304); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(305); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(306); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(307); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(308); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(309); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(310); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(311); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(312); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(313); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(314); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(315); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(316); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(317); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(318); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(319); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(320); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(321); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(322); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(323); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(324); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(325); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(326); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(327); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(328); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(329); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(330); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(331); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(332); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(333); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(334); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(335); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(336); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(337); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(338); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(339); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(340); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(341); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(342); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(343); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(344); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(345); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(346); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(347); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(348); |
| ASSERT_RESOURCE_ID_TAXONOMY_1(349); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(350); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(351); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(352); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(353); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(354); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(355); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(356); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(357); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(358); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(359); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(360); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(361); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(362); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(363); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(364); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(365); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(366); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(367); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(368); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(369); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(370); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(371); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(372); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(373); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(374); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(375); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(376); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(377); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(378); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(379); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(380); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(381); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(382); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(383); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(384); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(385); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(386); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(387); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(388); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(389); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(390); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(391); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(392); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(393); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(394); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(395); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(396); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(397); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(398); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(399); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(400); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(401); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(402); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(403); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(404); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(405); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(406); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(407); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(408); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(409); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(410); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(411); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(412); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(413); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(414); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(415); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(416); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(417); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(418); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(419); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(420); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(421); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(422); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(423); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(424); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(425); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(426); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(427); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(428); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(429); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(430); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(431); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(432); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(433); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(434); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(435); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(436); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(437); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(438); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(439); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(440); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(441); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(442); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(443); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(444); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(445); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(446); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(447); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(448); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(449); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(450); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(451); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(452); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(453); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(454); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(455); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(456); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(457); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(458); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(459); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(460); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(461); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(462); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(463); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(464); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(465); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(466); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(467); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(468); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(469); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(470); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(471); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(472); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(473); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(474); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(475); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(476); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(477); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(478); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(479); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(480); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(481); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(482); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(483); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(484); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(485); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(486); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(487); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(488); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(489); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(490); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(491); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(492); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(493); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(494); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(495); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(496); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(497); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(498); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(499); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(500); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(501); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(502); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(503); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(504); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(505); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(506); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(507); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(508); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(509); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(510); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(511); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(512); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(513); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(514); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(515); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(516); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(517); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(518); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(519); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(520); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(521); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(522); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(523); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(524); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(525); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(526); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(527); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(528); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(529); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(530); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(531); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(532); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(533); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(534); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(535); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(536); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(537); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(538); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(539); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(540); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(541); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(542); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(543); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(544); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(545); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(546); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(547); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(548); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(549); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(550); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(551); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(552); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(553); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(554); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(555); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(556); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(557); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(558); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(559); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(560); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(561); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(562); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(563); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(564); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(565); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(566); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(567); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(568); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(569); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(570); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(571); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(572); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(573); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(574); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(575); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(576); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(577); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(578); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(579); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(580); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(581); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(582); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(583); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(584); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(585); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(586); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(587); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(588); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(589); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(590); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(591); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(592); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(593); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(594); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(595); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(596); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(597); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(598); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(599); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(600); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(601); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(602); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(603); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(604); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(605); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(606); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(607); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(608); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(609); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(610); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(611); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(612); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(613); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(614); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(615); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(616); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(617); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(618); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(619); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(620); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(621); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(622); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(623); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(624); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(625); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(626); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(627); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(628); |
| ASSERT_RESOURCE_ID_TAXONOMY_2(629); |
| |
| bool IsTopicValid(Topic topic) { |
| int i = static_cast<int>(topic); |
| return i > 0 && i <= static_cast<int>(SemanticTree::kNumTopics); |
| } |
| |
| std::vector<Topic> GetParentTopics(Topic topic) { |
| if (kChildToFirstParent[static_cast<int>(topic) - 1] == |
| static_cast<int>(kNullTopic)) { |
| return {}; |
| } |
| std::vector<Topic> parents( |
| {Topic(kChildToFirstParent[static_cast<int>(topic) - 1])}); |
| |
| if (topic.value() == 277) { |
| parents.emplace_back(227); |
| } |
| return parents; |
| } |
| |
| bool IsAncestorTopic(Topic src, Topic target, bool only_direct = false) { |
| std::vector<Topic> parent_topics = GetParentTopics(src); |
| for (Topic topic : parent_topics) { |
| if (topic == target || |
| (!only_direct && IsAncestorTopic(topic, target, only_direct))) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| // Get the topics that are part of a taxonomy for taxonomy_version. Use |
| // this function only for taxonomy_version>1, since the first taxonomy is |
| // trivial (1-349). |
| const std::vector<Topic>& GetTopicsInTaxonomy(int taxonomy_version) { |
| CHECK_GT(taxonomy_version, 1); |
| CHECK_LE(taxonomy_version, SemanticTree::kMaxTaxonomyVersion); |
| if (GetTopicsForEachTaxonomyUpdate()[taxonomy_version - 2].empty()) { |
| // Include topics up to the maximum topic id for the `taxonomy_version`, |
| // and then remove the deleted topics. |
| uint16_t max_topic_id = |
| GetTaxonomyUpdates()[taxonomy_version - 2]->max_topic_id; |
| base::flat_set<Topic> topics; |
| for (uint16_t i = 1; i <= max_topic_id; ++i) { |
| topics.emplace(i); |
| } |
| for (int taxonomy_version_i = 2; taxonomy_version_i <= taxonomy_version; |
| ++taxonomy_version_i) { |
| for (uint16_t i : |
| GetTaxonomyUpdates()[taxonomy_version - 2]->deleted_topics) { |
| topics.erase(Topic(i)); |
| } |
| } |
| CHECK_EQ(topics.size(), |
| GetTaxonomyUpdates()[taxonomy_version - 2]->taxonomy_size); |
| GetTopicsForEachTaxonomyUpdate()[taxonomy_version - 2] = |
| std::vector(topics.begin(), topics.end()); |
| } |
| return GetTopicsForEachTaxonomyUpdate()[taxonomy_version - 2]; |
| } |
| |
| RepresentativenessMap GetInternalRepresentativenessMap() { |
| return {{1, std::make_pair(12, 23)}, {57, std::make_pair(369, 373)}, |
| {86, std::make_pair(392, 99)}, {100, std::make_pair(396, 399)}, |
| {103, std::make_pair(104, 419)}, {126, std::make_pair(129, 140)}, |
| {149, std::make_pair(158, 164)}, {172, std::make_pair(173, 462)}, |
| {180, std::make_pair(465, 183)}, {196, std::make_pair(469, 201)}, |
| {207, std::make_pair(482, 519)}, {215, std::make_pair(528, 534)}, |
| {226, std::make_pair(537, 237)}, {239, std::make_pair(560, 242)}, |
| {243, std::make_pair(561, 245)}, {250, 253}, |
| {254, std::make_pair(562, 258)}, {263, std::make_pair(264, 267)}, |
| {272, std::make_pair(565, 571)}, {275, std::make_pair(276, 278)}, |
| {279, std::make_pair(281, 288)}, {289, std::make_pair(572, 293)}, |
| {299, std::make_pair(325, 611)}, {332, std::make_pair(340, 626)}}; |
| } |
| |
| const RepresentativenessMap& GetRepresentativenessMapForCurrentTaxonomy() { |
| int current_taxonomy = blink::features::kBrowsingTopicsTaxonomyVersion.Get(); |
| switch (current_taxonomy) { |
| case 1: |
| static const base::NoDestructor<RepresentativenessMap> |
| kRepresentativenessMapV1(GetInternalRepresentativenessMap()); |
| return *kRepresentativenessMapV1; |
| case 2: |
| static const base::NoDestructor<RepresentativenessMap> |
| kRepresentativenessMapV2([]() -> RepresentativenessMap { |
| RepresentativenessMap map; |
| base::ranges::copy_if( |
| GetInternalRepresentativenessMap(), |
| std::inserter(map, map.end()), [](const auto& topic_kv) { |
| return topic_kv.first != 275 && topic_kv.first != 279; |
| }); |
| return map; |
| }()); |
| return *kRepresentativenessMapV2; |
| default: |
| NOTREACHED(); |
| } |
| } |
| } // namespace |
| |
| SemanticTree::SemanticTree() = default; |
| SemanticTree::~SemanticTree() = default; |
| |
| Topic SemanticTree::GetRandomTopic(int taxonomy_version, |
| uint64_t random_topic_index_decision) { |
| CHECK(IsTaxonomySupported(taxonomy_version)); |
| if (taxonomy_version == 1) { |
| size_t random_topic_index = random_topic_index_decision % kInitialNumTopics; |
| return Topic(base::checked_cast<int>(random_topic_index + 1)); |
| } |
| auto topics = GetTopicsInTaxonomy(taxonomy_version); |
| size_t random_topic_index = random_topic_index_decision % topics.size(); |
| return topics[random_topic_index]; |
| } |
| |
| std::vector<Topic> SemanticTree::GetFirstLevelTopicsInCurrentTaxonomy() { |
| static const base::NoDestructor<std::vector<Topic>> kFirstLevelTopics( |
| GetFirstLevelTopicsInCurrentTaxonomyInternal()); |
| return *kFirstLevelTopics; |
| } |
| |
| std::vector<Topic> |
| SemanticTree::GetFirstLevelTopicsInCurrentTaxonomyInternal() { |
| std::set<int> current_topics = GetTopicsInCurrentTaxonomyInternal(); |
| std::vector<Topic> first_level_topics; |
| const int kTopicWithNoParent = 0; |
| for (uint16_t i = 0; i < std::size(kChildToFirstParent); i++) { |
| if (kChildToFirstParent[i] == kTopicWithNoParent && |
| current_topics.contains(i + 1)) { |
| first_level_topics.emplace_back(i + 1); |
| } |
| } |
| return first_level_topics; |
| } |
| |
| std::set<int> SemanticTree::GetTopicsInCurrentTaxonomyInternal() { |
| int current_taxonomy = blink::features::kBrowsingTopicsTaxonomyVersion.Get(); |
| std::vector<Topic> topics_in_current_taxonomy; |
| if (current_taxonomy == 1) { |
| for (size_t i = 1; i <= kInitialNumTopics; i++) { |
| topics_in_current_taxonomy.emplace_back(base::checked_cast<int>(i)); |
| } |
| } else { |
| topics_in_current_taxonomy = GetTopicsInTaxonomy(current_taxonomy); |
| } |
| |
| std::set<int> current_topics(std::begin(topics_in_current_taxonomy), |
| std::end(topics_in_current_taxonomy)); |
| |
| return current_topics; |
| } |
| |
| std::vector<Topic> SemanticTree::GetAtMostTwoRepresentativesInCurrentTaxonomy( |
| const Topic& topic) { |
| const RepresentativenessMap& map = |
| GetRepresentativenessMapForCurrentTaxonomy(); |
| |
| auto map_iterator = map.find(topic.value()); |
| if (map_iterator == map.end()) { |
| return {}; |
| } |
| auto value = map_iterator->second; |
| if (holds_alternative<int>(value)) { |
| auto representative = get<int>(value); |
| return {Topic(representative)}; |
| } else if (holds_alternative<std::pair<int, int>>(value)) { |
| auto [topic_1, topic_2] = get<std::pair<int, int>>(value); |
| return {Topic(topic_1), Topic(topic_2)}; |
| } else { |
| return {}; |
| } |
| } |
| |
| bool SemanticTree::IsTaxonomySupported(int taxonomy_version) { |
| return taxonomy_version > 0 && |
| taxonomy_version <= SemanticTree::kMaxTaxonomyVersion; |
| } |
| |
| std::vector<Topic> SemanticTree::GetDescendantTopics(const Topic& topic, |
| bool only_direct) { |
| if (!IsTopicValid(topic)) { |
| return {}; |
| } |
| |
| std::vector<Topic> ret; |
| for (size_t i = 0; i < kNumTopics; ++i) { |
| Topic cur_topic = Topic(i + 1); |
| if (IsAncestorTopic(cur_topic, topic, only_direct)) { |
| ret.push_back(cur_topic); |
| } |
| } |
| return ret; |
| } |
| |
| std::vector<Topic> SemanticTree::GetAncestorTopics(const Topic& topic) { |
| if (!IsTopicValid(topic)) { |
| return {}; |
| } |
| |
| std::vector<Topic> ancestor_topics = GetParentTopics(topic); |
| size_t unvisited_start_idx = 0; |
| |
| while (unvisited_start_idx < ancestor_topics.size()) { |
| for (Topic parent : GetParentTopics(ancestor_topics[unvisited_start_idx])) { |
| ancestor_topics.emplace_back(parent); |
| } |
| unvisited_start_idx++; |
| } |
| |
| // Remove duplicate topics; duplicates can occur when a topic has two or more |
| // parents which share part of a lineage. |
| sort(ancestor_topics.begin(), ancestor_topics.end()); |
| ancestor_topics.erase(unique(ancestor_topics.begin(), ancestor_topics.end()), |
| ancestor_topics.end()); |
| return ancestor_topics; |
| } |
| |
| std::optional<int> SemanticTree::GetLatestLocalizedNameMessageId( |
| const Topic& topic) { |
| return SemanticTree::GetLocalizedNameMessageId( |
| topic, blink::features::kBrowsingTopicsTaxonomyVersion.Get()); |
| } |
| |
| std::optional<int> SemanticTree::GetLocalizedNameMessageId( |
| const Topic& topic, |
| int taxonomy_version) { |
| if (!IsTopicValid(topic) || !IsTaxonomySupported(taxonomy_version)) { |
| return std::nullopt; |
| } |
| // Get the most recent name for a topic by iterating through the taxonomy |
| // updates backwards. |
| for (int taxonomy_version_i = taxonomy_version; taxonomy_version_i > 0; |
| --taxonomy_version_i) { |
| if (taxonomy_version_i == 1) { |
| return IDS_PRIVACY_SANDBOX_TOPICS_TAXONOMY_V1_TOPIC_ID_1 + |
| static_cast<int>(topic) - 1; |
| } |
| auto renamed_topics_iterator = |
| GetTaxonomyUpdates()[taxonomy_version_i - 2]->renamed_topics.find( |
| static_cast<int>(topic)); |
| if (renamed_topics_iterator != |
| GetTaxonomyUpdates()[taxonomy_version_i - 2]->renamed_topics.end()) { |
| return renamed_topics_iterator->second; |
| } |
| } |
| return std::nullopt; |
| } |
| |
| } // namespace browsing_topics |