chromium/chromeos/ash/components/boca/on_task/on_task_blocklist.h

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

#ifndef CHROMEOS_ASH_COMPONENTS_BOCA_ON_TASK_ON_TASK_BLOCKLIST_H_
#define CHROMEOS_ASH_COMPONENTS_BOCA_ON_TASK_ON_TASK_BLOCKLIST_H_

#include <map>
#include <memory>

#include "base/memory/raw_ptr.h"
#include "base/memory/singleton.h"
#include "components/policy/core/browser/url_blocklist_manager.h"
#include "components/sessions/core/session_id.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"

// The OnTaskBlocklist is responsible for setting the appropriate url navigation
// restrictions for each tab.
class OnTaskBlocklist {
 public:
  enum class RestrictionLevel {
    kNoRestrictions = 1,               // No url restrictions.
    kLimitedNavigation,                // Only allow exact URL match.
    kSameDomainNavigation,             // Allow domain/subdomain navigation.
    kOneLevelDeepNavigation,           // Allow one level deeper navigation.
    kDomainAndOneLevelDeepNavigation,  // Allows same domain traversal and one
                                       // level deep.
  };

  // BlocklistSource implementation that blocks all traffic with the
  // exception of URLs specified by the teacher's navigation restriction level.
  // Note that this implementation only supports one observer at a time. Adding
  // a new observer will remove the previous one. These should only be called
  // from the main thread.
  class OnTaskBlocklistSource : public policy::BlocklistSource {
   public:
    OnTaskBlocklistSource(const GURL& url,
                          OnTaskBlocklist::RestrictionLevel restriction_type);
    OnTaskBlocklistSource(const OnTaskBlocklistSource&) = delete;
    OnTaskBlocklistSource& operator=(const OnTaskBlocklistSource&) = delete;
    ~OnTaskBlocklistSource() override = default;

    const base::Value::List* GetBlocklistSpec() const override;
    const base::Value::List* GetAllowlistSpec() const override;
    void SetBlocklistObserver(base::RepeatingClosure observer) override {}

   private:
    base::Value::List blocklist_;
    base::Value::List allowlist_;
  };

  explicit OnTaskBlocklist(
      std::unique_ptr<policy::URLBlocklistManager> url_blocklist_manager);
  OnTaskBlocklist(const OnTaskBlocklist&) = delete;
  OnTaskBlocklist& operator=(const OnTaskBlocklist&) = delete;
  ~OnTaskBlocklist();

  // Returns the URLBlocklistState for the given url.
  policy::URLBlocklist::URLBlocklistState GetURLBlocklistState(
      const GURL& url) const;

  // Sets the url restrictions for the given `url` with `restriction_level`.
  // This is different from `SetParentURLRestrictionLevel` since this can be
  // called on newly navigated urls not sent by the boca producer.
  void SetURLRestrictionLevel(
      content::WebContents* tab,
      OnTaskBlocklist::RestrictionLevel restriction_level);

  // Sets the url restrictions for the given `url` with `restriction_level`.
  // Should only be called for the set of urls sent by the boca producer.
  void SetParentURLRestrictionLevel(
      content::WebContents* tab,
      OnTaskBlocklist::RestrictionLevel restriction_level);

  // Updates the blocklist that is associated with the given `tab`. This is
  // triggered on an active tab change or when the current tab changes.
  void RefreshForUrlBlocklist(content::WebContents* tab);

  // Remove the `tab` from the `child_tab_to_nav_filters_`;
  void RemoveChildFilter(content::WebContents* tab);

  void CleanupBlocklist();

  const policy::URLBlocklistManager* url_blocklist_manager();
  std::map<SessionID, OnTaskBlocklist::RestrictionLevel>
  parent_tab_to_nav_filters();
  std::map<SessionID, OnTaskBlocklist::RestrictionLevel>
  child_tab_to_nav_filters();
  std::map<SessionID, bool> has_performed_one_level_deep();
  OnTaskBlocklist::RestrictionLevel current_page_restriction_level();

 private:
  OnTaskBlocklist::RestrictionLevel current_page_restriction_level_ =
      OnTaskBlocklist::RestrictionLevel::kNoRestrictions;
  GURL previous_url_;
  bool first_time_popup_ = true;
  std::map<SessionID, OnTaskBlocklist::RestrictionLevel>
      parent_tab_to_nav_filters_;
  std::map<SessionID, OnTaskBlocklist::RestrictionLevel>
      child_tab_to_nav_filters_;
  std::map<SessionID, bool> has_performed_one_level_deep_;
  const std::unique_ptr<policy::URLBlocklistManager> url_blocklist_manager_;
  base::WeakPtrFactory<OnTaskBlocklist> weak_pointer_factory_{this};
};
#endif  // CHROMEOS_ASH_COMPONENTS_BOCA_ON_TASK_ON_TASK_BLOCKLIST_H_