Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: ios/chrome/browser/ui/reader_mode/reader_mode_checker.mm

Issue 2589583003: Upstream Chrome on iOS source code [7/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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
5 #import "ios/chrome/browser/ui/reader_mode/reader_mode_checker.h"
6
7 #include "base/logging.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "components/dom_distiller/core/distillable_page_detector.h"
10 #include "components/dom_distiller/core/experiments.h"
11 #include "components/dom_distiller/core/page_features.h"
12 #include "components/dom_distiller/core/url_utils.h"
13 #include "components/grit/components_resources.h"
14 #include "ios/web/public/web_state/js/crw_js_injection_evaluator.h"
15 #include "ios/web/public/web_state/web_state.h"
16 #include "ui/base/resource/resource_bundle.h"
17
18 ReaderModeCheckerObserver::ReaderModeCheckerObserver(
19 ReaderModeChecker* readerModeChecker)
20 : readerModeChecker_(readerModeChecker) {
21 DCHECK(readerModeChecker);
22 readerModeChecker_->AddObserver(this);
23 }
24
25 ReaderModeCheckerObserver::~ReaderModeCheckerObserver() {
26 readerModeChecker_->RemoveObserver(this);
27 }
28
29 enum class ReaderModeChecker::Status {
30 kSwitchNo, // There is no way a switch could happen.
31 kSwitchMaybe, // Not sure, it may be possible.
32 kSwitchPossible, // It is possible to switch to reader mode.
33 };
34
35 ReaderModeChecker::ReaderModeChecker(web::WebState* web_state)
36 : web::WebStateObserver(web_state),
37 is_distillable_(Status::kSwitchNo),
38 weak_factory_(this) {
39 DCHECK(web_state);
40 }
41
42 ReaderModeChecker::~ReaderModeChecker() {
43 for (auto& observer : observers_)
44 observer.ReaderModeCheckerDestroyed();
45 }
46
47 bool ReaderModeChecker::CanSwitchToReaderMode() {
48 return is_distillable_ != ReaderModeChecker::Status::kSwitchNo;
49 }
50
51 void ReaderModeChecker::PageLoaded(
52 web::PageLoadCompletionStatus load_completion_status) {
53 if (load_completion_status != web::PageLoadCompletionStatus::SUCCESS)
54 return;
55
56 if (is_distillable_ == Status::kSwitchPossible)
57 return;
58
59 CheckIsDistillable();
60 }
61
62 void ReaderModeChecker::NavigationItemCommitted(
63 const web::LoadCommittedDetails& load_details) {
64 // When NavigationItemCommitted the page may not be completely loaded. But in
65 // order to get reader mode data faster this class tries to inject the
66 // javascript early. If it fails, it will be retried at PageLoaded().
67 is_distillable_ = Status::kSwitchNo;
68 CheckIsDistillable();
69 }
70
71 void ReaderModeChecker::CheckIsDistillableOG(CRWJSInjectionReceiver* receiver) {
72 // Retrieve the javascript used to figure out if the page is at all
73 // distillable.
74 NSString* is_distillable_js =
75 base::SysUTF8ToNSString(dom_distiller::url_utils::GetIsDistillableJs());
76 DCHECK(is_distillable_js);
77
78 // In case |this| gets deallocated before the block executes, the block only
79 // references a weak pointer.
80 base::WeakPtr<ReaderModeChecker> weak_this(weak_factory_.GetWeakPtr());
81 [receiver executeJavaScript:is_distillable_js
82 completionHandler:^(id result, NSError* error) {
83 if (!weak_this || error || !result)
84 return; // Inconclusive.
85 if ([result isEqual:@YES]) {
86 weak_this->is_distillable_ = Status::kSwitchPossible;
87 for (auto& observer : weak_this->observers_)
88 observer.PageIsDistillable();
89 } else {
90 weak_this->is_distillable_ = Status::kSwitchMaybe;
91 }
92 }];
93 }
94
95 void ReaderModeChecker::CheckIsDistillableDetector(
96 CRWJSInjectionReceiver* receiver) {
97 // Retrieve the javascript used to figure out if the page is at all
98 // distillable.
99 NSString* extract_features_js = base::SysUTF8ToNSString(
100 ResourceBundle::GetSharedInstance()
101 .GetRawDataResource(IDR_EXTRACT_PAGE_FEATURES_JS)
102 .as_string());
103 DCHECK(extract_features_js);
104
105 // In case |this| gets deallocated before the block executes, the block only
106 // references a weak pointer.
107 base::WeakPtr<ReaderModeChecker> weak_this(weak_factory_.GetWeakPtr());
108 [receiver
109 executeJavaScript:extract_features_js
110 completionHandler:^(id result, NSError* error) {
111 if (!weak_this || error || ![result isKindOfClass:[NSString class]]) {
112 return; // Inconclusive.
113 }
114 const dom_distiller::DistillablePageDetector* detector =
115 dom_distiller::DistillablePageDetector::GetDefault();
116 const base::StringValue value(base::SysNSStringToUTF8(result));
117 std::vector<double> features(
118 dom_distiller::CalculateDerivedFeaturesFromJSON(&value));
119 if (detector->Classify(features)) {
120 weak_this->is_distillable_ = Status::kSwitchPossible;
121 for (auto& observer : weak_this->observers_)
122 observer.PageIsDistillable();
123 } else {
124 weak_this->is_distillable_ = Status::kSwitchMaybe;
125 }
126 }];
127 }
128
129 void ReaderModeChecker::CheckIsDistillable() {
130 CRWJSInjectionReceiver* receiver = web_state()->GetJSInjectionReceiver();
131
132 if (!receiver || !web_state()->ContentIsHTML() ||
133 web_state()->IsShowingWebInterstitial()) {
134 is_distillable_ = Status::kSwitchNo;
135 return;
136 }
137
138 switch (dom_distiller::GetDistillerHeuristicsType()) {
139 case dom_distiller::DistillerHeuristicsType::NONE:
140 is_distillable_ = Status::kSwitchMaybe;
141 break;
142 case dom_distiller::DistillerHeuristicsType::OG_ARTICLE:
143 CheckIsDistillableOG(receiver);
144 break;
145 case dom_distiller::DistillerHeuristicsType::ADABOOST_MODEL:
146 CheckIsDistillableDetector(receiver);
147 break;
148 case dom_distiller::DistillerHeuristicsType::ALWAYS_TRUE:
149 is_distillable_ = Status::kSwitchPossible;
150 break;
151 }
152 }
153
154 void ReaderModeChecker::WebStateDestroyed() {
155 is_distillable_ = Status::kSwitchNo;
156 }
157
158 void ReaderModeChecker::AddObserver(ReaderModeCheckerObserver* observer) {
159 DCHECK(!observers_.HasObserver(observer));
160 observers_.AddObserver(observer);
161 }
162
163 void ReaderModeChecker::RemoveObserver(ReaderModeCheckerObserver* observer) {
164 DCHECK(observers_.HasObserver(observer));
165 observers_.RemoveObserver(observer);
166 }
OLDNEW
« no previous file with comments | « ios/chrome/browser/ui/reader_mode/reader_mode_checker.h ('k') | ios/chrome/browser/ui/reader_mode/reader_mode_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698