android.support.customtabs.CustomTabsSessionToken Java Examples

The following examples show how to use android.support.customtabs.CustomTabsSessionToken. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: CustomTabActivity.java    From 365browser with Apache License 2.0 7 votes vote down vote up
/**
 * Used to check whether an incoming intent can be handled by the
 * current {@link CustomTabContentHandler}.
 * @return Whether the active {@link CustomTabContentHandler} has handled the intent.
 */
public static boolean handleInActiveContentIfNeeded(Intent intent) {
    if (sActiveContentHandler == null) return false;

    if (sActiveContentHandler.shouldIgnoreIntent(intent)) {
        Log.w(TAG, "Incoming intent to Custom Tab was ignored.");
        return false;
    }

    CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
    if (session == null || !session.equals(sActiveContentHandler.getSession())) return false;

    String url = IntentHandler.getUrlFromIntent(intent);
    if (TextUtils.isEmpty(url)) return false;
    sActiveContentHandler.loadUrlAndTrackFromTimestamp(new LoadUrlParams(url),
            IntentHandler.getTimestampFromIntent(intent));
    return true;
}
 
Example #2
Source File: TwaLauncherTest.java    From custom-tabs-client with Apache License 2.0 6 votes vote down vote up
@Test
public void createsDifferentSessions_IfDifferentIdsSpecified() {
    int sessionId1 = 1;
    int sessionId2 = 2;

    TwaLauncher launcher1 = new TwaLauncher(mActivity, null, sessionId1);
    CustomTabsSessionToken token1 =
            getSessionTokenFromLaunchedBrowser(() -> launcher1.launch(URL));
    launcher1.destroy();

    // New activity is created (e.g. by an external VIEW intent).
    TwaLauncher launcher2 = new TwaLauncher(mActivity, null, sessionId2);
    CustomTabsSessionToken token2 =
            getSessionTokenFromLaunchedBrowser(() -> launcher2.launch(URL));
    launcher2.destroy();

    assertNotEquals(token1, token2);
}
 
Example #3
Source File: CustomTabActivity.java    From delion with Apache License 2.0 6 votes vote down vote up
/**
 * Used to check whether an incoming intent can be handled by the
 * current {@link CustomTabContentHandler}.
 * @return Whether the active {@link CustomTabContentHandler} has handled the intent.
 */
public static boolean handleInActiveContentIfNeeded(Intent intent) {
    if (sActiveContentHandler == null) return false;

    if (sActiveContentHandler.shouldIgnoreIntent(intent)) {
        Log.w(TAG, "Incoming intent to Custom Tab was ignored.");
        return false;
    }

    CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
    if (session == null || !session.equals(sActiveContentHandler.getSession())) return false;

    String url = IntentHandler.getUrlFromIntent(intent);
    if (TextUtils.isEmpty(url)) return false;
    sActiveContentHandler.loadUrlAndTrackFromTimestamp(new LoadUrlParams(url),
            IntentHandler.getTimestampFromIntent(intent));
    return true;
}
 
Example #4
Source File: CustomTabObserver.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
public CustomTabObserver(
        Application application, CustomTabsSessionToken session, boolean openedByChrome) {
    if (openedByChrome) {
        mCustomTabsConnection = null;
    } else {
        mCustomTabsConnection = CustomTabsConnection.getInstance(application);
    }
    mSession = session;
    if (!openedByChrome && mCustomTabsConnection.shouldSendNavigationInfoForSession(mSession)) {
        float desiredWidth = application.getResources().getDimensionPixelSize(
                R.dimen.custom_tabs_screenshot_width);
        float desiredHeight = application.getResources().getDimensionPixelSize(
                R.dimen.custom_tabs_screenshot_height);
        Rect bounds = ExternalPrerenderHandler.estimateContentSize(application, false);
        mScaleForNavigationInfo = (bounds.width() == 0 || bounds.height() == 0) ? 1f :
                Math.min(desiredWidth / bounds.width(), desiredHeight / bounds.height());
    }
    mOpenedByChrome = openedByChrome;
    resetPageLoadTracking();
}
 
Example #5
Source File: CustomTabsConnection.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
private boolean validatePostMessageOriginInternal(final CustomTabsSessionToken session) {
    if (!mWarmupHasBeenCalled.get()) return false;
    if (!isCallerForegroundOrSelf()) return false;
    final int uid = Binder.getCallingUid();
    ThreadUtils.postOnUiThread(new Runnable() {
        @Override
        public void run() {
            // If the API is not enabled, we don't set the post message origin, which will
            // avoid PostMessageHandler initialization and disallow postMessage calls.
            if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_POST_MESSAGE_API)) return;
            mClientManager.setPostMessageOriginForSession(
                    session, acquireOriginForSession(session, uid));
        }
    });
    return true;
}
 
Example #6
Source File: ClientManager.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
/**
 * Registers that a client has launched a URL inside a Custom Tab.
 */
public synchronized void registerLaunch(CustomTabsSessionToken session, String url) {
    int outcome = getPredictionOutcome(session, url);
    RecordHistogram.recordEnumeratedHistogram(
            "CustomTabs.PredictionStatus", outcome, PREDICTION_STATUS_COUNT);

    SessionParams params = mSessionParams.get(session);
    if (outcome == GOOD_PREDICTION) {
        long elapsedTimeMs = SystemClock.elapsedRealtime()
                - params.getLastMayLaunchUrlTimestamp();
        RequestThrottler.getForUid(mContext, params.uid).registerSuccess(
                params.mPredictedUrl);
        RecordHistogram.recordCustomTimesHistogram("CustomTabs.PredictionToLaunch",
                elapsedTimeMs, 1, TimeUnit.MINUTES.toMillis(3), TimeUnit.MILLISECONDS, 100);
    }
    RecordHistogram.recordEnumeratedHistogram(
            "CustomTabs.WarmupStateOnLaunch", getWarmupState(session), SESSION_WARMUP_COUNT);
    if (params != null) params.setPredictionMetrics(null, 0);
}
 
Example #7
Source File: ClientManager.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
@VisibleForTesting
synchronized int getWarmupState(CustomTabsSessionToken session) {
    SessionParams params = mSessionParams.get(session);
    boolean hasValidSession = params != null;
    boolean hasUidCalledWarmup = hasValidSession && mUidHasCalledWarmup.get(params.uid);
    int result = mWarmupHasBeenCalled ? NO_SESSION_WARMUP : NO_SESSION_NO_WARMUP;
    if (hasValidSession) {
        if (hasUidCalledWarmup) {
            result = SESSION_WARMUP;
        } else {
            result = mWarmupHasBeenCalled ? SESSION_NO_WARMUP_ALREADY_CALLED
                                          : SESSION_NO_WARMUP_NOT_CALLED;
        }
    }
    return result;
}
 
Example #8
Source File: CustomTabActivity.java    From AndroidChromium with Apache License 2.0 6 votes vote down vote up
/**
 * Used to check whether an incoming intent can be handled by the
 * current {@link CustomTabContentHandler}.
 * @return Whether the active {@link CustomTabContentHandler} has handled the intent.
 */
public static boolean handleInActiveContentIfNeeded(Intent intent) {
    if (sActiveContentHandler == null) return false;

    if (sActiveContentHandler.shouldIgnoreIntent(intent)) {
        Log.w(TAG, "Incoming intent to Custom Tab was ignored.");
        return false;
    }

    CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
    if (session == null || !session.equals(sActiveContentHandler.getSession())) return false;

    String url = IntentHandler.getUrlFromIntent(intent);
    if (TextUtils.isEmpty(url)) return false;
    sActiveContentHandler.loadUrlAndTrackFromTimestamp(new LoadUrlParams(url),
            IntentHandler.getTimestampFromIntent(intent));
    return true;
}
 
Example #9
Source File: CustomTabsConnection.java    From 365browser with Apache License 2.0 5 votes vote down vote up
private boolean requestPostMessageChannelInternal(final CustomTabsSessionToken session,
        final Uri postMessageOrigin) {
    if (!mWarmupHasBeenCalled.get()) return false;
    if (!isCallerForegroundOrSelf() && !CustomTabActivity.isActiveSession(session)) {
        return false;
    }
    if (!mClientManager.bindToPostMessageServiceForSession(session)) return false;

    final int uid = Binder.getCallingUid();
    ThreadUtils.postOnUiThread(new Runnable() {
        @Override
        public void run() {
            // If the API is not enabled, we don't set the post message origin, which will
            // avoid PostMessageHandler initialization and disallow postMessage calls.
            if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_POST_MESSAGE_API)) return;

            // Attempt to verify origin synchronously. If successful directly initialize
            // postMessage channel for session.
            Uri verifiedOrigin = verifyOriginForSession(session, uid, postMessageOrigin);
            if (verifiedOrigin == null) {
                mClientManager.verifyAndInitializeWithPostMessageOriginForSession(
                        session, postMessageOrigin);
            } else {
                mClientManager.initializeWithPostMessageOriginForSession(
                        session, verifiedOrigin);
            }
        }
    });
    return true;
}
 
Example #10
Source File: ClientManager.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
/**
 * @return The referrer that is associated with the client owning given session.
 */
public synchronized Referrer getReferrerForSession(CustomTabsSessionToken session) {
    SessionParams params = mSessionParams.get(session);
    if (params == null) return null;
    final String packageName = params.packageName;
    return IntentHandler.constructValidReferrerForAuthority(packageName);
}
 
Example #11
Source File: CustomTabActivity.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
/**
 * Checks whether the active {@link CustomTabContentHandler} belongs to the given session, and
 * if true, updates {@link RemoteViews} on the secondary toolbar.
 * @return Whether the update is successful.
 */
static boolean updateRemoteViews(
        CustomTabsSessionToken session, RemoteViews remoteViews, int[] clickableIDs,
        PendingIntent pendingIntent) {
    ThreadUtils.assertOnUiThread();
    // Do nothing if there is no activity or the activity does not belong to this session.
    if (sActiveContentHandler == null || !sActiveContentHandler.getSession().equals(session)) {
        return false;
    }
    return sActiveContentHandler.updateRemoteViews(remoteViews, clickableIDs, pendingIntent);
}
 
Example #12
Source File: CustomTabsConnection.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/**
 * Handle any clean up left after a session is destroyed.
 * @param session The session that has been destroyed.
 */
@VisibleForTesting
void cleanUpSession(final CustomTabsSessionToken session) {
    ThreadUtils.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mClientManager.cleanupSession(session);
        }
    });
}
 
Example #13
Source File: CustomTabsConnection.java    From 365browser with Apache License 2.0 5 votes vote down vote up
public int postMessage(CustomTabsSessionToken session, String message, Bundle extras) {
    int result;
    if (!mWarmupHasBeenCalled.get()) result = CustomTabsService.RESULT_FAILURE_DISALLOWED;
    if (!isCallerForegroundOrSelf() && !CustomTabActivity.isActiveSession(session)) {
        result = CustomTabsService.RESULT_FAILURE_DISALLOWED;
    }
    // If called before a validatePostMessageOrigin, the post message origin will be invalid and
    // will return a failure result here.
    result = mClientManager.postMessage(session, message);
    logCall("postMessage", result);
    return result;
}
 
Example #14
Source File: ClientManager.java    From delion with Apache License 2.0 5 votes vote down vote up
/**
 * @return The referrer that is associated with the client owning given session.
 */
public synchronized Referrer getReferrerForSession(CustomTabsSessionToken session) {
    SessionParams params = mSessionParams.get(session);
    if (params == null) return null;
    final String packageName = params.packageName;
    return IntentHandler.constructValidReferrerForAuthority(packageName);
}
 
Example #15
Source File: CustomTabObserver.java    From 365browser with Apache License 2.0 5 votes vote down vote up
public CustomTabObserver(
        Application application, CustomTabsSessionToken session, boolean openedByChrome) {
    if (openedByChrome) {
        mCustomTabsConnection = null;
    } else {
        mCustomTabsConnection = CustomTabsConnection.getInstance(application);
    }
    mSession = session;
    if (!openedByChrome && mCustomTabsConnection.shouldSendNavigationInfoForSession(mSession)) {
        float desiredWidth = application.getResources().getDimensionPixelSize(
                R.dimen.custom_tabs_screenshot_width);
        float desiredHeight = application.getResources().getDimensionPixelSize(
                R.dimen.custom_tabs_screenshot_height);
        Rect bounds = ExternalPrerenderHandler.estimateContentSize(application, false);
        if (bounds.width() == 0 || bounds.height() == 0) {
            mContentBitmapWidth = (int) Math.round(desiredWidth);
            mContentBitmapHeight = (int) Math.round(desiredHeight);
        } else {
            // Compute a size that scales the content bitmap to fit one (or both) dimensions,
            // but also preserves aspect ratio.
            float scale =
                    Math.min(desiredWidth / bounds.width(), desiredHeight / bounds.height());
            mContentBitmapWidth = (int) Math.round(bounds.width() * scale);
            mContentBitmapHeight = (int) Math.round(bounds.height() * scale);
        }
    }
    mOpenedByChrome = openedByChrome;
    resetPageLoadTracking();
}
 
Example #16
Source File: ClientManager.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/** Unbind from the KeepAlive service for a client. */
public synchronized void dontKeepAliveForSession(CustomTabsSessionToken session) {
    SessionParams params = mSessionParams.get(session);
    if (params == null || params.getKeepAliveConnection() == null) return;
    KeepAliveServiceConnection connection = params.getKeepAliveConnection();
    connection.disconnect();
}
 
Example #17
Source File: CustomTabsConnection.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
/** Cancels a prerender for a given session, or any session if null. */
void cancelPrerender(CustomTabsSessionToken session) {
    ThreadUtils.assertOnUiThread();
    if (mSpeculation != null && (session == null || session.equals(mSpeculation.session))
            && mSpeculation.webContents != null) {
        mExternalPrerenderHandler.cancelCurrentPrerender();
        mSpeculation.webContents.destroy();
        mSpeculation = null;
    }
}
 
Example #18
Source File: ClientManager.java    From delion with Apache License 2.0 5 votes vote down vote up
/**
 * Handle any clean up left after a session is destroyed.
 * @param session The session that has been destroyed.
 */
public synchronized void cleanupSession(CustomTabsSessionToken session) {
    SessionParams params = mSessionParams.get(session);
    if (params == null) return;
    mSessionParams.remove(session);
    if (params.disconnectCallback != null) params.disconnectCallback.run(session);
    mUidHasCalledWarmup.delete(params.uid);
}
 
Example #19
Source File: ClientManager.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/**
 * Handle any clean up left after a session is destroyed.
 * @param session The session that has been destroyed.
 */
public synchronized void cleanupSession(CustomTabsSessionToken session) {
    SessionParams params = mSessionParams.get(session);
    if (params == null) return;
    mSessionParams.remove(session);
    if (params.postMessageHandler != null) {
        params.postMessageHandler.cleanup(mContext);
    }
    if (params.disconnectCallback != null) params.disconnectCallback.run(session);
    mUidHasCalledWarmup.delete(params.uid);
}
 
Example #20
Source File: CustomTabsConnection.java    From 365browser with Apache License 2.0 5 votes vote down vote up
private void startSpeculation(CustomTabsSessionToken session, String url, int speculationMode,
        Bundle extras, int uid) {
    WarmupManager warmupManager = WarmupManager.getInstance();
    Profile profile = Profile.getLastUsedProfile();
    boolean preconnect = true, createSpareWebContents = true;
    if (speculationMode == SpeculationParams.HIDDEN_TAB
            && !ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_BACKGROUND_TAB)) {
        speculationMode = SpeculationParams.PRERENDER;
    }
    switch (speculationMode) {
        case SpeculationParams.PREFETCH:
            boolean didPrefetch = new LoadingPredictor(profile).prepareForPageLoad(url);
            if (didPrefetch) mSpeculation = SpeculationParams.forPrefetch(session, url);
            preconnect = !didPrefetch;
            break;
        case SpeculationParams.PRERENDER:
            boolean didPrerender = prerenderUrl(session, url, extras, uid);
            createSpareWebContents = !didPrerender;
            break;
        case SpeculationParams.HIDDEN_TAB:
            launchUrlInHiddenTab(session, url, extras);
            break;
        default:
            break;
    }
    if (preconnect) warmupManager.maybePreconnectUrlAndSubResources(profile, url);
    if (createSpareWebContents) warmupManager.createSpareWebContents();
}
 
Example #21
Source File: CustomTabActivity.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/**
 * Checks whether the active {@link CustomTabContentHandler} belongs to the given session, and
 * if true, updates {@link RemoteViews} on the secondary toolbar.
 * @return Whether the update is successful.
 */
static boolean updateRemoteViews(
        CustomTabsSessionToken session, RemoteViews remoteViews, int[] clickableIDs,
        PendingIntent pendingIntent) {
    ThreadUtils.assertOnUiThread();
    // Do nothing if there is no activity or the activity does not belong to this session.
    if (sActiveContentHandler == null || !sActiveContentHandler.getSession().equals(session)) {
        return false;
    }
    return sActiveContentHandler.updateRemoteViews(remoteViews, clickableIDs, pendingIntent);
}
 
Example #22
Source File: ClientManager.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
@VisibleForTesting
synchronized int getPredictionOutcome(CustomTabsSessionToken session, String url) {
    SessionParams params = mSessionParams.get(session);
    if (params == null) return NO_PREDICTION;

    String predictedUrl = params.getPredictedUrl();
    if (predictedUrl == null) return NO_PREDICTION;

    boolean urlsMatch = TextUtils.equals(predictedUrl, url)
            || (params.mIgnoreFragments
                    && UrlUtilities.urlsMatchIgnoringFragments(predictedUrl, url));
    return urlsMatch ? GOOD_PREDICTION : BAD_PREDICTION;
}
 
Example #23
Source File: CustomTabsConnection.java    From 365browser with Apache License 2.0 5 votes vote down vote up
private int getSpeculationMode(CustomTabsSessionToken session, int debugOverrideValue) {
    switch (debugOverrideValue) {
        case PREFETCH_ONLY:
            return SpeculationParams.PREFETCH;
        case NO_PRERENDERING:
            return SpeculationParams.NO_SPECULATION;
        default:
            return getSpeculationModeForSession(session);
    }
}
 
Example #24
Source File: ClientManager.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/**
 * See {@link PostMessageHandler#bindSessionToPostMessageService(Context, String)}.
 */
public synchronized boolean bindToPostMessageServiceForSession(CustomTabsSessionToken session) {
    SessionParams params = mSessionParams.get(session);
    if (params == null) return false;
    return params.postMessageHandler.bindSessionToPostMessageService(
            mContext, params.packageName);
}
 
Example #25
Source File: PostMessageHandler.java    From 365browser with Apache License 2.0 5 votes vote down vote up
/**
 * Basic constructor. Everytime the given {@link CustomTabsSessionToken} is associated with a
 * new {@link WebContents},
 * {@link PostMessageHandler#reset(WebContents)} should be called to
 * reset all internal state.
 * @param session The {@link CustomTabsSessionToken} to establish the postMessage communication
 *                with.
 */
public PostMessageHandler(CustomTabsSessionToken session) {
    super(session);
    mMessageCallback = new MessageCallback() {
        @Override
        public void onMessage(String message, MessagePort[] sentPorts) {
            if (mBoundToService) postMessage(message, null);
        }
    };
}
 
Example #26
Source File: TwaLauncherTest.java    From custom-tabs-client with Apache License 2.0 5 votes vote down vote up
@Test
public void reusesSessionForSubsequentLaunches() {
    TwaLauncher launcher1 = new TwaLauncher(mActivity);
    CustomTabsSessionToken token1 =
            getSessionTokenFromLaunchedBrowser(() -> launcher1.launch(URL));
    launcher1.destroy();

    // New activity is created (e.g. by an external VIEW intent).
    TwaLauncher launcher2 = new TwaLauncher(mActivity);
    CustomTabsSessionToken token2 =
            getSessionTokenFromLaunchedBrowser(() -> launcher2.launch(URL));
    launcher2.destroy();

    assertEquals(token1, token2);
}
 
Example #27
Source File: CustomTabsConnection.java    From delion with Apache License 2.0 5 votes vote down vote up
private boolean mayPrerender(CustomTabsSessionToken session) {
    if (!DeviceClassManager.enablePrerendering()) return false;
    // TODO(yusufo): The check for prerender in PrivacyManager now checks for the network
    // connection type as well, we should either change that or add another check for custom
    // tabs. Then PrivacyManager should be used to make the below check.
    if (!PrefServiceBridge.getInstance().getNetworkPredictionEnabled()) return false;
    if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()) return false;
    ConnectivityManager cm =
            (ConnectivityManager) mApplication.getApplicationContext().getSystemService(
                    Context.CONNECTIVITY_SERVICE);
    return !cm.isActiveNetworkMetered() || shouldPrerenderOnCellularForSession(session);
}
 
Example #28
Source File: CustomTabsConnection.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
private boolean mayLaunchUrlInternal(final CustomTabsSessionToken session, Uri url,
        final Bundle extras, final List<Bundle> otherLikelyBundles) {
    final boolean lowConfidence =
            (url == null || TextUtils.isEmpty(url.toString())) && otherLikelyBundles != null;
    final String urlString = checkAndConvertUri(url);
    if (url != null && urlString == null && !lowConfidence) return false;

    // Things below need the browser process to be initialized.

    // Forbids warmup() from creating a spare renderer, as prerendering wouldn't reuse
    // it. Checking whether prerendering is enabled requires the native library to be loaded,
    // which is not necessarily the case yet.
    if (!warmupInternal(false)) return false; // Also does the foreground check.

    final int uid = Binder.getCallingUid();
    // TODO(lizeb): Also throttle low-confidence mode.
    if (!lowConfidence
            && !mClientManager.updateStatsAndReturnWhetherAllowed(session, uid, urlString)) {
        return false;
    }
    ThreadUtils.postOnUiThread(new Runnable() {
        @Override
        public void run() {
            if (lowConfidence) {
                lowConfidenceMayLaunchUrl(otherLikelyBundles);
            } else {
                highConfidenceMayLaunchUrl(session, uid, urlString, extras, otherLikelyBundles);
            }
        }
    });
    return true;
}
 
Example #29
Source File: CustomTabsConnection.java    From AndroidChromium with Apache License 2.0 5 votes vote down vote up
private boolean mayPrerender(CustomTabsSessionToken session) {
    if (!DeviceClassManager.enablePrerendering()) return false;
    // TODO(yusufo): The check for prerender in PrivacyManager now checks for the network
    // connection type as well, we should either change that or add another check for custom
    // tabs. Then PrivacyManager should be used to make the below check.
    if (!PrefServiceBridge.getInstance().getNetworkPredictionEnabled()) return false;
    if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()) return false;
    ConnectivityManager cm =
            (ConnectivityManager) mApplication.getApplicationContext().getSystemService(
                    Context.CONNECTIVITY_SERVICE);
    return !cm.isActiveNetworkMetered() || shouldPrerenderOnCellularForSession(session);
}
 
Example #30
Source File: CustomTabsConnection.java    From 365browser with Apache License 2.0 5 votes vote down vote up
public boolean requestPostMessageChannel(CustomTabsSessionToken session,
        Uri postMessageOrigin) {
    boolean success = requestPostMessageChannelInternal(session, postMessageOrigin);
    logCall("requestPostMessageChannel() with origin "
            + (postMessageOrigin != null ? postMessageOrigin.toString() : ""), success);
    return success;
}