File: commerce_ui_tab_helper.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (293 lines) | stat: -rw-r--r-- 11,711 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_COMMERCE_COMMERCE_UI_TAB_HELPER_H_
#define CHROME_BROWSER_UI_COMMERCE_COMMERCE_UI_TAB_HELPER_H_

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/ui/commerce/price_tracking_page_action_controller.h"
#include "chrome/browser/ui/page_action/page_action_icon_type.h"
#include "chrome/browser/ui/tabs/contents_observing_tab_feature.h"
#include "components/commerce/core/shopping_service.h"
#include "components/prefs/pref_registry_simple.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/image/image.h"

// TODO(https://crbug.com/362675963): Once //c/b/ui/views/commerce/ gets
// modularized, the declaration of enum class PriceInsightsIconLabelType can
// move back into class PriceInsightsIconView, and we can include
// //c/b/ui/views/commerce/price_insights_icon_view.h directly, without
// circular dependencies.
enum class PriceInsightsIconLabelType;

class GURL;
class SidePanelEntryScope;
class SidePanelRegistry;
class SidePanelUI;
namespace bookmarks {
class BookmarkModel;
}

namespace content {
class NavigationHandle;
}  // namespace content

namespace tabs {
class TabInterface;
}

namespace image_fetcher {
class ImageFetcher;
}

namespace views {
class View;
}  // namespace views

namespace commerce {

class DiscountsPageActionController;
class ProductSpecificationsPageActionController;

// This tab helper is used to update and maintain the state of UI for commerce
// features.
class CommerceUiTabHelper : public tabs::ContentsObservingTabFeature {
 public:
  CommerceUiTabHelper(tabs::TabInterface& tab_interface,
                      ShoppingService* shopping_service,
                      bookmarks::BookmarkModel* model,
                      image_fetcher::ImageFetcher* image_fetcher,
                      SidePanelRegistry* side_panel_registry);
  ~CommerceUiTabHelper() override;
  CommerceUiTabHelper(const CommerceUiTabHelper& other) = delete;
  CommerceUiTabHelper& operator=(const CommerceUiTabHelper& other) = delete;

  static void RegisterProfilePrefs(PrefRegistrySimple* registry);

  // Get the image for the last fetched product URL. A reference to this object
  // should not be kept directly, if one is needed, a copy should be made.
  virtual const gfx::Image& GetProductImage();
  // Return whether the DiscountsPageActionIconView is visible.
  virtual bool ShouldShowDiscountsIconView();
  // Return whether the PriceTrackingIconView is visible.
  virtual bool ShouldShowPriceTrackingIconView();
  // Return whether the PriceInsightsIconView is visible.
  virtual bool ShouldShowPriceInsightsIconView();
  // Return whether the ProductSpecificationsIconView is visible.
  virtual bool ShouldShowProductSpecificationsIconView();

  // Return the page action label. If no label should be shown, return
  // PriceInsightsIconLabelType::kNone.
  virtual PriceInsightsIconLabelType GetPriceInsightsIconLabelTypeForPage();

  // The URL for the last fetched product image. A reference to this object
  // should not be kept directly, if one is needed, a copy should be made.
  const GURL& GetProductImageURL();

  // Returns whether the current page has a product that is being price tracked.
  virtual bool IsPriceTracking();

  // Returns whether the product in the current page is in the recommended
  // product specifications set.
  virtual bool IsInRecommendedSet();

  // A notification that the open button in the added to compare set toast is
  // clicked. This method will open the compare page in a new tab if the compare
  // page is not already open in the current window, otherwise it will switch to
  // that compare page tab.
  virtual void OnOpenComparePageClicked();

  // Returns the name of the comparison set.
  virtual std::u16string GetComparisonSetName();

  // Returns the label to show on the product specifications icon.
  virtual std::u16string GetProductSpecificationsLabel(bool is_added);

  // Returns discounts for the last committed URL. A reference to this object
  // should not be kept directly, if one is needed, a copy should be made.
  virtual const std::vector<DiscountInfo>& GetDiscounts();

  // content::WebContentsObserver implementation
  void DidFinishNavigation(
      content::NavigationHandle* navigation_handle) override;
  void WebContentsDestroyed() override;

  // Update this tab helper to use the specified image fetcher in tests.
  void SetImageFetcherForTesting(image_fetcher::ImageFetcher* image_fetcher);

  // Set the price tracking state for the product on the current page.
  virtual void SetPriceTrackingState(bool enable,
                                     bool is_new_bookmark,
                                     base::OnceCallback<void(bool)> callback);
  void OnPriceInsightsIconClicked();
  virtual void OnProductSpecificationsIconClicked();

  // Return the PriceInsightsInfo for the last fetched product URL. A reference
  // to this object should not be kept directly, if one is needed, a copy should
  // be made.
  virtual const std::optional<PriceInsightsInfo>& GetPriceInsightsInfo();

  // Gets whether the page action with the provided |type| should expand. This
  // method will change the internal state of this class if the ID provided
  // matches the icon that should expand -- the "true" response is only valid
  // once per page load to avoid having the icon expand multiple times.
  virtual bool ShouldExpandPageActionIcon(PageActionIconType type);
  // Return whether the page action with provided |type| has been expanded.
  bool IsPageActionIconExpanded(PageActionIconType type);

  // A notification that the price tracking icon was clicked.
  void OnPriceTrackingIconClicked();

  // TODO(b/355566609): Expose the DiscountsPageActionController getter instead
  // of the discount related methods below.
  //  A notification that the coupon code in the Discounts bubble is copied.
  void OnDiscountsCouponCodeCopied();
  // Return whether the coupon code is copied. This will reset the copied
  // status.
  virtual bool IsDiscountsCouponCodeCopied();
  // Return whether the Discounts bubble should show automatically for the given
  // |discount_id|.
  virtual bool ShouldAutoShowDiscountsBubble(uint64_t discount_id,
                                             bool is_merchant_wide);
  void DiscountsBubbleShown(uint64_t discount_id);

  PriceTrackingPageActionController* GetPriceTrackingControllerForTesting();

  void SetPriceTrackingControllerForTesting(
      std::unique_ptr<PriceTrackingPageActionController> controller);

 protected:
  const std::optional<bool>& GetPendingTrackingStateForTesting();

  virtual std::unique_ptr<views::View> CreateShoppingInsightsWebView(
      SidePanelEntryScope& scope);

  virtual GURL GetComparisonTableURL();

 private:
  friend class CommerceUiTabHelperTest;

  void UpdateUiForShoppingServiceReady(ShoppingService* service);

  void HandleProductInfoResponse(const GURL& url,
                                 const std::optional<const ProductInfo>& info);

  void HandlePriceInsightsInfoResponse(
      const GURL& url,
      const std::optional<PriceInsightsInfo>& info);

  void UpdateDiscountsIconView();

  void UpdatePriceTrackingIconView();

  void UpdatePriceInsightsIconView();

  void UpdateProductSpecificationsIconView();

  void TriggerUpdateForIconView();

  bool ShouldIgnoreSameUrlNavigation();

  bool IsSameDocumentWithSameCommittedUrl(
      content::NavigationHandle* navigation_handle);

  // Make the ShoppingInsights entry available in the side panel.
  void MakeShoppingInsightsSidePanelAvailable();

  // Make the ShoppingInsights entry unavailable in the side panel. If the
  // ShoppingInsights side panel is currently showing, close the side panel
  // first.
  void MakeShoppingInsightsSidePanelUnavailable();

  SidePanelUI* GetSidePanelUI();

  void MaybeComputePageActionToExpand();

  void ComputePageActionToExpand();

  void RecordIconMetrics(PageActionIconType page_action, bool from_icon_use);

  void RecordPriceInsightsIconMetrics(bool from_icon_use);

  void MaybeRecordShoppingInformationUKM(
      std::optional<PageActionIconType> page_action_type);

  void OnPageActionControllerNotification(
      base::RepeatingClosure page_action_icon_update_callback);

  base::RepeatingClosure GetPageActionControllerNotificationCallback(
      base::RepeatingClosure page_action_icon_update_callback);

  // This helper is for the legacy page actions. It will be removed after the
  // migration to the new framework.
  void UpdatePageActionIconView(PageActionIconType type);

  // The shopping service is tied to the lifetime of the browser context
  // which will always outlive this tab helper.
  raw_ptr<ShoppingService, DanglingUntriaged> shopping_service_;
  raw_ptr<bookmarks::BookmarkModel> bookmark_model_;
  raw_ptr<image_fetcher::ImageFetcher> image_fetcher_;
  raw_ptr<SidePanelRegistry> side_panel_registry_;

  std::unique_ptr<PriceTrackingPageActionController> price_tracking_controller_;
  std::unique_ptr<ProductSpecificationsPageActionController>
      product_specifications_controller_;
  std::unique_ptr<DiscountsPageActionController>
      discounts_page_action_controller_;

  // The product info available for the current page if available.
  std::optional<ProductInfo> product_info_for_page_;

  // Whether the chip that should expand for the current page has been computed.
  bool is_page_action_expansion_computed_for_page_{false};

  // Whether we have received responses for the various commerce features for
  // the current page load.
  bool got_discounts_response_for_page_{false};
  bool got_insights_response_for_page_{false};
  bool page_has_discounts_{false};

  // Page action icon uses that have already been recorded for the current page.
  // For Price Tracking, this will only record "track" events.
  std::set<PageActionIconType> icon_use_recorded_for_page_;

  // A flag indicating whether the initial navigation has committed for the web
  // contents. This is used to ensure product info is fetched when a tab is
  // being restored.
  bool is_initial_navigation_committed_{false};

  // This represents the desired state of the tracking icon prior to getting the
  // callback from the (un)subscribe event. If no value, there is no pending
  // state, otherwise true means "tracking" and false means "not tracking".
  std::optional<bool> pending_tracking_state_;

  // The url from the previous successful main frame navigation. This will be
  // empty if this is the first navigation for this tab or post-restart.
  GURL previous_main_frame_url_;

  // The PriceInsightsInfo associated with the last committed URL.
  std::optional<PriceInsightsInfo> price_insights_info_;

  // The page action that should expand for the current page. This optional will
  // be reset once the value is read by the UI.
  std::optional<PageActionIconType> page_action_to_expand_;

  // The page action that was expanded for the current page load, if any. This
  // indicates that |page_action_to_expand_| was read by the UI and lets us keep
  // track of which page action actually expanded.
  std::optional<PageActionIconType> page_action_expanded_;

  base::TimeTicks page_action_icon_compute_start_time_;

  // The price insights icon label type for the current page load.
  PriceInsightsIconLabelType price_insights_label_type_;

  base::WeakPtrFactory<CommerceUiTabHelper> weak_ptr_factory_{this};
};

}  // namespace commerce

#endif  // CHROME_BROWSER_UI_COMMERCE_COMMERCE_UI_TAB_HELPER_H_