| 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 "chrome/common/thumbnail_score.h" | 5 #include "components/history/core/common/thumbnail_score.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 | 9 |
| 10 using base::Time; | 10 using base::Time; |
| 11 using base::TimeDelta; | 11 using base::TimeDelta; |
| 12 | 12 |
| 13 const int64 ThumbnailScore::kUpdateThumbnailTimeDays = 1; | 13 const int64 ThumbnailScore::kUpdateThumbnailTimeDays = 1; |
| 14 const double ThumbnailScore::kThumbnailMaximumBoringness = 0.94; | 14 const double ThumbnailScore::kThumbnailMaximumBoringness = 0.94; |
| 15 const double ThumbnailScore::kThumbnailDegradePerHour = 0.01; | 15 const double ThumbnailScore::kThumbnailDegradePerHour = 0.01; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 41 | 41 |
| 42 ThumbnailScore::ThumbnailScore(double score, bool clipping, bool top) | 42 ThumbnailScore::ThumbnailScore(double score, bool clipping, bool top) |
| 43 : boring_score(score), | 43 : boring_score(score), |
| 44 good_clipping(clipping), | 44 good_clipping(clipping), |
| 45 at_top(top), | 45 at_top(top), |
| 46 load_completed(false), | 46 load_completed(false), |
| 47 time_at_snapshot(Time::Now()), | 47 time_at_snapshot(Time::Now()), |
| 48 redirect_hops_from_dest(0) { | 48 redirect_hops_from_dest(0) { |
| 49 } | 49 } |
| 50 | 50 |
| 51 ThumbnailScore::ThumbnailScore(double score, bool clipping, bool top, | 51 ThumbnailScore::ThumbnailScore(double score, |
| 52 bool clipping, |
| 53 bool top, |
| 52 const Time& time) | 54 const Time& time) |
| 53 : boring_score(score), | 55 : boring_score(score), |
| 54 good_clipping(clipping), | 56 good_clipping(clipping), |
| 55 at_top(top), | 57 at_top(top), |
| 56 load_completed(false), | 58 load_completed(false), |
| 57 time_at_snapshot(time), | 59 time_at_snapshot(time), |
| 58 redirect_hops_from_dest(0) { | 60 redirect_hops_from_dest(0) { |
| 59 } | 61 } |
| 60 | 62 |
| 61 ThumbnailScore::~ThumbnailScore() { | 63 ThumbnailScore::~ThumbnailScore() { |
| 62 } | 64 } |
| 63 | 65 |
| 64 bool ThumbnailScore::Equals(const ThumbnailScore& rhs) const { | 66 bool ThumbnailScore::Equals(const ThumbnailScore& rhs) const { |
| 65 return boring_score == rhs.boring_score && | 67 return boring_score == rhs.boring_score && |
| 66 good_clipping == rhs.good_clipping && | 68 good_clipping == rhs.good_clipping && at_top == rhs.at_top && |
| 67 at_top == rhs.at_top && | 69 time_at_snapshot == rhs.time_at_snapshot && |
| 68 time_at_snapshot == rhs.time_at_snapshot && | 70 redirect_hops_from_dest == rhs.redirect_hops_from_dest; |
| 69 redirect_hops_from_dest == rhs.redirect_hops_from_dest; | |
| 70 } | 71 } |
| 71 | 72 |
| 72 std::string ThumbnailScore::ToString() const { | 73 std::string ThumbnailScore::ToString() const { |
| 73 return base::StringPrintf( | 74 return base::StringPrintf( |
| 74 "boring_score: %f, at_top %d, good_clipping %d, " | 75 "boring_score: %f, at_top %d, good_clipping %d, " |
| 75 "load_completed: %d, " | 76 "load_completed: %d, " |
| 76 "time_at_snapshot: %f, redirect_hops_from_dest: %d", | 77 "time_at_snapshot: %f, redirect_hops_from_dest: %d", |
| 77 boring_score, | 78 boring_score, |
| 78 at_top, | 79 at_top, |
| 79 good_clipping, | 80 good_clipping, |
| 80 load_completed, | 81 load_completed, |
| 81 time_at_snapshot.ToDoubleT(), | 82 time_at_snapshot.ToDoubleT(), |
| 82 redirect_hops_from_dest); | 83 redirect_hops_from_dest); |
| 83 } | 84 } |
| 84 | 85 |
| 85 bool ShouldReplaceThumbnailWith(const ThumbnailScore& current, | 86 bool ShouldReplaceThumbnailWith(const ThumbnailScore& current, |
| 86 const ThumbnailScore& replacement) { | 87 const ThumbnailScore& replacement) { |
| 87 int current_type = GetThumbnailType(current); | 88 int current_type = GetThumbnailType(current); |
| 88 int replacement_type = GetThumbnailType(replacement); | 89 int replacement_type = GetThumbnailType(replacement); |
| 89 if (replacement_type < current_type) { | 90 if (replacement_type < current_type) { |
| 90 // If we have a better class of thumbnail, add it if it meets | 91 // If we have a better class of thumbnail, add it if it meets |
| 91 // certain minimum boringness. | 92 // certain minimum boringness. |
| 92 return replacement.boring_score < | 93 return replacement.boring_score < |
| 93 ThumbnailScore::kThumbnailMaximumBoringness; | 94 ThumbnailScore::kThumbnailMaximumBoringness; |
| 94 } else if (replacement_type == current_type) { | 95 } else if (replacement_type == current_type) { |
| 95 // It's much easier to do the scaling below when we're dealing with "higher | 96 // It's much easier to do the scaling below when we're dealing with "higher |
| 96 // is better." Then we can decrease the score by dividing by a fraction. | 97 // is better." Then we can decrease the score by dividing by a fraction. |
| 97 const double kThumbnailMinimumInterestingness = | 98 const double kThumbnailMinimumInterestingness = |
| 98 1.0 - ThumbnailScore::kThumbnailMaximumBoringness; | 99 1.0 - ThumbnailScore::kThumbnailMaximumBoringness; |
| 99 double current_interesting_score = 1.0 - current.boring_score; | 100 double current_interesting_score = 1.0 - current.boring_score; |
| 100 double replacement_interesting_score = 1.0 - replacement.boring_score; | 101 double replacement_interesting_score = 1.0 - replacement.boring_score; |
| 101 | 102 |
| 102 // Degrade the score of each thumbnail to account for how many redirects | 103 // Degrade the score of each thumbnail to account for how many redirects |
| 103 // they are away from the destination. 1/(x+1) gives a scaling factor of | 104 // they are away from the destination. 1/(x+1) gives a scaling factor of |
| 104 // one for x = 0, and asymptotically approaches 0 for larger values of x. | 105 // one for x = 0, and asymptotically approaches 0 for larger values of x. |
| 105 current_interesting_score *= | 106 current_interesting_score *= 1.0 / (current.redirect_hops_from_dest + 1); |
| 106 1.0 / (current.redirect_hops_from_dest + 1); | |
| 107 replacement_interesting_score *= | 107 replacement_interesting_score *= |
| 108 1.0 / (replacement.redirect_hops_from_dest + 1); | 108 1.0 / (replacement.redirect_hops_from_dest + 1); |
| 109 | 109 |
| 110 // Degrade the score and prefer the newer one based on how long apart the | 110 // Degrade the score and prefer the newer one based on how long apart the |
| 111 // two thumbnails were taken. This means we'll eventually replace an old | 111 // two thumbnails were taken. This means we'll eventually replace an old |
| 112 // good one with a new worse one assuming enough time has passed. | 112 // good one with a new worse one assuming enough time has passed. |
| 113 TimeDelta time_between_thumbnails = | 113 TimeDelta time_between_thumbnails = |
| 114 replacement.time_at_snapshot - current.time_at_snapshot; | 114 replacement.time_at_snapshot - current.time_at_snapshot; |
| 115 current_interesting_score -= time_between_thumbnails.InHours() * | 115 current_interesting_score -= time_between_thumbnails.InHours() * |
| 116 ThumbnailScore::kThumbnailDegradePerHour; | 116 ThumbnailScore::kThumbnailDegradePerHour; |
| 117 | 117 |
| 118 if (current_interesting_score < kThumbnailMinimumInterestingness) | 118 if (current_interesting_score < kThumbnailMinimumInterestingness) |
| 119 current_interesting_score = kThumbnailMinimumInterestingness; | 119 current_interesting_score = kThumbnailMinimumInterestingness; |
| 120 if (replacement_interesting_score > current_interesting_score) | 120 if (replacement_interesting_score > current_interesting_score) |
| 121 return true; | 121 return true; |
| 122 } | 122 } |
| 123 | 123 |
| 124 // If the current thumbnail doesn't meet basic boringness | 124 // If the current thumbnail doesn't meet basic boringness |
| 125 // requirements, but the replacement does, always replace the | 125 // requirements, but the replacement does, always replace the |
| 126 // current one even if we're using a worse thumbnail type. | 126 // current one even if we're using a worse thumbnail type. |
| 127 return current.boring_score >= ThumbnailScore::kThumbnailMaximumBoringness && | 127 return current.boring_score >= ThumbnailScore::kThumbnailMaximumBoringness && |
| 128 replacement.boring_score < ThumbnailScore::kThumbnailMaximumBoringness; | 128 replacement.boring_score < ThumbnailScore::kThumbnailMaximumBoringness; |
| 129 } | 129 } |
| 130 | 130 |
| 131 bool ThumbnailScore::ShouldConsiderUpdating() { | 131 bool ThumbnailScore::ShouldConsiderUpdating() { |
| 132 const TimeDelta time_elapsed = Time::Now() - time_at_snapshot; | 132 const TimeDelta time_elapsed = Time::Now() - time_at_snapshot; |
| 133 if (time_elapsed < TimeDelta::FromDays(kUpdateThumbnailTimeDays) && | 133 if (time_elapsed < TimeDelta::FromDays(kUpdateThumbnailTimeDays) && |
| 134 good_clipping && at_top && load_completed) { | 134 good_clipping && at_top && load_completed) { |
| 135 // The current thumbnail is new and has good properties. | 135 // The current thumbnail is new and has good properties. |
| 136 return false; | 136 return false; |
| 137 } | 137 } |
| 138 // The current thumbnail should be updated. | 138 // The current thumbnail should be updated. |
| 139 return true; | 139 return true; |
| 140 } | 140 } |
| OLD | NEW |