chromium/ios/chrome/browser/crash_report/model/crash_reporter_url_observer.h

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef IOS_CHROME_BROWSER_CRASH_REPORT_MODEL_CRASH_REPORTER_URL_OBSERVER_H_
#define IOS_CHROME_BROWSER_CRASH_REPORT_MODEL_CRASH_REPORTER_URL_OBSERVER_H_

#import <Foundation/Foundation.h>

#include <map>
#include <string>

#include "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer.h"
#include "ios/web/public/web_state_observer.h"
#include "url/gurl.h"

namespace web {
class NavigationContext;
class WebState;
}  // namespace web
class AllWebStateObservationForwarder;

// Provides method to set and remove parameter values.
@protocol CrashReporterParameterSetter
// Sets a parameter named `key||pending` with value `value`.
- (void)setReportParameterURL:(const GURL&)URL
                       forKey:(NSNumber*)key
                      pending:(BOOL)pending;

// Deletes the parameter `key||pending`.
- (void)removeReportParameter:(NSNumber*)key pending:(BOOL)pending;
@end

// WebStateListObserver that allows loaded urls to be sent to the crash server.
// The different webStates are bundled in groups. Each group reports at most
// 1 URL.
class CrashReporterURLObserver : public WebStateListObserver,
                                 public web::WebStateObserver {
 public:
  CrashReporterURLObserver(id<CrashReporterParameterSetter> params_setter);
  ~CrashReporterURLObserver() override;
  static CrashReporterURLObserver* GetSharedInstance();

  // Removes the URL reported for the group (if any).
  void RemoveWebStateList(WebStateList* web_state_list);

  // Records the given URL associated to the given id to the list of URLs to
  // send to the crash server. If `pending` is true, the URL is one that is
  // expected to start loading, but hasn't actually been seen yet.
  void RecordURL(const GURL& url, const web::WebState* web_state, bool pending);

  // Observes `webState` by this instance of the CrashReporterURLObserver.
  void ObservePreloadWebState(web::WebState* web_state);
  // Stop Observing `webState` by this instance of the CrashReporterURLObserver.
  void StopObservingPreloadWebState(web::WebState* web_state);
  // Observes `webStateList` by this instance of the CrashReporterURLObserver.
  void ObserveWebStateList(WebStateList* web_state_list);
  // Stop Observing `webStateList` by this instance of the
  // CrashReporterURLObserver.
  void StopObservingWebStateList(WebStateList* web_state_list);

  // WebStateObserver
  void DidStartNavigation(web::WebState* web_state,
                          web::NavigationContext* navigation_context) override;
  void DidFinishNavigation(web::WebState* web_state,
                           web::NavigationContext* navigation_context) override;

  // WebStateListObserver
  void WebStateListDidChange(WebStateList* web_state_list,
                             const WebStateListChange& change,
                             const WebStateListStatus& status) override;

 private:
  // A unique string identifying `web_state_list` as a group of WebStates.
  std::string GroupForWebStateList(WebStateList* web_state_list);
  // Convenient method to report the URL displayed by `web_state`.
  void RecordURLForWebState(const web::WebState* web_state);
  // Remove the reporting of URLs of every WebStates in `group`.
  void RemoveGroup(const std::string& group);
  // Map associating each crash key with the group it is currently reporting
  // URLs for.
  NSMutableDictionary<NSString*, NSNumber*>* crash_key_by_group_;
  // Map associating each WebState to its group.
  std::map<const web::WebState*, std::string> web_state_to_group_;
  // Map associating each group to the WebState currently reported in crash
  // reports.
  std::map<std::string, const web::WebState*> current_web_states_;
  // List of keys to use for recording URLs. This list is sorted such that a new
  // tab must use the first key in this list to record its URLs.
  NSMutableArray<NSNumber*>* crash_keys_;
  // Forwards observer methods for all WebStates in the WebStateList monitored
  // by the CrashReporterURLObserver.
  std::map<WebStateList*, std::unique_ptr<AllWebStateObservationForwarder>>
      all_web_state_observation_forwarders_;
  // The object responsible for forwarding the urls to the crash reporter.
  id<CrashReporterParameterSetter> params_setter_;
};

#endif  // IOS_CHROME_BROWSER_CRASH_REPORT_MODEL_CRASH_REPORTER_URL_OBSERVER_H_