| Index: chrome/browser/ui/tabs/tab_utils.cc
|
| diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc
|
| index cfe6282b03aeb2d6ad9a80104fae4874f394a759..32facfddbe4d744c504154f5ea6c77eb9b3ad0a9 100644
|
| --- a/chrome/browser/ui/tabs/tab_utils.cc
|
| +++ b/chrome/browser/ui/tabs/tab_utils.cc
|
| @@ -17,12 +17,22 @@
|
| #include "ui/base/resource/resource_bundle.h"
|
| #include "ui/gfx/animation/multi_animation.h"
|
|
|
| +const int kMuteTokenBucketCostSeconds = 15;
|
| +const int kMuteTokenBucketCapacitySeconds = 3 * kMuteTokenBucketCostSeconds;
|
| +
|
| struct LastMuteMetadata
|
| : public content::WebContentsUserData<LastMuteMetadata> {
|
| std::string cause; // Extension ID or constant from header file
|
| // or empty string
|
| + base::TimeDelta token_bucket;
|
| + base::TimeTicks last_attempt;
|
| +
|
| private:
|
| - explicit LastMuteMetadata(content::WebContents* contents) {}
|
| + explicit LastMuteMetadata(content::WebContents* contents) {
|
| + token_bucket =
|
| + base::TimeDelta::FromSeconds(kMuteTokenBucketCapacitySeconds);
|
| + last_attempt = base::TimeTicks::Now();
|
| + }
|
| friend class content::WebContentsUserData<LastMuteMetadata>;
|
| };
|
|
|
| @@ -91,6 +101,29 @@ TabRecordingIndicatorAnimation::Create() {
|
| return animation.Pass();
|
| }
|
|
|
| +// Only run when cause should be rate limited (i.e. extensions)
|
| +// |contents| should exist and have LastMuteMetadata initialized.
|
| +void UpdateTokenBuckets(content::WebContents* contents) {
|
| + base::TimeTicks now = base::TimeTicks::Now();
|
| + base::TimeDelta elapsed_since_last_attempt =
|
| + now - LastMuteMetadata::FromWebContents(contents)->last_attempt;
|
| + LastMuteMetadata::FromWebContents(contents)->last_attempt = now;
|
| +
|
| + // Add tokens to the bucket, proportional to how much time has elapsed, capped
|
| + // at the maximum capacity.
|
| + LastMuteMetadata::FromWebContents(contents)->token_bucket =
|
| + std::min(base::TimeDelta::FromSeconds(kMuteTokenBucketCapacitySeconds),
|
| + LastMuteMetadata::FromWebContents(contents)->token_bucket +
|
| + elapsed_since_last_attempt);
|
| +}
|
| +
|
| +// Only run when cause should be rate limited (i.e. extensions)
|
| +// |contents| should exist and have LastMuteMetadata initialized.
|
| +bool IsTabAudioMutedRateLimited(content::WebContents* contents) {
|
| + return (LastMuteMetadata::FromWebContents(contents)->token_bucket <
|
| + base::TimeDelta::FromSeconds(kMuteTokenBucketCostSeconds));
|
| +}
|
| +
|
| } // namespace
|
|
|
| bool ShouldTabShowFavicon(int capacity,
|
| @@ -276,16 +309,38 @@ const std::string& GetTabAudioMutedCause(content::WebContents* contents) {
|
| return LastMuteMetadata::FromWebContents(contents)->cause;
|
| }
|
|
|
| -void SetTabAudioMuted(content::WebContents* contents,
|
| - bool mute,
|
| - const std::string& cause) {
|
| - if (!contents || !chrome::CanToggleAudioMute(contents))
|
| - return;
|
| +TabMutedResult SetTabAudioMuted(content::WebContents* contents,
|
| + bool mute,
|
| + const std::string& cause) {
|
| + DCHECK(contents);
|
| +
|
| + if (!IsTabAudioMutingFeatureEnabled())
|
| + return TAB_MUTED_RESULT_FAIL_NOT_ENABLED;
|
| +
|
| + if (!chrome::CanToggleAudioMute(contents))
|
| + return TAB_MUTED_RESULT_FAIL_TABCAPTURE;
|
|
|
| LastMuteMetadata::CreateForWebContents(contents); // Create if not exists.
|
| - LastMuteMetadata::FromWebContents(contents)->cause = cause;
|
| +
|
| + if ((IsTabAudioMuted(contents) == mute) &&
|
| + (LastMuteMetadata::FromWebContents(contents)->cause == cause)) {
|
| + return TAB_MUTED_RESULT_SUCCESS;
|
| + }
|
| +
|
| + if ((cause != kMutedToggleCauseUser) && (cause != kMutedToggleCauseCapture)) {
|
| + UpdateTokenBuckets(contents);
|
| +
|
| + if (IsTabAudioMutedRateLimited(contents))
|
| + return TAB_MUTED_RESULT_FAIL_RATE_LIMITED;
|
| +
|
| + LastMuteMetadata::FromWebContents(contents)->token_bucket -=
|
| + base::TimeDelta::FromSeconds(kMuteTokenBucketCostSeconds);
|
| + }
|
|
|
| contents->SetAudioMuted(mute);
|
| + LastMuteMetadata::FromWebContents(contents)->cause = cause;
|
| +
|
| + return TAB_MUTED_RESULT_SUCCESS;
|
| }
|
|
|
| bool IsTabAudioMuted(content::WebContents* contents) {
|
|
|