package org.mozilla.focus.web;

import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.customtabs.CustomTabsIntent;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mozilla.focus.utils.SafeIntent;
import org.robolectric.RobolectricTestRunner;

import java.lang.reflect.Field;

import static org.junit.Assert.*;

@RunWith(RobolectricTestRunner.class)
public class CustomTabConfigTest {

    /**
     * This class can't be unparceled, and can therefore be used to test that SafeIntent and SafeBundle
     * work as expected.
     */
    private static class UnparcelableParcel implements Parcelable {
        UnparcelableParcel() {}

        protected UnparcelableParcel(Parcel in) {
            // Used when unparceling:
            throw new RuntimeException("Haha");
        }

        public static final Creator<UnparcelableParcel> CREATOR = new Creator<UnparcelableParcel>() {
            @Override
            public UnparcelableParcel createFromParcel(Parcel in) {
                return new UnparcelableParcel(in);
            }

            @Override
            public UnparcelableParcel[] newArray(int size) {
                return new UnparcelableParcel[size];
            }
        };

        @Override
        public void writeToParcel(Parcel dest, int flags) {}

        @Override
        public int describeContents() {
            return 0;
        }
    }

    @Test
    public void isCustomTabIntent() throws Exception {
        final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
        final CustomTabsIntent customTabsIntent = builder.build();

        assertTrue(CustomTabConfig.isCustomTabIntent(new SafeIntent(customTabsIntent.intent)));
    }

    @Test
    public void malformedExtras() throws Exception {
        final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();

        final CustomTabsIntent customTabsIntent = builder.build();

        customTabsIntent.intent.putExtra("garbage", new UnparcelableParcel());

        // Warning: yuck
        // We write the extras into a parcel so that we can check what happens when unparcelling fails
        final Parcel parcel = Parcel.obtain();
        final Bundle extras = customTabsIntent.intent.getExtras();
        extras.writeToParcel(parcel, 0);
        extras.clear();

        // Bundle is lazy and doesn't unparcel when calling readBundle()
        parcel.setDataPosition(0);
        final Bundle injectedBundle = parcel.readBundle();
        parcel.recycle();

        // We aren't usually allowed to overwrite an intent's extras:
        final Field extrasField = Intent.class.getDeclaredField("mExtras");
        extrasField.setAccessible(true);
        extrasField.set(customTabsIntent.intent, injectedBundle);
        extrasField.setAccessible(false);

        // And we can't access any extra now because unparcelling fails:
        assertFalse(CustomTabConfig.isCustomTabIntent(new SafeIntent(customTabsIntent.intent)));

        // Ensure we don't crash regardless
        final CustomTabConfig c = CustomTabConfig.parseCustomTabIntent(new SafeIntent(customTabsIntent.intent));

        // And we don't have any data:
        assertNull(c.actionButtonConfig);
    }


    @Test
    public void malformedActionButtonConfig() throws Exception {
        final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
        final CustomTabsIntent customTabsIntent = builder.build();

        final Bundle garbage = new Bundle();
        garbage.putParcelable("foobar", new UnparcelableParcel());
        customTabsIntent.intent.putExtra(CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE, garbage);

        // We should still detect that this is a custom tab
        assertTrue(CustomTabConfig.isCustomTabIntent(new SafeIntent(customTabsIntent.intent)));

        // And we still don't crash
        final CustomTabConfig c = CustomTabConfig.parseCustomTabIntent(new SafeIntent(customTabsIntent.intent));

        // But we weren't able to read the action button data because of the unparcelable data
        assertNull(c.actionButtonConfig);
    }

}
@@ -25,16 +25,50 @@
 s.web;%0A%0A
+import android.app.PendingIntent;%0A
 import a
@@ -369,16 +369,59 @@
 tRunner;
+%0Aimport org.robolectric.RuntimeEnvironment;
 %0A%0Aimport
@@ -781,32 +781,134 @@
     
-UnparcelableParcel() %7B%7D%0A
+// Called when constructing for test purposes%0A        UnparcelableParcel() %7B%0A        %7D%0A%0A        // Used only when unparceling:
 %0A   
@@ -958,46 +958,8 @@
 ) %7B%0A
-            // Used when unparceling:%0A
     
@@ -1510,16 +1510,25 @@
 flags) %7B
+%0A        
 %7D%0A%0A     
@@ -1928,32 +1928,1101 @@
 tent)));%0A    %7D%0A%0A
+    @Test%0A    public void menuTest() throws Exception %7B%0A        final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();%0A        final PendingIntent pendingIntent = PendingIntent.getActivity(null, 0, null, 0);%0A%0A        builder.addMenuItem(%22menuitem1%22, pendingIntent);%0A        builder.addMenuItem(%22menuitem2%22, pendingIntent);%0A        // We can only handle menu items with an actual PendingIntent, other ones should be ignored:%0A        builder.addMenuItem(%22menuitemIGNORED%22, null);%0A%0A        final CustomTabsIntent customTabsIntent = builder.build();%0A%0A        final CustomTabConfig config = CustomTabConfig.parseCustomTabIntent(RuntimeEnvironment.application, new SafeIntent(customTabsIntent.intent));%0A%0A        assertEquals(%22Menu should contain 2 items%22, 2, config.menuItems.size());%0A        final String s = config.menuItems.get(0).name;%0A        assertEquals(%22Unexpected menu item%22,%0A                %22menuitem1%22, config.menuItems.get(0).name);%0A        assertEquals(%22Unexpected menu item%22,%0A                %22menuitem2%22, config.menuItems.get(1).name);%0A    %7D%0A%0A
     @Test%0A    pu
@@ -3302,33 +3302,8 @@
 );%0A%0A
-        // Warning: yuck%0A
     
@@ -4111,16 +4111,17 @@
 ny extra
+s
  now bec
@@ -4350,32 +4350,64 @@
 CustomTabIntent(
+RuntimeEnvironment.application, 
 new SafeIntent(c
@@ -4521,17 +4521,16 @@
 %0A    %7D%0A%0A
-%0A
     @Tes
@@ -5210,32 +5210,64 @@
 CustomTabIntent(
+RuntimeEnvironment.application, 
 new SafeIntent(c

Add CustomTabConfig MenuItem tests