New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 758635 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Last visit > 30 days ago
Closed: Aug 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug



Sign in to add a comment

Disabling then re-enabling SiteNotificationChannels can trigger a crash

Project Member Reported by awdf@chromium.org, Aug 24 2017

Issue description

Chrome Version: (copy from chrome://version)
OS: (e.g. Win7, OSX 10.9.5, etc...)

What steps will reproduce the problem?

(0) Cherry-pick the Unmigration CL changes here: https://chromium-review.googlesource.com/c/chromium/src/+/628680 (should soon ship)

(1) Ensure the flag is enabled:
build/android/adb_chrome_public_command_line --enable-features=SiteNotificationChannels

(2) Grant notification permission to tests.peter.sh

(3) Disable the flag:
build/android/adb_chrome_public_command_line ""

(4) Kill & restart the app

(5) Block notification permission for tests.peter.sh via site settings

(6) Enable the flag as in (1)

(7) Kill & restart the app


What is the expected result?

No crash and the block setting is migrated so a new channel is created as blocked

What happens instead?

Crash: '[FATAL:notification_channels_provider_android.cc(385)] Check failed: old_chan
nel_status == new_channel_status (1 vs. 0)


It seems we crash because the pref provider returns a rule iterator with two rules in for the origin - both BLOCK, and ALLOW. We dcheck  when trying to create a channel for the second one.

I don't know why the pref provider returns two rules for the same origin - we only call SetWebsiteSetting on it once during the unmigration process.

Some local logs that might help:

08-24 16:58:47.470 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(186)] ANITA: MigrateToChannelsIfNecessary
08-24 16:58:47.470 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(421)] ANITA: InitCachedChannels
08-24 16:58:47.476 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(188)] ANITA: MigrateToChannelsIfNecessary Initialized cache.
08-24 16:58:47.476 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(399)] ANITA: CreateChannelForRule origin=https://tests.peter.sh, setting=2
08-24 16:58:47.476 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(365)] ANITA: CreateChannelIfRequired origin=https://tests.peter.sh, status=1
08-24 16:58:47.476 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(371)] ANITA: CreateChannelIfRequired cache miss
08-24 16:58:47.483 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(399)] ANITA: CreateChannelForRule origin=https://tests.peter.sh, setting=1
08-24 16:58:47.483 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(365)] ANITA: CreateChannelIfRequired origin=https://tests.peter.sh, status=0
08-24 16:58:47.483 W/chromium(17501): [WARNING:notification_channels_provider_android.cc(382)] ANITA: CreateChannelIfRequired cache hit



 

Comment 1 by awdf@chromium.org, Aug 24 2017

Cc: dominickn@chromium.org
cc dominick in case you have ideas why the pref provider might return two conflicting rules for the same origin
I've done some poking and my suspicion is because of the inconsistent treatment of the port between url::Origin::Serialize -> ContentSettingsPattern::FromString and GURL -> ContentSettingsPattern::FromURLNoWildcard.

url::Origin::Serialize() strips the port if it's the default port for the scheme (https://cs.chromium.org/chromium/src/url/scheme_host_port.cc?type=cs&sq=package:chromium&l=217). Then using ContentSettingsPattern::FromString sets the port to a wildcard  (https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_pattern_parser.cc?gsn=Parse&l=167).

However, ContentSettingsPattern::FromURLNoWildcard (which is used by SetWebsiteSetting) explicitly keeps the port, and if the port isn't there, it adds the default port, not a wildcard (https://cs.chromium.org/chromium/src/components/content_settings/core/common/content_settings_pattern.cc?type=cs&q=components/content_settings/core/common/content_settings_pattern.cc&sq=package:chromium&l=387). So you have this behaviour:

1. Allow permission (port = 443)
2. Migrate (creates channels with the port stripped out)
3. Unmigrate (uses ContentSettingsPattern::FromString on url::Origin::Serialize, no port)

At this point we have two conflicting rules: one for port 443, and one for *.

Can you try keeping to using the same code path as what settings does (i.e. ContentSettingsPattern::FromURLNoWildcard from a GURL)?

Comment 3 by awdf@chromium.org, Aug 25 2017

Status: Started (was: Assigned)
Agree with your hypothesis - adding a log in content_settings_pref_provider confirmed it:
... unmigrate ...
08-25 10:46:20.477 W/chromium(25834): [WARNING:content_settings_pref_provider.cc(149)] ANITA: SetWebsiteSetting pattern=https://tests.peter.sh

... block site from site settings ...
08-25 10:47:22.513 W/chromium(25834): [WARNING:content_settings_pref_provider.cc(149)] ANITA: SetWebsiteSetting pattern=https://tests.peter.sh:443


, changing ContentSettingsPattern::FromString(..) --> ContentSettingsPattern::FromURLNoWildcard(GURL(...)) where I construct the pattern from the channel origin means they both get the port and only one rule is then returned so the crash goes away - hooray! 

Thanks so much for your help figuring this out - saved me a bunch of debugging :)

Now I just need to figure out how to write a regression test for this!

Comment 4 by awdf@chromium.org, Aug 30 2017

I've done a quick fix in the interests of expediency as per #3 here: https://chromium-review.googlesource.com/c/chromium/src/+/643069 

Filed  crbug.com/760510  to make it use the same codepath as SetWebsiteSetting in future as suggested in #2. I think that's a really good idea but it'll take a little longer.
Project Member

Comment 5 by bugdroid1@chromium.org, Aug 30 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/42bb1dd7d8e7836997e0207d472e15c65bbc2aad

commit 42bb1dd7d8e7836997e0207d472e15c65bbc2aad
Author: Anita Woodruff <awdf@chromium.org>
Date: Wed Aug 30 14:11:52 2017

[Android notification channels] Quick fix for flag re-enabling crash

- Previously the ContentSettingsPrefProvider could end up storing two
conflicting notification settings for the same origin after
unmigrating channel settings, due to recreating the
ContentSettingsPattern from the channel origin inconsistently with how
it is created when setting a website pattern in the normal way. This
meant we would sometimes fail a DCHECK in the channels provider when
re-migrating to channel settings.

- This change makes the construction of a ContentSettingsPattern from
a channel origin string consistent with how ContentSettingPatterns are
constructed via HostContentSettingsMap.SetWebsiteSetting - first
convert to a GURL, then use ContentSettingsPattern::FromURLNoWildCard.

- A proper fix would involve going through HCSM.SetWebsiteSetting,
to ensure this is always done consistently - filed  crbug.com/760510 
to do this.

Bug:  758635 
Change-Id: I468075e62f7dce7f092389fb72f9d02f89925902
Reviewed-on: https://chromium-review.googlesource.com/643069
Commit-Queue: Anita Woodruff <awdf@chromium.org>
Reviewed-by: Peter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#498451}
[modify] https://crrev.com/42bb1dd7d8e7836997e0207d472e15c65bbc2aad/chrome/browser/notifications/notification_channels_provider_android.cc
[modify] https://crrev.com/42bb1dd7d8e7836997e0207d472e15c65bbc2aad/chrome/browser/notifications/notification_channels_provider_android_unittest.cc

Comment 6 by awdf@chromium.org, Aug 30 2017

Status: Fixed (was: Started)

Sign in to add a comment