Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Conversation

@cyanglaz
Copy link
Contributor

@cyanglaz cyanglaz commented Mar 6, 2020

Description

Fix a potential crash when we cast context() to Application in the v1 embedding code.

Related Issues

flutter/flutter#50861

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

@cyanglaz cyanglaz requested a review from mklim as a code owner March 6, 2020 19:14
@cyanglaz cyanglaz changed the title [in_app_purchase] Android: fix potential crash when casting in v1 embedding. [in_app_purchase] Android: fix potential crash when casting in v1 embedding. (Trivial) Mar 6, 2020
Comment on lines 53 to 54
if (registrar.context().getApplicationContext() != null
&& registrar.context().getApplicationContext() instanceof Application) {
Copy link
Member

Choose a reason for hiding this comment

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

Is it bad if it's null or not an Application? Does that need to be handled?

Copy link
Contributor Author

@cyanglaz cyanglaz Mar 6, 2020

Choose a reason for hiding this comment

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

if either of those situations happens, we are not able to get the application, which makes us no way to register life cycle callbacks. We kind of just bailing here.
I'm not sure if there would be a way to handle that situation in V1 embedding, but we definitely don't want to crash here.

Copy link
Member

Choose a reason for hiding this comment

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

Do we know how people are getting in this state?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not entirely sure. @mklim or @matthew-carroll might have more ideas on this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that you can just say registrar.context().getApplicationContext(). I don't think that context() can return null, and I don't think that getApplicationContext() can return null

Copy link
Contributor

Choose a reason for hiding this comment

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

BTW, do you know why you need an Application? What are the Application methods that are being called that are not defined on a Context?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok. I just did some search and it seems to be the case. I'll update the fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe .registerActivityLifecycleCallbacks is only in Application?

Copy link
Contributor

Choose a reason for hiding this comment

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

That looks right.

Copy link
Contributor

@mklim mklim Mar 7, 2020

Choose a reason for hiding this comment

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

To explain this a little more, there is a difference between an ApplicationContext (can be cast to Application) and an ActivityContext (can be cast to Activity) even though they're both Contexts. Generally it's hard to tell the difference but occasionally it's critical. The Activity Context is tied to the Activity lifecycle so can be invalidated much easier. registrar.context() returns an activity context if an activity has been registered with the Engine and an application context otherwise. getApplicationContext() should always be castable to an application like @matthew-carroll mentioned.

Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

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

WorkspaceSettings.xcsettings looks right. Defer to @matthew-carroll for the java change.

}

@Test
public void registerWith_doNotCrashWhenApplicationContextIsTypeApplication() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this test necessary? We should probably avoid testing situations that can't happen, because it might indicate to readers that it can happen...

Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't context.getApplicationContext() always going to return an application? This looks like the standard case to me.

Copy link
Contributor

Choose a reason for hiding this comment

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

Though on a second look, maybe a more meaningful test here would be to return an Activity from registrar.context() and make sure that that doesn't crash?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mklim Sounds good, I will update the test.

Copy link
Contributor

@mklim mklim left a comment

Choose a reason for hiding this comment

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

LGTM

}

@Test
public void registerWith_doNotCrashWhenApplicationContextIsTypeApplication() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't context.getApplicationContext() always going to return an application? This looks like the standard case to me.

public static void registerWith(Registrar registrar) {
InAppPurchasePlugin plugin = new InAppPurchasePlugin();
plugin.setupMethodChannel(registrar.activity(), registrar.messenger(), registrar.context());
((Application) registrar.context())
Copy link
Contributor

Choose a reason for hiding this comment

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

Just for a little more info in case this doesn't make sense, the bug here is that sometimes registrar.context() will return an Activity context instead of an Application context if it's available and this case will fail. My understanding is that it's the typical for it to do this so I'm actually surprised that this was routinely working before.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was newly added in my new patch so it might be that my patch broke it. However, when I tested locally, it was working. I wonder why activity was not available when i was testing it.

@cyanglaz
Copy link
Contributor Author

cyanglaz commented Mar 9, 2020

Updated the tests based on discussion. Will merge on green.

@cyanglaz
Copy link
Contributor Author

cyanglaz commented Mar 9, 2020

Landing on tree red as it is going to fix a ci error.

@cyanglaz cyanglaz merged commit 43d9b5a into flutter:master Mar 9, 2020
@cyanglaz cyanglaz deleted the iap_crash_fix branch March 9, 2020 19:39
EdwinRomelta pushed a commit to EdwinRomelta/plugins that referenced this pull request Jun 11, 2020
FlutterSu pushed a commit to FlutterSu/flutter-plugins that referenced this pull request Nov 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants