// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/user_script_listener.h"

#include "base/bind.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/timer/elapsed_timer.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/content_scripts_handler.h"
#include "extensions/common/url_pattern.h"

using content::BrowserThread;
using content::NavigationThrottle;
using content::ResourceType;

namespace extensions {

class UserScriptListener::Throttle
    : public NavigationThrottle,
      public base::SupportsWeakPtr<UserScriptListener::Throttle> {
 public:
  explicit Throttle(content::NavigationHandle* navigation_handle)
      : NavigationThrottle(navigation_handle) {}

  void ResumeIfDeferred() {
    DCHECK(should_defer_);
    should_defer_ = false;
    // Only resume the request if |this| has deferred it.
    if (did_defer_) {
      UMA_HISTOGRAM_TIMES("Extensions.ThrottledNetworkRequestDelay",
                          timer_->Elapsed());
      Resume();
    }
  }

  // NavigationThrottle implementation:
  ThrottleCheckResult WillStartRequest() override {
    // Only defer requests if Resume has not yet been called.
    if (should_defer_) {
      did_defer_ = true;
      timer_.reset(new base::ElapsedTimer());
      return DEFER;
    }
    return PROCEED;
  }

  const char* GetNameForLogging() override {
    return "UserScriptListener::Throttle";
  }

 private:
  bool should_defer_ = true;
  bool did_defer_ = false;
  std::unique_ptr<base::ElapsedTimer> timer_;

  DISALLOW_COPY_AND_ASSIGN(Throttle);
};

struct UserScriptListener::ProfileData {
  // True if the user scripts contained in |url_patterns| are ready for
  // injection.
  bool user_scripts_ready = false;

  // A list of URL patterns that have will have user scripts applied to them.
  URLPatterns url_patterns;
};

UserScriptListener::UserScriptListener() : extension_registry_observer_(this) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Profile manager can be null in unit tests.
  if (g_browser_process->profile_manager()) {
    for (auto* profile :
         g_browser_process->profile_manager()->GetLoadedProfiles()) {
      extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
    }
  }

  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
                 content::NotificationService::AllSources());

  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
                 content::NotificationService::AllSources());
  registrar_.Add(this,
                 extensions::NOTIFICATION_USER_SCRIPTS_UPDATED,
                 content::NotificationService::AllSources());
}

std::unique_ptr<NavigationThrottle>
UserScriptListener::CreateNavigationThrottle(
    content::NavigationHandle* navigation_handle) {
  if (!ShouldDelayRequest(navigation_handle->GetURL()))
    return nullptr;

  auto throttle = std::make_unique<Throttle>(navigation_handle);
  throttles_.push_back(throttle->AsWeakPtr());
  return throttle;
}

void UserScriptListener::SetUserScriptsNotReadyForTesting(
    content::BrowserContext* context) {
  AppendNewURLPatterns(context, {URLPattern(URLPattern::SCHEME_ALL,
                                            URLPattern::kAllUrlsPattern)});
}

UserScriptListener::~UserScriptListener() {}

bool UserScriptListener::ShouldDelayRequest(const GURL& url) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // Note: we could delay only requests made by the profile who is causing the
  // delay, but it's a little more complicated to associate requests with the
  // right profile. Since this is a rare case, we'll just take the easy way
  // out.
  if (user_scripts_ready_)
    return false;

  for (ProfileDataMap::const_iterator pt = profile_data_.begin();
       pt != profile_data_.end(); ++pt) {
    for (auto it = pt->second.url_patterns.begin();
         it != pt->second.url_patterns.end(); ++it) {
      if ((*it).MatchesURL(url)) {
        // One of the user scripts wants to inject into this request, but the
        // script isn't ready yet. Delay the request.
        return true;
      }
    }
  }

  return false;
}

void UserScriptListener::StartDelayedRequests() {
  WeakThrottleList::const_iterator it;
  for (it = throttles_.begin(); it != throttles_.end(); ++it) {
    if (it->get())
      (*it)->ResumeIfDeferred();
  }
  throttles_.clear();
}

void UserScriptListener::CheckIfAllUserScriptsReady() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  bool was_ready = user_scripts_ready_;

  user_scripts_ready_ = true;
  for (ProfileDataMap::const_iterator it = profile_data_.begin();
       it != profile_data_.end(); ++it) {
    if (!it->second.user_scripts_ready)
      user_scripts_ready_ = false;
  }

  if (user_scripts_ready_ && !was_ready)
    StartDelayedRequests();
}

void UserScriptListener::UserScriptsReady(content::BrowserContext* context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  profile_data_[context].user_scripts_ready = true;
  CheckIfAllUserScriptsReady();
}

void UserScriptListener::ProfileDestroyed(content::BrowserContext* context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  profile_data_.erase(context);

  // We may have deleted the only profile we were waiting on.
  CheckIfAllUserScriptsReady();
}

void UserScriptListener::AppendNewURLPatterns(content::BrowserContext* context,
                                              const URLPatterns& new_patterns) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  user_scripts_ready_ = false;

  ProfileData& data = profile_data_[context];
  data.user_scripts_ready = false;

  data.url_patterns.insert(data.url_patterns.end(),
                           new_patterns.begin(), new_patterns.end());
}

void UserScriptListener::ReplaceURLPatterns(content::BrowserContext* context,
                                            const URLPatterns& patterns) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  ProfileData& data = profile_data_[context];
  data.url_patterns = patterns;
}

void UserScriptListener::CollectURLPatterns(const Extension* extension,
                                            URLPatterns* patterns) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  for (const std::unique_ptr<UserScript>& script :
       ContentScriptsInfo::GetContentScripts(extension)) {
    patterns->insert(patterns->end(), script->url_patterns().begin(),
                     script->url_patterns().end());
  }
}

void UserScriptListener::Observe(int type,
                                 const content::NotificationSource& source,
                                 const content::NotificationDetails& details) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  switch (type) {
    case chrome::NOTIFICATION_PROFILE_ADDED: {
      auto* registry =
          ExtensionRegistry::Get(content::Source<Profile>(source).ptr());
      DCHECK(!extension_registry_observer_.IsObserving(registry));
      extension_registry_observer_.Add(registry);
      break;
    }
    case chrome::NOTIFICATION_PROFILE_DESTROYED: {
      Profile* profile = content::Source<Profile>(source).ptr();
      ProfileDestroyed(profile);
      break;
    }
    case extensions::NOTIFICATION_USER_SCRIPTS_UPDATED: {
      Profile* profile = content::Source<Profile>(source).ptr();
      UserScriptsReady(profile);
      break;
    }
    default:
      NOTREACHED();
  }
}

void UserScriptListener::OnExtensionLoaded(
    content::BrowserContext* browser_context,
    const Extension* extension) {
  if (ContentScriptsInfo::GetContentScripts(extension).empty())
    return;  // no new patterns from this extension.

  URLPatterns new_patterns;
  CollectURLPatterns(extension, &new_patterns);
  if (!new_patterns.empty()) {
    AppendNewURLPatterns(browser_context, new_patterns);
  }
}

void UserScriptListener::OnExtensionUnloaded(
    content::BrowserContext* browser_context,
    const Extension* extension,
    UnloadedExtensionReason reason) {
  if (ContentScriptsInfo::GetContentScripts(extension).empty())
    return;  // No patterns to delete for this extension.

  // Clear all our patterns and reregister all the still-loaded extensions.
  const ExtensionSet& extensions =
      ExtensionRegistry::Get(browser_context)->enabled_extensions();
  URLPatterns new_patterns;
  for (ExtensionSet::const_iterator it = extensions.begin();
       it != extensions.end(); ++it) {
    if (it->get() != extension)
      CollectURLPatterns(it->get(), &new_patterns);
  }
  ReplaceURLPatterns(browser_context, new_patterns);
}

void UserScriptListener::OnShutdown(ExtensionRegistry* registry) {
  extension_registry_observer_.Remove(registry);
}

}  // namespace extensions
