Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable granular control of autoplay #222

Merged
merged 20 commits into from
Aug 7, 2018
Merged

Enable granular control of autoplay #222

merged 20 commits into from
Aug 7, 2018

Conversation

darkdh
Copy link
Member

@darkdh darkdh commented Jul 5, 2018

by following steps:

  1. Add AutoplayPermissionContext
  2. Update PermissionDescriptorToPermissionType
  3. RquestPermission from AutoplayPolicy
  4. Content setting page & blocked status bubble
  5. Auto refresh when clicking allow in permission ask bubble

fix brave/brave-browser#281

Auditors: @bbondy, @bridiver

Submitter Checklist:

  • Submitted a ticket for my issue if one did not already exist.
  • Used Github auto-closing keywords in the commit message.
  • Added/updated tests for this change (for new code or code which already has tests).
  • Ran git rebase -i to squash commits (if needed).
  • Tagged reviewers and labelled the pull request as needed.
  • Request a security/privacy review as needed.

Test Plan:

Automatic:

yarn test brave_unit_tests --filter=AutoplayPermissionContextTests.*
yarn test brave_browser_tests --filter=AutoplayPermissionContextBrowserTest.*
yarn test brave_browser_tests --filter=BraveAutoplayBlockedImageModelTest.*

Manual:
a. Allow autoplay

  1. Go to https://www.cnet.com/ pick a random article
  2. There should be a bubble shows up asking allow/block www.cnet.com to autoplay media screen shot 2018-07-09 at 6 51 03 pm
  3. Click allow and the page should auto refresh and video should play
  4. Check Autoplay site setting should be allow
    4.a In site detail screen shot 2018-07-09 at 6 51 53 pm
    4.b In site content setting screen shot 2018-07-09 at 6 55 26 pm
    4.c In global content setting screen shot 2018-07-09 at 6 57 08 pm
  5. Next time you visit cnet.com, the video will be autoplay automatically

b. Block autoplay

  1. Same steps as a.
  2. Except click block will not refresh the page
  3. Notice when video is blocked there will be an indicator on urlbar

screen shot 2018-07-09 at 7 12 05 pm

c. General behavior

  1. every time you change site content setting, there will be a banner shows up

screen shot 2018-07-09 at 7 12 39 pm

2. If you close permission bubble, that would be automatically blocked

screen shot 2018-07-09 at 7 15 33 pm

screen shot 2018-07-09 at 7 16 21 pm

3. Open any local media files should allow autoplay by default

Reviewer Checklist:

  • New files have MPL-2.0 license header.
  • Request a security/privacy review as needed.
  • Adequate test coverage exists to prevent regressions

@darkdh darkdh self-assigned this Jul 5, 2018
"list_item_ordinal.h",
"media/autoplay_policy.cc",
"media/autoplay_policy.h",
+ "//third_party/blink/renderer/modules/permissions/permission_utils.cc",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blink/renderer/modules depends on blink/renderer/core so if I add deps here will introduce circular deps

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain more? This seems really strange.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use functions of third_party/blink/renderer/modules/permissions/permission_utils.h in third_party/blink/renderer/core/html/media/autoplay_policy.cc for requesting permission.
So we need to add dependency for "//third_party/blink/renderer/modules/permissions:permissions"
Unfortunately, it will cause this circular dependency error

ERROR Dependency cycle:
  //third_party/blink/renderer/core:core ->
  //third_party/blink/renderer/core/html:html ->
  //third_party/blink/renderer/modules/permissions:permissions ->
  //third_party/blink/renderer/core:core

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this will effectively build it twice and we don't want that. What build error do you get without it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undefined symbols for architecture x86_64:
  "blink::ConnectToPermissionService(blink::ExecutionContext*, mojo::InterfaceRequest<blink::mojom::blink::PermissionService>)", referenced from:
      blink::AutoplayPolicy::IsAutoplayAllowedPerSettings() const in autoplay_policy.o
  "blink::CreatePermissionDescriptor(blink::mojom::PermissionName)", referenced from:
      blink::AutoplayPolicy::IsAutoplayAllowedPerSettings() const in autoplay_policy.o

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 2d27548

@darkdh darkdh force-pushed the autoplay-rebase branch 2 times, most recently from c9555b0 to b4ae901 Compare July 10, 2018 01:35
@darkdh darkdh changed the title WIP: autoplay Enable granular control of autoplay Jul 10, 2018
@darkdh darkdh requested review from bbondy and bridiver July 10, 2018 02:18
@bbondy
Copy link
Member

bbondy commented Jul 10, 2018

Some comments for a v2 iteration, not blocking this review, it is still in progress.

Noting that a user might get almost as annoyed with autoplay as with a popup that asks them if they want to allow autoplay. Also when clicking allow on that popup, I know this is just for now, but reloading the page is probably also painful for users.

An alternative to reloading that I think is better is displaying this bar:
screen shot 2018-07-10 at 12 30 37 pm

But even that might be annoying. URL bar icon only is maybe enough.

Copy link
Member

@bbondy bbondy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't have time to make suggestions on everything but we need to try to reduce the patches more. One thing to note is patch and call into src/brave is better than patch and don't. The reason is because maintaining patch files while we have multiple chromium versions is going to be harder for each .patch change. But if we just add in the hooks and then change things in src/brave, those are easy things to pull into different chromium versions that we maintain.

return CONTENT_SETTINGS_TYPE_CLIPBOARD_WRITE;
case PermissionType::PAYMENT_HANDLER:
return CONTENT_SETTINGS_TYPE_PAYMENT_HANDLER;
+ case PermissionType::AUTOPLAY:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe go with rename PermissionTypeToContentSetting to PermissionTypeToContentSetting_ChromiumImpl
in a patch and then chromium_src override to provide a proper definition that uses it. In that way we can add in more types later without touching patching from there on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternately call into something like if(BravePermissionTypeToContentSetting(&permission) return permission` and then have the function inside src/brave.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overrides is not gonna work because there are callers of it in the same file. It will end up no one calling this function.
Second idea doesn't work either unless we turn off this compile time checking
error: enumeration value 'AUTOPLAY' not handled in switch [-Werror,-Wswitch]
error: 16 enumeration values not handled in switch: 'MIDI_SYSEX', 'NOTIFICATIONS', 'GEOLOCATION'... [-Werror,-Wswitch]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we subclass PermissionManager and then override those caller method, it eliminates the patch but that would be too many copy logic. Not sure if it is worthy.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@darkdh it doesn't matter if there are callers in the same file. @bbondy he can redefine PermissionTypeToContentSetting, the problem is actually that he can't reference the original method because it's in an anonymous namespace so he'd have to replace the entire thing

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@darkdh Chrome already has content settings for allowing sites to play sound, can't we use those?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually didn't Chrome briefly turn off autoplay by default? Can't we just turn back on whatever they turned off? Seems odd that we would need our own permission for something that is already in chrome

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sound content setting doesn't have capacity to stop video from autoplaying.
Chrome's autoplay is globally defined, users can only change the global autoplay policy
screen shot 2018-07-25 at 10 18 33 am
And Chrome also default allows muted video and there is no control of content settings for different sites for users

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually patch one line default: NOTREACHED() should allow us to get around [-Werror,-Wswitch]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 1154635

permission_contexts_[CONTENT_SETTINGS_TYPE_PAYMENT_HANDLER] =
std::make_unique<payments::PaymentHandlerPermissionContext>(profile);
+ permission_contexts_[CONTENT_SETTINGS_TYPE_AUTOPLAY] =
+ std::make_unique<AutoplayPermissionContext>(profile);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer we just use a subclass of PermissionManager and patch instead to instantiate it.
Allowing less patching in the future has value because we'll need to for example rebase changes that land across multiple Chromium versions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in ea9e693

WebRuntimeFeatures::EnableWebNfc(true);
#endif

+#if !defined(BRAVE_CHROMIUM_BUILD)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of patching here can you use chromium_src override and rename away SetRuntimeFeaturesDefaultsAndUpdateFromArgs to SetRuntimeFeaturesDefaultsAndUpdateFromArgs_ChromiumImpl? Then adjust the value of WebRuntimeFeatures::EnableAutoplayMutedVideos as you want after your SetRuntimeFeaturesDefaultsAndUpdateFromArgs calls SetRuntimeFeaturesDefaultsAndUpdateFromArgs_Impl

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in e4cc08b

WebsiteSettingsRegistry::PLATFORM_ANDROID,
ContentSettingsInfo::INHERIT_IN_INCOGNITO);

- Register(CONTENT_SETTINGS_TYPE_AUTOPLAY, "autoplay", CONTENT_SETTING_ALLOW,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use chromium_src override here and define your own Register function that calls the ChromiumImpl passing on the same args for everything except for when "autoplay" is encountered, it does what you do here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in a85e50e


if (base::FeatureList::IsEnabled(media::kUnifiedAutoplay))
+#if defined(BRAVE_CHROMIUM_BUILD)
+ return switches::autoplay::kUserGestureRequiredPolicy;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chromium_src override for this please.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 2f47e35

{CONTENT_SETTINGS_TYPE_SENSORS, "sensors"},
{CONTENT_SETTINGS_TYPE_PAYMENT_HANDLER, "payment-handler"},
{CONTENT_SETTINGS_TYPE_USB_GUARD, "usb-devices"},
+ {CONTENT_SETTINGS_TYPE_AUTOPLAY, "autoplay"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer chromium_src override method here for HasRegisteredGroupName, ContentSettingsTypeFromGroupName, ContentSettingsTypeToGroupName here. Create own array built from filtered kContentSettingsTypeGroupNames

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 6557fd8

"list_item_ordinal.h",
"media/autoplay_policy.cc",
"media/autoplay_policy.h",
+ "//third_party/blink/renderer/modules/permissions/permission_utils.cc",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain more? This seems really strange.

@@ -2080,6 +2081,14 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS},
{"siteSettingsProtectedContentEnable",
IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_ENABLE},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename in patch file for AddSiteSettingsStrings and chromium_src override to use it and add your own things to it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

already there, just forgot to remove patch

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 2f47e35

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated fix 2ead047

// Push does not allow permission requests from iframes.
PermissionManager::Get(profile_)->RequestPermission(
- CONTENT_SETTINGS_TYPE_NOTIFICATIONS, web_contents->GetMainFrame(),
+ CONTENT_SETTINGS_TYPE_AUTOPLAY, web_contents->GetMainFrame(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to do this in addition?
Maybe subclass for this and patch the creation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I forgot to remove this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 2f47e35

case PermissionRequestType::PERMISSION_PAYMENT_HANDLER:
return "PaymentHandler";
+ case PermissionRequestType::PERMISSION_AUTOPLAY:
+ return "Autoplay";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this is only used by RecordEngagementMetric, is that needed? Maybe if PERMISSION_AUTOPLAY was just a separate int which is cast where needed it would simplify needing to have all enum values specified?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTREACHED() after this will CHECK failed and crash browser if we don't handle this case.
And I prefer putting it into enum because it can save us from something that we don't handle in compile time when upstream add other usage somewhere.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 462c5d2

@darkdh darkdh force-pushed the autoplay-rebase branch 2 times, most recently from e9bb454 to 8f07aee Compare July 31, 2018 00:13
return false;

+ // brave(darkdh): default allow local files
+ if (element_->GetDocument().origin() == String("null") || element_->GetDocument().origin() == String("file://"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be done with a default content setting

There were link errors on Windows
```
../../third_party/llvm-build/Release+Asserts/bin\lld-link.exe: error:
undefined symbol:
?GetForProfile@PermissionManagerFactory@@SAPEAVPermissionManager@@PEAVProfile@@@z
>>> referenced by
C:\brave-browser\src\chrome\browser\permissions\permission_manager.cc:264
>>>
browser.lib(permission_manager.obj):(?Get@PermissionManager@@SAPEAV1@PEAVProfile@@@z)

../../third_party/llvm-build/Release+Asserts/bin\lld-link.exe: error:
undefined symbol:
?GetForProfile@PermissionManagerFactory@@SAPEAVPermissionManager@@PEAVProfile@@@z
>>> referenced by
C:\brave-browser\src\chrome\browser\budget_service\budget_service_impl.cc:56
>>>
browser.lib(budget_service_impl.obj):(?GetBudget@BudgetServiceImpl@@UEAAXV?$OnceCallback@$$A6AXW4BudgetServiceErrorType@mojom@blink@@v?$vector@V?$InlinedStructPtr@VBudgetState@mojom@blink@@@mojo@@v?$allocator@V?$InlinedStructPtr@VBudgetState@mojom@blink@@@mojo@@@std@@@std@@@z@base@@@z)

../../third_party/llvm-build/Release+Asserts/bin\lld-link.exe: error:
undefined symbol:
?GetForProfile@PermissionManagerFactory@@SAPEAVPermissionManager@@PEAVProfile@@@z
>>> referenced by
C:\brave-browser\src\chrome\browser\profiles\profile_impl.cc:1094
>>>
browser.lib(profile_impl.obj):(?GetPermissionControllerDelegate@ProfileImpl@@UEAAPEAVPermissionControllerDelegate@content@@xz)

../../third_party/llvm-build/Release+Asserts/bin\lld-link.exe: error:
undefined symbol:
?GetForProfile@PermissionManagerFactory@@SAPEAVPermissionManager@@PEAVProfile@@@z
>>> referenced by
C:\brave-browser\src\chrome\browser\profiles\off_the_record_profile_impl.cc:450
>>>
browser.lib(off_the_record_profile_impl.obj):(?GetPermissionControllerDelegate@OffTheRecordProfileImpl@@UEAAPEAVPermissionControllerDelegate@content@@xz)
```
because
b4842cc#diff-e9e16c8776e75c58827f5f1af6feac31R1
also changes signature of `PermissionManagerFactory::GetForProfile` but
we only need `PermissionManagerFactory::BuildServiceInstanceFor`
@darkdh
Copy link
Member Author

darkdh commented Aug 7, 2018

build and test pass on all platforms.

#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gtest/include/gtest/gtest.h"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 1 newline

.content_setting);
}

// There is no way to genearte a request that is automatically accepted in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: generate

}

// There is no way to genearte a request that is automatically accepted in
// unittest by RequestPermission so we test reverse cases here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: // unittest by RequestPermission, so we test reverse cases here

return GetPermissionRequestString_ChromiumImpl(type);
}

}
Copy link
Member

@bbondy bbondy Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
} // namespace

}
}

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
} // namespace

BraveAddCommonStrings(html_source, profile);
}

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
} // namespace settings

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will stop commenting on those but apply everywhere please.

content_type != CONTENT_SETTINGS_TYPE_PPAPI_BROKER &&
content_type != CONTENT_SETTINGS_TYPE_MIDI_SYSEX &&
content_type != CONTENT_SETTINGS_TYPE_CLIPBOARD_READ &&
+ content_type != CONTENT_SETTINGS_TYPE_AUTOPLAY &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can probably improve on this patch in a follow up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bbondy
bbondy previously approved these changes Aug 7, 2018
Copy link
Member

@bbondy bbondy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you mentioned as followups sounds good, but please post a new issue for those and mark this issue as fixed by this PR.

@darkdh
Copy link
Member Author

darkdh commented Aug 7, 2018

Followup issue link brave/brave-browser#699

@darkdh darkdh merged commit 409515d into master Aug 7, 2018
@darkdh darkdh deleted the autoplay-rebase branch August 21, 2018 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add disable Autoplay support
3 participants