OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/history/core/browser/thumbnail_database.h" | 5 #include "components/history/core/browser/thumbnail_database.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <string> | 10 #include <string> |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
57 // favicons. There is a separate row for every size in a | 57 // favicons. There is a separate row for every size in a |
58 // multi resolution bitmap. The bitmap data is associated | 58 // multi resolution bitmap. The bitmap data is associated |
59 // to the favicon via the |icon_id| field which matches | 59 // to the favicon via the |icon_id| field which matches |
60 // the |id| field in the appropriate row in the |favicons| | 60 // the |id| field in the appropriate row in the |favicons| |
61 // table. | 61 // table. |
62 // | 62 // |
63 // id Unique ID. | 63 // id Unique ID. |
64 // icon_id The ID of the favicon that the bitmap is associated to. | 64 // icon_id The ID of the favicon that the bitmap is associated to. |
65 // last_updated The time at which this favicon was inserted into the | 65 // last_updated The time at which this favicon was inserted into the |
66 // table. This is used to determine if it needs to be | 66 // table. This is used to determine if it needs to be |
67 // redownloaded from the web. | 67 // redownloaded from the web. Value 0 denotes that the bitmap |
68 // has been explicitly expired. | |
68 // image_data PNG encoded data of the favicon. | 69 // image_data PNG encoded data of the favicon. |
69 // width Pixel width of |image_data|. | 70 // width Pixel width of |image_data|. |
70 // height Pixel height of |image_data|. | 71 // height Pixel height of |image_data|. |
71 // last_requested The time at which this bitmap was last requested. This is | 72 // last_requested The time at which this bitmap was last requested. This is |
72 // used to determine the priority with which the bitmap | 73 // only used for bitmaps of type ON_DEMAND, for clearing old |
73 // should be retained on cleanup. | 74 // entries. (On-demand bitmaps cannot get cleared along with |
75 // expired visits in history DB.) On-demand bitmaps are | |
76 // defined by last_requested>0 and thus this field should | |
77 // never get updated for bitmaps of type ON_VISIT. | |
74 | 78 |
75 namespace { | 79 namespace { |
76 | 80 |
81 const int kFaviconUpdateLastRequestedAfterDays = 14; | |
82 | |
77 // For this database, schema migrations are deprecated after two | 83 // For this database, schema migrations are deprecated after two |
78 // years. This means that the oldest non-deprecated version should be | 84 // years. This means that the oldest non-deprecated version should be |
79 // two years old or greater (thus the migrations to get there are | 85 // two years old or greater (thus the migrations to get there are |
80 // older). Databases containing deprecated versions will be cleared | 86 // older). Databases containing deprecated versions will be cleared |
81 // at startup. Since this database is a cache, losing old data is not | 87 // at startup. Since this database is a cache, losing old data is not |
82 // fatal (in fact, very old data may be expired immediately at startup | 88 // fatal (in fact, very old data may be expired immediately at startup |
83 // anyhow). | 89 // anyhow). |
84 | 90 |
85 // Version 8: 982ef2c1/r323176 by rogerm@chromium.org on 2015-03-31 | 91 // Version 8: 982ef2c1/r323176 by rogerm@chromium.org on 2015-03-31 |
86 // Version 7: 911a634d/r209424 by qsr@chromium.org on 2013-07-01 | 92 // Version 7: 911a634d/r209424 by qsr@chromium.org on 2013-07-01 |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
490 } | 496 } |
491 | 497 |
492 if (pixel_size) { | 498 if (pixel_size) { |
493 *pixel_size = gfx::Size(statement.ColumnInt(2), | 499 *pixel_size = gfx::Size(statement.ColumnInt(2), |
494 statement.ColumnInt(3)); | 500 statement.ColumnInt(3)); |
495 } | 501 } |
496 | 502 |
497 if (last_requested) | 503 if (last_requested) |
498 *last_requested = base::Time::FromInternalValue(statement.ColumnInt64(4)); | 504 *last_requested = base::Time::FromInternalValue(statement.ColumnInt64(4)); |
499 | 505 |
506 // Checking timestamps: last_requested is set only for bitmaps of type | |
507 // ON_DEMAND, last_updated timestamp is set only for bitmaps of type ON_VISIT. | |
508 DCHECK(!last_requested || !last_updated || *last_requested == base::Time() || | |
509 *last_updated == base::Time()) | |
510 << "the favicon " << bitmap_id << " does not have consistent timestamps"; | |
pkotwicz
2017/06/07 17:40:53
I am not a big fan of DCHECKs in general. The main
jkrcal
2017/06/09 16:38:38
Okay, removed (as this is not tested by unit-test,
| |
511 | |
500 return true; | 512 return true; |
501 } | 513 } |
502 | 514 |
503 FaviconBitmapID ThumbnailDatabase::AddFaviconBitmap( | 515 FaviconBitmapID ThumbnailDatabase::AddFaviconBitmap( |
504 favicon_base::FaviconID icon_id, | 516 favicon_base::FaviconID icon_id, |
505 const scoped_refptr<base::RefCountedMemory>& icon_data, | 517 const scoped_refptr<base::RefCountedMemory>& icon_data, |
518 FaviconBitmapType type, | |
506 base::Time time, | 519 base::Time time, |
507 const gfx::Size& pixel_size) { | 520 const gfx::Size& pixel_size) { |
508 DCHECK(icon_id); | 521 DCHECK(icon_id); |
509 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 522 |
510 "INSERT INTO favicon_bitmaps (icon_id, image_data, last_updated, width, " | 523 sql::Statement statement(db_.GetCachedStatement( |
511 "height) VALUES (?, ?, ?, ?, ?)")); | 524 SQL_FROM_HERE, |
525 type == ON_VISIT | |
526 // On-visit bitmaps: | |
527 // - keep track of last_updated: last write time is used for | |
528 // expiration; | |
529 // - always have last_requested==0: no need to keep track | |
530 // of last read time. | |
531 ? "INSERT INTO favicon_bitmaps (icon_id, image_data, last_updated, " | |
532 "width, height) VALUES (?, ?, ?, ?, ?)" | |
533 // On-demand bitmaps: | |
534 // - always have last_updated==0: last write time is not stored as | |
535 // they are always expired and thus ready to be replaced by | |
536 // ON_VISIT icons; | |
537 // - keep track of last_requested: last read time is used for cache | |
538 // eviction. | |
539 : "INSERT INTO favicon_bitmaps (icon_id, image_data, last_requested, " | |
540 "width, height) VALUES (?, ?, ?, ?, ?)")); | |
541 | |
pkotwicz
2017/06/07 17:40:53
Can you do this instead:
INSERT INTO favicon_bitm
jkrcal
2017/06/09 16:38:38
Ah, sure, much better.
| |
512 statement.BindInt64(0, icon_id); | 542 statement.BindInt64(0, icon_id); |
513 if (icon_data.get() && icon_data->size()) { | 543 if (icon_data.get() && icon_data->size()) { |
514 statement.BindBlob(1, icon_data->front(), | 544 statement.BindBlob(1, icon_data->front(), |
515 static_cast<int>(icon_data->size())); | 545 static_cast<int>(icon_data->size())); |
516 } else { | 546 } else { |
517 statement.BindNull(1); | 547 statement.BindNull(1); |
518 } | 548 } |
549 // Both versions of the statement have a timestamp at index 2. | |
519 statement.BindInt64(2, time.ToInternalValue()); | 550 statement.BindInt64(2, time.ToInternalValue()); |
520 statement.BindInt(3, pixel_size.width()); | 551 statement.BindInt(3, pixel_size.width()); |
521 statement.BindInt(4, pixel_size.height()); | 552 statement.BindInt(4, pixel_size.height()); |
522 | 553 |
523 if (!statement.Run()) | 554 if (!statement.Run()) |
524 return 0; | 555 return 0; |
525 return db_.GetLastInsertRowId(); | 556 return db_.GetLastInsertRowId(); |
526 } | 557 } |
527 | 558 |
528 bool ThumbnailDatabase::SetFaviconBitmap( | 559 bool ThumbnailDatabase::SetFaviconBitmap( |
529 FaviconBitmapID bitmap_id, | 560 FaviconBitmapID bitmap_id, |
530 scoped_refptr<base::RefCountedMemory> bitmap_data, | 561 scoped_refptr<base::RefCountedMemory> bitmap_data, |
531 base::Time time) { | 562 base::Time time) { |
532 DCHECK(bitmap_id); | 563 DCHECK(bitmap_id); |
533 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 564 // By updating last_updated timestamp, we assume the icon is of type ON_VISIT. |
534 "UPDATE favicon_bitmaps SET image_data=?, last_updated=? WHERE id=?")); | 565 // If it is ON_DEMAND, reset last_requested to 0 and thus silently change the |
566 // type to ON_VISIT. | |
567 sql::Statement statement( | |
568 db_.GetCachedStatement(SQL_FROM_HERE, | |
569 "UPDATE favicon_bitmaps SET image_data=?, " | |
570 "last_updated=?, last_requested=? WHERE id=?")); | |
535 if (bitmap_data.get() && bitmap_data->size()) { | 571 if (bitmap_data.get() && bitmap_data->size()) { |
536 statement.BindBlob(0, bitmap_data->front(), | 572 statement.BindBlob(0, bitmap_data->front(), |
537 static_cast<int>(bitmap_data->size())); | 573 static_cast<int>(bitmap_data->size())); |
538 } else { | 574 } else { |
539 statement.BindNull(0); | 575 statement.BindNull(0); |
540 } | 576 } |
541 statement.BindInt64(1, time.ToInternalValue()); | 577 statement.BindInt64(1, time.ToInternalValue()); |
542 statement.BindInt64(2, bitmap_id); | 578 statement.BindInt64(2, 0); |
579 statement.BindInt64(3, bitmap_id); | |
543 | 580 |
544 return statement.Run(); | 581 return statement.Run(); |
545 } | 582 } |
546 | 583 |
547 bool ThumbnailDatabase::SetFaviconBitmapLastUpdateTime( | 584 bool ThumbnailDatabase::SetFaviconBitmapLastUpdateTime( |
548 FaviconBitmapID bitmap_id, | 585 FaviconBitmapID bitmap_id, |
549 base::Time time) { | 586 base::Time time) { |
550 DCHECK(bitmap_id); | 587 DCHECK(bitmap_id); |
551 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 588 // By updating last_updated timestamp, we assume the icon is of type ON_VISIT. |
552 "UPDATE favicon_bitmaps SET last_updated=? WHERE id=?")); | 589 // If it is ON_DEMAND, reset last_requested to 0 and thus silently change the |
590 // type to ON_VISIT. | |
591 sql::Statement statement( | |
592 db_.GetCachedStatement(SQL_FROM_HERE, | |
593 "UPDATE favicon_bitmaps SET last_updated=?, " | |
594 "last_requested=? WHERE id=?")); | |
553 statement.BindInt64(0, time.ToInternalValue()); | 595 statement.BindInt64(0, time.ToInternalValue()); |
554 statement.BindInt64(1, bitmap_id); | 596 statement.BindInt64(1, 0); |
597 statement.BindInt64(2, bitmap_id); | |
555 return statement.Run(); | 598 return statement.Run(); |
556 } | 599 } |
557 | 600 |
558 bool ThumbnailDatabase::SetFaviconBitmapLastRequestedTime( | 601 bool ThumbnailDatabase::TouchOnDemandFavicon(const GURL& icon_url, |
559 FaviconBitmapID bitmap_id, | 602 base::Time time) { |
560 base::Time time) { | 603 // Look up the id of the icon. |
561 DCHECK(bitmap_id); | 604 sql::Statement id_statement(db_.GetCachedStatement( |
562 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 605 SQL_FROM_HERE, "SELECT id FROM favicons WHERE url=?")); |
pkotwicz
2017/06/07 17:40:53
Isn't it theoretically possible to have multiple e
jkrcal
2017/06/09 16:38:38
Done.
| |
563 "UPDATE favicon_bitmaps SET last_requested=? WHERE id=?")); | 606 id_statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url)); |
607 if (!id_statement.Step()) | |
608 return false; // not cached | |
609 favicon_base::FaviconID icon_id = id_statement.ColumnInt64(0); | |
610 | |
611 // Update the time only for ON_DEMAND bitmaps (i.e. with last_requested > 0). | |
612 sql::Statement statement(db_.GetCachedStatement( | |
613 SQL_FROM_HERE, | |
614 "UPDATE favicon_bitmaps SET last_requested=? WHERE icon_id=? AND " | |
615 "last_requested>0 AND last_requested<=?")); | |
564 statement.BindInt64(0, time.ToInternalValue()); | 616 statement.BindInt64(0, time.ToInternalValue()); |
565 statement.BindInt64(1, bitmap_id); | 617 statement.BindInt64(1, icon_id); |
618 // For performance reasons update the time only if the currently stored time | |
619 // is old enough (UPDATEs where the WHERE condition does not match any entries | |
620 // are way faster than UPDATEs that really change some data). | |
pkotwicz
2017/06/07 17:40:53
Nit: Merge this comment with the comment on line 6
jkrcal
2017/06/09 16:38:38
Done.
| |
621 base::Time max_time = | |
622 time - base::TimeDelta::FromDays(kFaviconUpdateLastRequestedAfterDays); | |
623 statement.BindInt64(2, max_time.ToInternalValue()); | |
566 return statement.Run(); | 624 return statement.Run(); |
567 } | 625 } |
568 | 626 |
569 bool ThumbnailDatabase::DeleteFaviconBitmap(FaviconBitmapID bitmap_id) { | 627 bool ThumbnailDatabase::DeleteFaviconBitmap(FaviconBitmapID bitmap_id) { |
570 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, | 628 sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, |
571 "DELETE FROM favicon_bitmaps WHERE id=?")); | 629 "DELETE FROM favicon_bitmaps WHERE id=?")); |
572 statement.BindInt64(0, bitmap_id); | 630 statement.BindInt64(0, bitmap_id); |
573 return statement.Run(); | 631 return statement.Run(); |
574 } | 632 } |
575 | 633 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 return db_.GetLastInsertRowId(); | 688 return db_.GetLastInsertRowId(); |
631 } | 689 } |
632 | 690 |
633 favicon_base::FaviconID ThumbnailDatabase::AddFavicon( | 691 favicon_base::FaviconID ThumbnailDatabase::AddFavicon( |
634 const GURL& icon_url, | 692 const GURL& icon_url, |
635 favicon_base::IconType icon_type, | 693 favicon_base::IconType icon_type, |
636 const scoped_refptr<base::RefCountedMemory>& icon_data, | 694 const scoped_refptr<base::RefCountedMemory>& icon_data, |
637 base::Time time, | 695 base::Time time, |
638 const gfx::Size& pixel_size) { | 696 const gfx::Size& pixel_size) { |
639 favicon_base::FaviconID icon_id = AddFavicon(icon_url, icon_type); | 697 favicon_base::FaviconID icon_id = AddFavicon(icon_url, icon_type); |
640 if (!icon_id || !AddFaviconBitmap(icon_id, icon_data, time, pixel_size)) | 698 if (!icon_id || |
699 !AddFaviconBitmap(icon_id, icon_data, FaviconBitmapType::ON_VISIT, time, | |
700 pixel_size)) | |
641 return 0; | 701 return 0; |
642 | 702 |
643 return icon_id; | 703 return icon_id; |
644 } | 704 } |
645 | 705 |
646 bool ThumbnailDatabase::DeleteFavicon(favicon_base::FaviconID id) { | 706 bool ThumbnailDatabase::DeleteFavicon(favicon_base::FaviconID id) { |
647 sql::Statement statement; | 707 sql::Statement statement; |
648 statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE, | 708 statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE, |
649 "DELETE FROM favicons WHERE id = ?")); | 709 "DELETE FROM favicons WHERE id = ?")); |
650 statement.BindInt64(0, id); | 710 statement.BindInt64(0, id); |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1058 meta_table_.SetVersionNumber(8); | 1118 meta_table_.SetVersionNumber(8); |
1059 meta_table_.SetCompatibleVersionNumber(std::min(8, kCompatibleVersionNumber)); | 1119 meta_table_.SetCompatibleVersionNumber(std::min(8, kCompatibleVersionNumber)); |
1060 return true; | 1120 return true; |
1061 } | 1121 } |
1062 | 1122 |
1063 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { | 1123 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { |
1064 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); | 1124 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); |
1065 } | 1125 } |
1066 | 1126 |
1067 } // namespace history | 1127 } // namespace history |
OLD | NEW |