Removing flow to demote App Launcher to App Host, so app_host.exe can be deleted...
[chromium-blink-merge.git] / chrome / common / thumbnail_score.cc
blobe2f41a0feb36b28243208c2b50c71a98efcd4fb8
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
3 // found in the LICENSE file.
5 #include "chrome/common/thumbnail_score.h"
7 #include "base/logging.h"
8 #include "base/stringprintf.h"
10 using base::Time;
11 using base::TimeDelta;
13 const int64 ThumbnailScore::kUpdateThumbnailTimeDays = 1;
14 const double ThumbnailScore::kThumbnailMaximumBoringness = 0.94;
15 const double ThumbnailScore::kThumbnailDegradePerHour = 0.01;
16 const double ThumbnailScore::kTooWideAspectRatio = 2.0;
18 // Calculates a numeric score from traits about where a snapshot was
19 // taken. The lower the better. We store the raw components in the
20 // database because I'm sure this will evolve and I don't want to break
21 // databases.
22 static int GetThumbnailType(const ThumbnailScore& score) {
23 int type = 0;
24 if (!score.at_top)
25 type += 1;
26 if (!score.good_clipping)
27 type += 2;
28 if (!score.load_completed)
29 type += 3;
30 return type;
33 ThumbnailScore::ThumbnailScore()
34 : boring_score(1.0),
35 good_clipping(false),
36 at_top(false),
37 load_completed(false),
38 time_at_snapshot(Time::Now()),
39 redirect_hops_from_dest(0) {
42 ThumbnailScore::ThumbnailScore(double score, bool clipping, bool top)
43 : boring_score(score),
44 good_clipping(clipping),
45 at_top(top),
46 load_completed(false),
47 time_at_snapshot(Time::Now()),
48 redirect_hops_from_dest(0) {
51 ThumbnailScore::ThumbnailScore(double score, bool clipping, bool top,
52 const Time& time)
53 : boring_score(score),
54 good_clipping(clipping),
55 at_top(top),
56 load_completed(false),
57 time_at_snapshot(time),
58 redirect_hops_from_dest(0) {
61 ThumbnailScore::~ThumbnailScore() {
64 bool ThumbnailScore::Equals(const ThumbnailScore& rhs) const {
65 return boring_score == rhs.boring_score &&
66 good_clipping == rhs.good_clipping &&
67 at_top == rhs.at_top &&
68 time_at_snapshot == rhs.time_at_snapshot &&
69 redirect_hops_from_dest == rhs.redirect_hops_from_dest;
72 std::string ThumbnailScore::ToString() const {
73 return StringPrintf("boring_score: %f, at_top %d, good_clipping %d, "
74 "load_completed: %d, "
75 "time_at_snapshot: %f, redirect_hops_from_dest: %d",
76 boring_score,
77 at_top,
78 good_clipping,
79 load_completed,
80 time_at_snapshot.ToDoubleT(),
81 redirect_hops_from_dest);
84 bool ShouldReplaceThumbnailWith(const ThumbnailScore& current,
85 const ThumbnailScore& replacement) {
86 int current_type = GetThumbnailType(current);
87 int replacement_type = GetThumbnailType(replacement);
88 if (replacement_type < current_type) {
89 // If we have a better class of thumbnail, add it if it meets
90 // certain minimum boringness.
91 return replacement.boring_score <
92 ThumbnailScore::kThumbnailMaximumBoringness;
93 } else if (replacement_type == current_type) {
94 // It's much easier to do the scaling below when we're dealing with "higher
95 // is better." Then we can decrease the score by dividing by a fraction.
96 const double kThumbnailMinimumInterestingness =
97 1.0 - ThumbnailScore::kThumbnailMaximumBoringness;
98 double current_interesting_score = 1.0 - current.boring_score;
99 double replacement_interesting_score = 1.0 - replacement.boring_score;
101 // Degrade the score of each thumbnail to account for how many redirects
102 // they are away from the destination. 1/(x+1) gives a scaling factor of
103 // one for x = 0, and asymptotically approaches 0 for larger values of x.
104 current_interesting_score *=
105 1.0 / (current.redirect_hops_from_dest + 1);
106 replacement_interesting_score *=
107 1.0 / (replacement.redirect_hops_from_dest + 1);
109 // Degrade the score and prefer the newer one based on how long apart the
110 // two thumbnails were taken. This means we'll eventually replace an old
111 // good one with a new worse one assuming enough time has passed.
112 TimeDelta time_between_thumbnails =
113 replacement.time_at_snapshot - current.time_at_snapshot;
114 current_interesting_score -= time_between_thumbnails.InHours() *
115 ThumbnailScore::kThumbnailDegradePerHour;
117 if (current_interesting_score < kThumbnailMinimumInterestingness)
118 current_interesting_score = kThumbnailMinimumInterestingness;
119 if (replacement_interesting_score > current_interesting_score)
120 return true;
123 // If the current thumbnail doesn't meet basic boringness
124 // requirements, but the replacement does, always replace the
125 // current one even if we're using a worse thumbnail type.
126 return current.boring_score >= ThumbnailScore::kThumbnailMaximumBoringness &&
127 replacement.boring_score < ThumbnailScore::kThumbnailMaximumBoringness;
130 bool ThumbnailScore::ShouldConsiderUpdating() {
131 const TimeDelta time_elapsed = Time::Now() - time_at_snapshot;
132 if (time_elapsed < TimeDelta::FromDays(kUpdateThumbnailTimeDays) &&
133 good_clipping && at_top && load_completed) {
134 // The current thumbnail is new and has good properties.
135 return false;
137 // The current thumbnail should be updated.
138 return true;