text:
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.customtabs;

import android.app.ActivityManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.os.StrictMode;
import android.support.customtabs.CustomTabsCallback;
import android.support.customtabs.CustomTabsIntent;
import android.support.customtabs.CustomTabsService;
import android.support.customtabs.CustomTabsSessionToken;
import android.text.TextUtils;
import android.widget.RemoteViews;

import org.chromium.base.CommandLine;
import org.chromium.base.Log;
import org.chromium.base.SysUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeApplication;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.WarmupManager;
import org.chromium.chrome.browser.WebContentsFactory;
import org.chromium.chrome.browser.device.DeviceClassManager;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.prerender.ExternalPrerenderHandler;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.util.IntentUtils;
import org.chromium.chrome.browser.util.UrlUtilities;
import org.chromium.content.browser.ChildProcessCreationParams;
import org.chromium.content.browser.ChildProcessLauncher;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.common.Referrer;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Implementation of the ICustomTabsConnectionService interface.
 *
 * Note: This class is meant to be package private, and is public to be
 * accessible from {@link ChromeApplication}.
 */
public class CustomTabsConnection {
    private static final String TAG = "ChromeConnection";
    private static final String LOG_SERVICE_REQUESTS = "custom-tabs-log-service-requests";

    @VisibleForTesting
    static final String PAGE_LOAD_METRICS_CALLBACK = "NavigationMetrics";
    @VisibleForTesting
    static final String NO_PRERENDERING_KEY =
            "android.support.customtabs.maylaunchurl.NO_PRERENDERING";

    private static AtomicReference<CustomTabsConnection> sInstance =
            new AtomicReference<CustomTabsConnection>();

    @VisibleForTesting
    static final class PrerenderedUrlParams {
        public final CustomTabsSessionToken mSession;
        public final WebContents mWebContents;
        public final String mUrl;
        public final String mReferrer;
        public final Bundle mExtras;

        PrerenderedUrlParams(CustomTabsSessionToken session, WebContents webContents,
                String url, String referrer, Bundle extras) {
            mSession = session;
            mWebContents = webContents;
            mUrl = url;
            mReferrer = referrer;
            mExtras = extras;
        }
    }

    @VisibleForTesting
    PrerenderedUrlParams mPrerender;
    protected final Application mApplication;
    protected final ClientManager mClientManager;
    private final boolean mLogRequests;
    private final AtomicBoolean mWarmupHasBeenCalled = new AtomicBoolean();
    private final AtomicBoolean mWarmupHasBeenFinished = new AtomicBoolean();
    private ExternalPrerenderHandler mExternalPrerenderHandler;
    private WebContents mSpareWebContents;
    // TODO(lizeb): Remove once crbug.com/630303 is fixed.
    private boolean mPageLoadMetricsEnabled;

    /**
     * DO NOT CALL
     * Public to be instanciable from {@link ChromeApplication}. This is however
     * intended to be private.
     */
    public CustomTabsConnection(Application application) {
        super();
        mApplication = application;
        mClientManager = new ClientManager(mApplication);
        mLogRequests = CommandLine.getInstance().hasSwitch(LOG_SERVICE_REQUESTS);
    }

    /**
     * @return The unique instance of ChromeCustomTabsConnection.
     */
    @SuppressFBWarnings("BC_UNCONFIRMED_CAST")
    public static CustomTabsConnection getInstance(Application application) {
        if (sInstance.get() == null) {
            ChromeApplication chromeApplication = (ChromeApplication) application;
            chromeApplication.initCommandLine();
            sInstance.compareAndSet(null, chromeApplication.createCustomTabsConnection());
        }
        return sInstance.get();
    }

    /**
     * If service requests logging is enabled, logs that a call was made.
     *
     * No rate-limiting, can be spammy if the app is misbehaved.
     *
     * @param name Call name to log.
     * @param success Whether the call was successful.
     */
    void logCall(String name, boolean success) {
        if (mLogRequests) {
            Log.w(TAG, "%s = %b, Calling UID = %d", name, success, Binder.getCallingUid());
        }
    }

    public boolean newSession(CustomTabsSessionToken session) {
        boolean success = newSessionInternal(session);
        logCall("newSession()", success);
        return success;
    }

    private boolean newSessionInternal(CustomTabsSessionToken session) {
        ClientManager.DisconnectCallback onDisconnect = new ClientManager.DisconnectCallback() {
            @Override
            public void run(CustomTabsSessionToken session) {
                cancelPrerender(session);
            }
        };
        return mClientManager.newSession(session, Binder.getCallingUid(), onDisconnect);
    }

    /** Warmup activities that should only happen once. */
    @SuppressFBWarnings("DM_EXIT")
    private static void initializeBrowser(final Application app) {
        ThreadUtils.assertOnUiThread();
        try {
            ChromeBrowserInitializer.getInstance(app).handleSynchronousStartup();
        } catch (ProcessInitException e) {
            Log.e(TAG, "ProcessInitException while starting the browser process.");
            // Cannot do anything without the native library, and cannot show a
            // dialog to the user.
            System.exit(-1);
        }
        final Context context = app.getApplicationContext();
        final ChromeApplication chrome = (ChromeApplication) context;
        ChildProcessCreationParams.set(chrome.getChildProcessCreationParams());
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                ChildProcessLauncher.warmUp(context);
                return null;
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        ChromeBrowserInitializer.initNetworkChangeNotifier(context);
        WarmupManager.getInstance().initializeViewHierarchy(
                context, R.layout.custom_tabs_control_container);
    }

    public boolean warmup(long flags) {
        boolean success = warmupInternal(true);
        logCall("warmup()", success);
        return success;
    }

    /**
     * @return Whether {@link CustomTabsConnection#warmup(long)} has been called.
     */
    public static boolean hasWarmUpBeenFinished(Application application) {
        return getInstance(application).mWarmupHasBeenFinished.get();
    }

    /**
     * Starts as much as possible in anticipation of a future navigation.
     *
     * @param mayCreatesparewebcontents true if warmup() can create a spare renderer.
     * @return true for success.
     */
    private boolean warmupInternal(final boolean mayCreateSpareWebContents) {
        // Here and in mayLaunchUrl(), don't do expensive work for background applications.
        if (!isCallerForegroundOrSelf()) return false;
        mClientManager.recordUidHasCalledWarmup(Binder.getCallingUid());
        final boolean initialized = !mWarmupHasBeenCalled.compareAndSet(false, true);
        // The call is non-blocking and this must execute on the UI thread, post a task.
        ThreadUtils.postOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (!initialized) initializeBrowser(mApplication);
                if (mayCreateSpareWebContents && mPrerender == null && !SysUtils.isLowEndDevice()) {
                    createSpareWebContents();
                }
                mWarmupHasBeenFinished.set(true);
            }
        });
        return true;
    }

    /** Creates a spare {@link WebContents}, if none exists. */
    private void createSpareWebContents() {
        ThreadUtils.assertOnUiThread();
        if (mSpareWebContents != null) return;
        mSpareWebContents = WebContentsFactory.createWebContentsWithWarmRenderer(false, false);
    }

    /** @return the URL converted to string, or null if it's invalid. */
    private static String checkAndConvertUri(Uri uri) {
        if (uri == null) return null;
        // Don't do anything for unknown schemes. Not having a scheme is allowed, as we allow
        // "www.example.com".
        String scheme = uri.normalizeScheme().getScheme();
        boolean allowedScheme = scheme == null || scheme.equals("http") || scheme.equals("https");
        if (!allowedScheme) return null;
        return uri.toString();
    }

    /**
     * High confidence mayLaunchUrl() call, that is:
     * - Tries to prerender if possible.
     * - An empty URL cancels the current prerender if any.
     * - If prerendering is not possible, makes sure that there is a spare renderer.
     */
    private void highConfidenceMayLaunchUrl(CustomTabsSessionToken session,
            int uid, String url, Bundle extras, List<Bundle> otherLikelyBundles) {
        ThreadUtils.assertOnUiThread();
        if (TextUtils.isEmpty(url)) {
            cancelPrerender(session);
            return;
        }
        url = DataReductionProxySettings.getInstance().maybeRewriteWebliteUrl(url);
        boolean noPrerendering =
                extras != null ? extras.getBoolean(NO_PRERENDERING_KEY, false) : false;
        WarmupManager.getInstance().maybePreconnectUrlAndSubResources(
                Profile.getLastUsedProfile(), url);
        boolean didStartPrerender = false;
        if (!noPrerendering && mayPrerender(session)) {
            didStartPrerender = prerenderUrl(session, url, extras, uid);
        }
        preconnectUrls(otherLikelyBundles);
        if (!didStartPrerender) createSpareWebContents();
    }

    /**
     * Low confidence mayLaunchUrl() call, that is:
     * - Preconnects to the ordered list of URLs.
     * - Makes sure that there is a spare renderer.
     */
    @VisibleForTesting
    boolean lowConfidenceMayLaunchUrl(List<Bundle> likelyBundles) {
        ThreadUtils.assertOnUiThread();
        if (!preconnectUrls(likelyBundles)) return false;
        createSpareWebContents();
        return true;
    }

    private boolean preconnectUrls(List<Bundle> likelyBundles) {
        boolean atLeastOneUrl = false;
        if (likelyBundles == null) return false;
        WarmupManager warmupManager = WarmupManager.getInstance();
        Profile profile = Profile.getLastUsedProfile();
        for (Bundle bundle : likelyBundles) {
            Uri uri;
            try {
                uri = IntentUtils.safeGetParcelable(bundle, CustomTabsService.KEY_URL);
            } catch (ClassCastException e) {
                continue;
            }
            String url = checkAndConvertUri(uri);
            if (url != null) {
                warmupManager.maybePreconnectUrlAndSubResources(profile, url);
                atLeastOneUrl = true;
            }
        }
        return atLeastOneUrl;
    }

    public boolean mayLaunchUrl(CustomTabsSessionToken session, Uri url, Bundle extras,
            List<Bundle> otherLikelyBundles) {
        boolean success = mayLaunchUrlInternal(session, url, extras, otherLikelyBundles);
        logCall("mayLaunchUrl()", success);
        return success;
    }

    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;
    }

    public Bundle extraCommand(String commandName, Bundle args) {
        return null;
    }

    /** @return a spare WebContents, or null. */
    WebContents takeSpareWebContents() {
        ThreadUtils.assertOnUiThread();
        WebContents result = mSpareWebContents;
        mSpareWebContents = null;
        return result;
    }

    private void destroySpareWebContents() {
        ThreadUtils.assertOnUiThread();
        WebContents webContents = takeSpareWebContents();
        if (webContents != null) webContents.destroy();
    }

    public boolean updateVisuals(final CustomTabsSessionToken session, Bundle bundle) {
        final Bundle actionButtonBundle = IntentUtils.safeGetBundle(bundle,
                CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE);
        boolean result = true;
        if (actionButtonBundle != null) {
            final int id = IntentUtils.safeGetInt(actionButtonBundle, CustomTabsIntent.KEY_ID,
                    CustomTabsIntent.TOOLBAR_ACTION_BUTTON_ID);
            final Bitmap bitmap = CustomButtonParams.parseBitmapFromBundle(actionButtonBundle);
            final String description = CustomButtonParams
                    .parseDescriptionFromBundle(actionButtonBundle);
            if (bitmap != null && description != null) {
                try {
                    result &= ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
                        @Override
                        public Boolean call() throws Exception {
                            return CustomTabActivity.updateCustomButton(session, id,
                                    bitmap, description);
                        }
                    });
                } catch (ExecutionException e) {
                    result = false;
                }
            }
        }
        if (bundle.containsKey(CustomTabsIntent.EXTRA_REMOTEVIEWS)) {
            final RemoteViews remoteViews = IntentUtils.safeGetParcelable(bundle,
                    CustomTabsIntent.EXTRA_REMOTEVIEWS);
            final int[] clickableIDs = IntentUtils.safeGetIntArray(bundle,
                    CustomTabsIntent.EXTRA_REMOTEVIEWS_VIEW_IDS);
            final PendingIntent pendingIntent = IntentUtils.safeGetParcelable(bundle,
                    CustomTabsIntent.EXTRA_REMOTEVIEWS_PENDINGINTENT);
            try {
                result &= ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
                    @Override
                    public Boolean call() throws Exception {
                        return CustomTabActivity.updateRemoteViews(session,
                                remoteViews, clickableIDs, pendingIntent);
                    }
                });
            } catch (ExecutionException e) {
                result = false;
            }
        }
        return result;
    }

    /**
     * Registers a launch of a |url| for a given |session|.
     *
     * This is used for accounting.
     */
    void registerLaunch(CustomTabsSessionToken session, String url) {
        mClientManager.registerLaunch(session, url);
    }

    /**
     * Transfers a prerendered WebContents if one exists.
     *
     * This resets the internal WebContents; a subsequent call to this method
     * returns null. Must be called from the UI thread.
     * If a prerender exists for a different URL with the same sessionId or with
     * a different referrer, then this is treated as a mispredict from the
     * client application, and cancels the previous prerender. This is done to
     * avoid keeping resources laying around for too long, but is subject to a
     * race condition, as the following scenario is possible:
     * The application calls:
     * 1. mayLaunchUrl(url1) <- IPC
     * 2. loadUrl(url2) <- Intent
     * 3. mayLaunchUrl(url3) <- IPC
     * If the IPC for url3 arrives before the intent for url2, then this methods
     * cancels the prerender for url3, which is unexpected. On the other
     * hand, not cancelling the previous prerender leads to wasted resources, as
     * a WebContents is lingering. This can be solved by requiring applications
     * to call mayLaunchUrl(null) to cancel a current prerender before 2, that
     * is for a mispredict.
     *
     * Note that this methods accepts URLs that don't exactly match the initially
     * prerendered URL. More precisely, the #fragment is ignored. In this case,
     * the client needs to navigate to the correct URL after the WebContents
     * swap. This can be tested using {@link UrlUtilities#urlsFragmentsDiffer()}.
     *
     * @param session The Binder object identifying a session.
     * @param url The URL the WebContents is for.
     * @param referrer The referrer to use for |url|.
     * @return The prerendered WebContents, or null.
     */
    WebContents takePrerenderedUrl(CustomTabsSessionToken session, String url, String referrer) {
        ThreadUtils.assertOnUiThread();
        if (mPrerender == null || session == null || !session.equals(mPrerender.mSession)) {
            return null;
        }
        WebContents webContents = mPrerender.mWebContents;
        String prerenderedUrl = mPrerender.mUrl;
        String prerenderReferrer = mPrerender.mReferrer;
        if (referrer == null) referrer = "";
        boolean ignoreFragments = mClientManager.getIgnoreFragmentsForSession(session);
        boolean urlsMatch = TextUtils.equals(prerenderedUrl, url)
                || (ignoreFragments
                        && UrlUtilities.urlsMatchIgnoringFragments(prerenderedUrl, url));
        WebContents result = null;
        if (urlsMatch && TextUtils.equals(prerenderReferrer, referrer)) {
            result = webContents;
            mPrerender = null;
        } else {
            cancelPrerender(session);
        }
        if (!mClientManager.usesDefaultSessionParameters(session) && webContents != null) {
            RecordHistogram.recordBooleanHistogram(
                    "CustomTabs.NonDefaultSessionPrerenderMatched", result != null);
        }

        return result;
    }

    /** Returns the URL prerendered for a session, or null. */
    String getPrerenderedUrl(CustomTabsSessionToken session) {
        if (mPrerender == null || session == null || !session.equals(mPrerender.mSession)) {
            return null;
        }
        return mPrerender.mUrl;
    }

    /** See {@link ClientManager#getReferrerForSession(CustomTabsSessionToken)} */
    public Referrer getReferrerForSession(CustomTabsSessionToken session) {
        return mClientManager.getReferrerForSession(session);
    }

    /** @see ClientManager#shouldHideDomainForSession(CustomTabsSessionToken) */
    public boolean shouldHideDomainForSession(CustomTabsSessionToken session) {
        return mClientManager.shouldHideDomainForSession(session);
    }

    /** @see ClientManager#shouldPrerenderOnCellularForSession(CustomTabsSessionToken) */
    public boolean shouldPrerenderOnCellularForSession(CustomTabsSessionToken session) {
        return mClientManager.shouldPrerenderOnCellularForSession(session);
    }

    /** See {@link ClientManager#getClientPackageNameForSession(CustomTabsSessionToken)} */
    public String getClientPackageNameForSession(CustomTabsSessionToken session) {
        return mClientManager.getClientPackageNameForSession(session);
    }

    @VisibleForTesting
    void setIgnoreUrlFragmentsForSession(CustomTabsSessionToken session, boolean value) {
        mClientManager.setIgnoreFragmentsForSession(session, value);
    }

    @VisibleForTesting
    boolean getIgnoreUrlFragmentsForSession(CustomTabsSessionToken session) {
        return mClientManager.getIgnoreFragmentsForSession(session);
    }

    @VisibleForTesting
    void setShouldPrerenderOnCellularForSession(CustomTabsSessionToken session, boolean value) {
        mClientManager.setPrerenderCellularForSession(session, value);
    }

    /**
     * Extracts the creator package name from the intent.
     * @param intent The intent to get the package name from.
     * @return the package name which can be null.
     */
    String extractCreatorPackage(Intent intent) {
        return null;
    }

    /**
     * Shows a toast about any possible sign in issues encountered during custom tab startup.
     * @param session The session that corresponding custom tab is assigned.
     * @param intent The intent that launched the custom tab.
     */
    void showSignInToastIfNecessary(CustomTabsSessionToken session, Intent intent) { }

    /**
     * Sends a callback using {@link CustomTabsCallback} about the first run result if necessary.
     * @param intent The initial VIEW intent that initiated first run.
     * @param resultOK Whether first run was successful.
     */
    public void sendFirstRunCallbackIfNecessary(Intent intent, boolean resultOK) { }

    /**
     * Notifies the application of a navigation event.
     *
     * Delivers the {@link CustomTabsConnectionCallback#onNavigationEvent}
     * callback to the application.
     *
     * @param session The Binder object identifying the session.
     * @param navigationEvent The navigation event code, defined in {@link CustomTabsCallback}
     * @return true for success.
     */
    boolean notifyNavigationEvent(CustomTabsSessionToken session, int navigationEvent) {
        CustomTabsCallback callback = mClientManager.getCallbackForSession(session);
        if (callback == null) return false;
        try {
            callback.onNavigationEvent(navigationEvent, null);
        } catch (Exception e) {
            // Catching all exceptions is really bad, but we need it here,
            // because Android exposes us to client bugs by throwing a variety
            // of exceptions. See crbug.com/517023.
            return false;
        }
        return true;
    }

    // TODO(lizeb): Remove once crbug.com/630303 is fixed.
    @VisibleForTesting
    void enablePageLoadMetricsCallbacks() {
        mPageLoadMetricsEnabled = true;
    }

    /**
     * Notifies the application of a page load metric.
     *
     * TODD(lizeb): Move this to a proper method in {@link CustomTabsCallback} once one is
     * available.
     *
     * @param session Session identifier.
     * @param metricName Name of the page load metric.
     * @param offsetMs Offset in ms from navigationStart.
     */
    boolean notifyPageLoadMetric(CustomTabsSessionToken session, String metricName, long offsetMs) {
        CustomTabsCallback callback = mClientManager.getCallbackForSession(session);
        if (!mPageLoadMetricsEnabled) return false;
        if (callback == null) return false;
        Bundle args = new Bundle();
        args.putLong(metricName, offsetMs);
        try {
            callback.extraCallback(PAGE_LOAD_METRICS_CALLBACK, args);
        } catch (Exception e) {
            // Pokemon exception handling, see above and crbug.com/517023.
            return false;
        }
        return true;
    }

    /**
     * Keeps the application linked with a given session alive.
     *
     * The application is kept alive (that is, raised to at least the current
     * process priority level) until {@link dontKeepAliveForSessionId()} is
     * called.
     *
     * @param session The Binder object identifying the session.
     * @param intent Intent describing the service to bind to.
     * @return true for success.
     */
    boolean keepAliveForSession(CustomTabsSessionToken session, Intent intent) {
        return mClientManager.keepAliveForSession(session, intent);
    }

    /**
     * Lets the lifetime of the process linked to a given sessionId be managed normally.
     *
     * Without a matching call to {@link keepAliveForSessionId}, this is a no-op.
     *
     * @param session The Binder object identifying the session.
     */
    void dontKeepAliveForSession(CustomTabsSessionToken session) {
        mClientManager.dontKeepAliveForSession(session);
    }

    /**
     * @return the CPU cgroup of a given process, identified by its PID, or null.
     */
    @VisibleForTesting
    static String getSchedulerGroup(int pid) {
        // Android uses two cgroups for the processes: the root cgroup, and the
        // "/bg_non_interactive" one for background processes. The list of
        // cgroups a process is part of can be queried by reading
        // /proc/<pid>/cgroup, which is world-readable.
        String cgroupFilename = "/proc/" + pid + "/cgroup";
        // Reading from /proc does not cause disk IO, but strict mode doesn't like it.
        // crbug.com/567143
        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
        try {
            FileReader fileReader = new FileReader(cgroupFilename);
            BufferedReader reader = new BufferedReader(fileReader);
            try {
                String line = null;
                while ((line = reader.readLine()) != null) {
                    // line format: 2:cpu:/bg_non_interactive
                    String fields[] = line.trim().split(":");
                    if (fields.length == 3 && fields[1].equals("cpu")) return fields[2];
                }
            } finally {
                reader.close();
            }
        } catch (IOException e) {
            return null;
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
        return null;
    }

    private static boolean isBackgroundProcess(int pid) {
        String schedulerGroup = getSchedulerGroup(pid);
        // "/bg_non_interactive" is from L MR1, "/apps/bg_non_interactive" before.
        return "/bg_non_interactive".equals(schedulerGroup)
                || "/apps/bg_non_interactive".equals(schedulerGroup);
    }

    /**
     * @return true when inside a Binder transaction and the caller is in the
     * foreground or self. Don't use outside a Binder transaction.
     */
    private boolean isCallerForegroundOrSelf() {
        int uid = Binder.getCallingUid();
        if (uid == Process.myUid()) return true;
        // Starting with L MR1, AM.getRunningAppProcesses doesn't return all the
        // processes. We use a workaround in this case.
        boolean useWorkaround = true;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
            ActivityManager am =
                    (ActivityManager) mApplication.getSystemService(Context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningAppProcessInfo> running = am.getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo rpi : running) {
                boolean matchingUid = rpi.uid == uid;
                boolean isForeground = rpi.importance
                        == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
                useWorkaround &= !matchingUid;
                if (matchingUid && isForeground) return true;
            }
        }
        return useWorkaround ? !isBackgroundProcess(Binder.getCallingPid()) : false;
    }

    @VisibleForTesting
    void cleanupAll() {
        ThreadUtils.assertOnUiThread();
        mClientManager.cleanupAll();
    }

    /**
     * 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);
            }
        });
    }

    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);
    }

    /** Cancels a prerender for a given session, or any session if null. */
    void cancelPrerender(CustomTabsSessionToken session) {
        ThreadUtils.assertOnUiThread();
        if (mPrerender != null && (session == null || session.equals(mPrerender.mSession))) {
            mExternalPrerenderHandler.cancelCurrentPrerender();
            mPrerender.mWebContents.destroy();
            mPrerender = null;
        }
    }

    /**
     * Tries to request a prerender for a given URL.
     *
     * @param session Session the request comes from.
     * @param url URL to prerender.
     * @param extras extra parameters.
     * @param uid UID of the caller.
     * @return true if a prerender has been initiated.
     */
    private boolean prerenderUrl(
            CustomTabsSessionToken session, String url, Bundle extras, int uid) {
        ThreadUtils.assertOnUiThread();
        // Ignores mayPrerender() for an empty URL, since it cancels an existing prerender.
        if (!mayPrerender(session) && !TextUtils.isEmpty(url)) return false;
        if (!mWarmupHasBeenCalled.get()) return false;
        // Last one wins and cancels the previous prerender.
        cancelPrerender(null);
        if (TextUtils.isEmpty(url)) return false;
        boolean throttle = !shouldPrerenderOnCellularForSession(session);
        if (throttle && !mClientManager.isPrerenderingAllowed(uid)) return false;

        // A prerender will be requested. Time to destroy the spare WebContents.
        destroySpareWebContents();

        Intent extrasIntent = new Intent();
        if (extras != null) extrasIntent.putExtras(extras);
        if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) return false;
        if (mExternalPrerenderHandler == null) {
            mExternalPrerenderHandler = new ExternalPrerenderHandler();
        }
        Point contentSize = ExternalPrerenderHandler.estimateContentSize(mApplication, true);
        Context context = mApplication.getApplicationContext();
        String referrer = IntentHandler.getReferrerUrlIncludingExtraHeaders(extrasIntent, context);
        if (referrer == null && getReferrerForSession(session) != null) {
            referrer = getReferrerForSession(session).getUrl();
        }
        if (referrer == null) referrer = "";
        WebContents webContents = mExternalPrerenderHandler.addPrerender(
                Profile.getLastUsedProfile(), url, referrer, contentSize.x, contentSize.y,
                shouldPrerenderOnCellularForSession(session));
        if (webContents == null) return false;
        if (throttle) mClientManager.registerPrerenderRequest(uid, url);
        mPrerender = new PrerenderedUrlParams(session, webContents, url, referrer, extras);

        RecordHistogram.recordBooleanHistogram("CustomTabs.PrerenderSessionUsesDefaultParameters",
                mClientManager.usesDefaultSessionParameters(session));

        return true;
    }

    @VisibleForTesting
    void resetThrottling(Context context, int uid) {
        mClientManager.resetThrottling(uid);
    }

    @VisibleForTesting
    void ban(Context context, int uid) {
        mClientManager.ban(uid);
    }
}

redpajama_set_name: RedPajamaGithub


Set in two hectares of the British countryside, Laverstoke Mill, Hampshire, is the new home of BOMBAY SAPPHIRE®, the world's fastest-growing major gin brand by volume and value*. It was the renovated paper mill that provided the inspiration behind the Bombay Sapphire Limited Edition Bottle; an outstanding packaging development that has been awarded the 'Best Bottle in Glass', at the 2014 World Beverage Awards.
The elaborate project took packaging designers on a creative journey that lasted over 12 months. The brief was simple: reflect the soul, craftsmanship and essence of the prestigious brand. The result: a stunning limited edition glass bottle that creatively represents the state of the art production facility and visitor centre, located on the River Test.
Stretching the boundaries of structural design and decorative printing, the Limited Edition Bottle features illustrations of Laverstoke Mill by award winning British illustrator Si Scott, bringing to life the brand story and maintaining the iconic blue colour, with which the brand is now synonymous.
The global marketing team at Bombay Sapphire worked closely with design agency, Webb de Vlam, and packaging manufacturer, Ardagh Group, to produce the sophisticated design, making sure that the bottles would run smoothly on the production, decoration and filling lines.
"We successfully executed a number of highly intricate features on the bottle, working in close partnership with the design agency and other packaging suppliers, as well our in-house decoration centre.
Furthermore, the continuous print around the facetted corners meant that the ceramic printing process would not provide the required level of detail required. Trials were carried out using alternative decoration techniques and finally, using ceramic water slide transfers, that offer a superior print quality, a solution was found.
To achieve the high level of accuracy and avoid any imperfections during the firing process, the transfers were applied by hand, a true crafted finish to a distinctive design. What's more, the self-adhesive metal band, set into the shaped label recess, features images of the brand's iconic ten botanicals. A bank note is also detailed; a nod to the narrative behind Laverstoke Mill.


text:
Q: ios how to show activity indicator during fetching the data from rss feed in UITableView? I am trying to populating the data from a rss feed. This process take some time. During this delay I want to display a activity indicator and hide it when data is loaded.  how can I do it? Please help

A: *

*Add a UIActivityIndicator subview.

*During the start of loading make it visible. You can disable all user interaction if you want and also can apply a semitransparent view to let users know that interaction is disabled.

*Start asynchronous loading of data. You must do asynchronous loading. In synchronous loading everything, including UI update, is blocked. So indicator won't animate in that case.

*When data loading is completed stop the connecting animation. And enable the interaction if disabled earlier.

And that's all.

redpajama_set_name: RedPajamaStackExchange


text:
Das Neumarkt (vormals: Theater Neumarkt bzw. Theater am Neumarkt) ist ein Ensembletheater am gleichnamigen Platz in der Altstadt von Zürich. Es steht seit 1966 mit seinem Profil für innovatives und experimentelles Theater. Unter dem Motto «LOVE PLAY FIGHT», in drei seit 2019 eingeführten Sparten Playground, Theater und Akademie, erforscht die kollektive Leitung bestehend aus Hayat Erdoğan, Tine Milz und Julia Reichert und ein festes Team aus knapp 50 Mitarbeitern aus Kunst, Technik und Verwaltung neue Formen und Erzählweisen. Mit den drei Sparten möchte das Leitungsteam «eine barrierefreie Denkanstalt, einen Spielplatz der Ideen und Inspirationen, ein Labor für ästhetische Experimente etablieren und das bewegliche Profil des Neumarkt lebendig halten».

Der flexibel nutzbare Theatersaal des Neumarkts bietet, je nach Raumsituation, bis zu 170 Zuschauern Platz. Eine kleine Nebenspielstätte, nach ihrer Lage Chorgasse genannt, verfügt über bis zu 40 Plätze. Rechtsträger des Theaters ist die Theater am Neumarkt AG, die mehrheitlich im Besitz von Stadt und Kanton Zürich ist.

Geschichte
Das an den Bilgeriturm angebaute Haus Neumarkt 5 in Zürich, in dem heute das Theater untergebracht ist, wurde 1742 von David Morf für die Zunft der Schuhmacher errichtet beziehungsweise umgebaut, aber nur etwa 50 Jahre als Gesellschaftshaus genutzt. Nach der Französischen Revolution wurde das Haus verkauft, beherbergte bis 1877 eine Töchterschule und ging 1888 in den Besitz des deutschen Arbeiterbildungsvereins Eintracht Zürich über, wo das Gebäude zu einem wichtigen Treffpunkt der Arbeiterbewegung in Zürich wurde. Unter anderem hielten sich Leo Trotzki und Wladimir I. Lenin, der während seines Zürcher Exils in der nahe gelegenen Spiegelgasse wohnte, hier immer wieder auf.

Im März 1921 wurde Haus die Kommunistische Partei der Schweiz gegründet. 1933 kam es in den Besitz der Stadt Zürich. Von 1948 bis 1960 veranstaltete die Schwulenorganisation DER KREIS im Theatersaal des ehemaligen Restaurants «Eintracht» am Neumarkt 5 grosse festliche Anlässe. Auch heute ist neben dem Theater ein Restaurantbetrieb im Gebäude, das seit 1956 auch Sitz der Hottingerzunft ist. Für Zunftanlässe wird der Theatersaal zweimal im Jahr geräumt.

In den 1960er Jahren kam Bewegung in die Zürcher Theaterszene, die sich dem Modernen und Experimentellen langsam öffnete. 1965 wurde unter der Leitung der Verwaltungsabteilung des Zürcher Stadtpräsidenten im Haus ein Gastspielbetrieb eingerichtet. Am 12. Januar 1966 wurde das Theater am Neumarkt unter der künstlerischen Direktion von Felix Rellstab offiziell gegründet. Eröffnet wurde mit Das Gartenfest, dem Erstlingswerk des damals jungen tschechischen Autors und späteren Staatspräsidenten Václav Havel. Auf der Bühne agierten Silvia Mey, Nelly Rademacher, Irmgard Paulis, Martin Kempf, Mathias Gnädinger, Peter Oehme, Giovanni Früh, Hermann Brand, Paul Lohr und Meinhard Zanger. Schweizer Autoren (u. a. Walter Vogt) sowie Werke von Sławomir Mrożek, Harold Pinter, Samuel Beckett u. a. wurden aufgeführt.  Eugène Ionesco, heute der meistgespielte französische Dramatiker ausserhalb Frankreichs, inszenierte sein Stück selbst.

1971 übernahm Horst Zankl die Direktion. Die revolutionäre Einführung eines Selbst- und Mitbestimmungssystems, bei dem alle Mitarbeiter des Theaters über den Spielplan und die Belange des Theaters abstimmten, machte das Haus im ganzen deutschsprachigen Raum bekannt. Zankl eröffnete seine Saison mit Peter Handkes Ritt über den Bodensee und brachte Fleisser, Kroetz, Valentin, Horváth, Walser und Weiss auf die Bühne.

Unter der Direktion von Luis Bolliger (1975 bis 1979) gab es zwölf Schweizer Erst- und Uraufführungen. Von 1979 bis 1983 leitete Helmut Palitsch das Theater. Auf dem Spielplan standen Brecht, Beckett, Horváth, Brasch und Ulrike Meinhofs Stück Bambule.

In den Jahren 1983 bis 1988 prägten Autoren aus der Schweiz, aus der DDR sowie Klassiker der Moderne den Spielplan. Unter der Direktion von Peter Schweiger etablierten sich Sonntagsmatineen zu laufenden Produktionen sowie zu aktuellem tagespolitischen Geschehen. Die deutsche Regisseurin Gudrun Orsky begann ihre Direktionszeit 1989. Sie eröffnete programmatisch mit Clara S. von Elfriede Jelinek. 1993 übernahmen Volker Hesse und Stephan Müller das Haus. Die Inszenierungen Top Dogs von Urs Widmer und Die Wahlverwandtschaften von Goethe fanden internationale Anerkennung und wurden zum Berliner Theatertreffen eingeladen.

Ab der Spielzeit 1999/2000 leiteten Crescentia Dünßer und Otto Kukla das Theater am Neumarkt. Sie präsentierten ein junges Ensemble mit jungen Regisseuren und Autoren. Die Produktionen Memory und Steinasche wurden nach Teheran und Stabat Mater/Unscheinbare Veränderungen nach Moskau und St. Petersburg eingeladen. Ab der Spielzeit 2004/2005 war Wolfgang Reiter Direktor. Neben der Pflege zeitgenössischer Dramatik fanden auch neue, insbesondere vom Musik- und Tanztheater inspirierte Formen ihren Platz im Spielplan.

Von 2008 an leiteten die beiden Schweizer Regisseure Barbara Weber und Rafael Sanchez das Theater Neumarkt. Neben den Co-Direktoren inszenierten seither u. a. Laurent Chétouane, Martin Kušej, Stephan Müller und Christoph Schlingensief. Von 2013 bis 2019 leiteten Peter Kastenmüller und Ralf Fiedler das Haus. Mit rund 18'000 verkauften Eintrittskarten lag das Theater laut NZZ in der Spielzeit 2014/2015 im Schnitt der letzten fünf Jahre. Die Inszenierung Jakobs Ross von Silvia Tschui (Regie: Peter Kastenmüller) wurde 2015 zum zweiten Schweizer Theatertreffen eingeladen, im Jahr 2019 Café Populaire von Nora Abdel-Maksoud.

Seit Beginn der Spielzeit 2019/2020 leiten Hayat Erdoğan, Tine Milz und Julia Reichert das Haus als Kollektiv. Die Intendanz verschreibt sich einem erweiterten Theaterbegriff mittels drei neu begründeter Sparten: Theater, Playground und Akademie. Damit wird die Tradition des Hauses als Ensembletheater und Ort fürs künstlerische Experiment fortgeführt.

Direktion
 Felix Rellstab, 1966–1971
 Horst Zankl, 1971–1975
 Luis Bolliger, 1975–1979
 Helmut Palitsch, 1979–1983
 Peter Schweiger, 1983–1989
 Gudrun Orsky, 1989–1993
 Volker Hesse und Stephan Müller, 1993–1999
 Crescentia Dünsser und Otto Kukla, 1999–2004
 Wolfgang Reiter, 2004–2008
 Barbara Weber & Rafael Sanchez, 2008–2013
 Peter Kastenmüller & Ralf Fiedler (2013–2019)
 Hayat Erdoğan, Tine Milz & Julia Reichert, seit 2019

Literatur
 Theater am Neumarkt: 1983-1989, eine Dokumentation. Mit Beiträgen von Wolfram Malte Fues, Redaktion Willi Händler. Theater am Neumarkt, Zürich 1989, .
 Ralf Fiedler, Inga Schonlau, Benjamin von Wyl: Wohin mit dem ganzen Idealismus. Theater Neumarkt Zürich 1966-2066. Theater der Zeit, Berlin 2016, ISBN 978-3-95749-065-0.

Weblinks

 Website des Theaters Neumarkt
 https://www.srf.ch/kultur/buehne/auftakt-am-theater-neumarkt-in-der-schweiz-gibt-es-einiges-zu-reparieren
 https://www.srf.ch/kultur/buehne/zuercher-theater-das-ding-mit-der-diversitaet
 https://www.woz.ch/-9f8d
 https://www.tagblatt.ch/newsticker/schweiz/lieben-spielen-und-streiten-am-zurcher-neumarkt-ld.1123040
 https://www.nzz.ch/feuilleton/frauen-an-der-front-ld.1339818

Belege

Zurich, Theater Neumarkt
Schauspielhaus
Zunfthaus

redpajama_set_name: RedPajamaWikipedia


text:
Speaker Among, CAF president Motsepe discuss future of sports in Uganda
Home Football
In his remarks, Motsepe welcomed and encouraged Uganda's bid to co-host AFCON 2027 with Tanzania, saying this would be important for East Africa since this would be the region's first time hosting the tournament.
in Football, News
The Speaker of Parliament, Anita Among on Friday morning held discussions with the CAF president, Dr Patrice Motsepe on the future of sports in Uganda.
This was during a meeting between Among and CAF delegation led by Motsepe at the Speaker's office.
In her remarks, Among briefed the CAF delegation about Uganda's bid to co-host the 2027 AFCON with Tanzania.
Among emphasized that as a country, there is a need to start looking at football as a way of supporting the livelihood of young people and the business community.
"As a country with abundant talent, we need to build networks that create opportunities for our young people. As Parliament, we shall place sports at the centre of our priorities in the coming years," Among said.
"As the president of CAF, I must say that I would personally not just welcome but encourage a joint hosting between these two countries because it will make a huge contribution to football development in Uganda and Tanzania," Motsepe said.
The CAF president revealed that so far, about 9 countries have expressed interest in hosting AFCON 2027.
However, he said, it would be important if the East Africa region got the opportunity to host the tournament in 2027.
Motsepe who arrived on Thursday is in the country for a two-day official visit. He is expected to meet President Museveni, Friday afternoon.
ShareTweetSendSendShare
ICC T20 World Cup Global Qualifiers: Uganda finish fifth

redpajama_set_name: RedPajamaCommonCrawl


A group of Worthing Raiders academy players had a weekend to remember as they travelled to Paris to take on Stade Francais.
The travelling Raiders contingent took a mix of under-12 and under-13 club members.
Stade Francais provided top-quality opposition, with youngsters from the French Premiership academy team training three times a week.
The match was played in three 20-minute periods as Raiders academy players took on Stade Francais' 'minimes elite under-14s'.
Raiders made a blistering start, scoring three tries through Hamish Williams, Daniel Seymour and Jude Raza all inside the opening 20 minutes.
The French side pushed hard in the two 20-minute periods that followed but Raiders' academy team held on for a 15-0 victory.
A club official said a huge well done to all of the Raiders academy players involved in the trip.
It was a great experience and all players will have special memories for years to come. Playing older players in Stade Francais, adapting to French rules but more so the way they pulled together as a squad displaying skills and maturity well beyond their young years.


text:
King Kong (2005) – Movie Review
September 16, 2018 September 16, 2018 by thequantumranger, posted in Film Reviews
King Kong is a 2005 film directed by Peter Jackson and it stars Naomi Watts, Adrien Brody, Jack Black, Thomas Kretschmann, Colin Hanks, Andy Serkis, Kyle Chandler, Evan Parke, and Jamie Bell. The film is about a film crew that goes to the mysterious Skull Island for filming where they encounter Kong who becomes attracted to lead actress Ann Darrow. The film did well at the box office and it has won 3 Academy Awards!
Opening Thoughts:
Around 2005, I remember seeing the 2006 Academy Awards and saw King Kong earning a couple of awards. I was really interested in seeing the film once I saw it won a couple of Oscars. My mom got the DVD for me so my entire family and I has seen it many times. I grew up watching this movie and I believe this is the first longest movie that I grew up watching since the film is about 3 hours. I've seen the film countless of times and still to this day I appreciate and love the film. This is the only Peter Jackson movie that I grew up watching. I did not grow up watching The Lord of the Rings unfortunately. But I love that franchise as well no doubt. But The Lord of the Rings will be talked about more when the time comes with those reviews or anything related to the franchise. I got the 4k bluray of King Kong recently, so I'm looking forward to seeing the film again and see how it looks in 4k!
The Positives:
The main great thing about the 2005 King Kong movie is the story. In the middle act of the film, you see Kong being attracted to Ann Darrow (Naomi Watts) and he does anything he can to protect her from danger. The fighting scenes between Kong and the T-Rex at Skull Island is really top notch. The last act of the film where Kong is looking for Ann Darrow in 1930's Manhattan and spending time with her on top of the Empire State Building were beautiful moments that made the film come to life.
There was great character development with Ann, Carl Denham (Jack Black) and even Kong. At first you see Ann being scared and does not want anything to do with Kong when she is caputured by him. However as the film progresses, you see she also gets drawn to Kong and she feels good being around him. Carl Denham who is the director for his special film has great character development as well. You see him first being attached to his film project and he'll do anything to make it be successful. However when he brings the captured Kong to broadway and sees it was a disaster, I think he realized that his task to make Kong to be a great broadway hit was a failure and there's no alternative. I think he realized he cannot mess with Kong once he saw that disaster at the broadway show. So in a way I think he did change which showed good character development. Kong also had great development as a character. At first you see him as a ferocious ape that will do anythiing to defend his habitat and himself but then you see he has actual feelings for a human being which happens to be Ann Darrow. I don't know how much more amazing can it get than that.
The last act of the film where Kong is fighting the airplanes and protecting Ann Darrow at the Empire State Building wasa memorable moment of the film. The scene where Kong sees Ann Darrow for the last time before dropping and dying on the street floor from the Empire State Building was another memorable moment. The last scene where Carl tells someone "It wasn't the airplanes. It was Beauty Killed the Beast." was the definite highlight of the film. That line spoken by Carl showed how amazing this movie is and sums up the entire story of the film in general. That scene reminded me of the 90's Beauty and the Beast Animated Disney movie because both share similar concepts. It doesn't matter if you are a human being because animals (in this case an ape) can learn to love someone as well. They can have the same feelings that a regular human being always have. This film conveyed this beautiful message in a flawless way. The way this film was executed was top notch. The Cinemetography and film score was solid as well.
The Negatives:
I actually have no issues with this movie but only one nitpick. My major nitpick with this movie is that the first act was really slow and I thought it could've picked up the pace a little better. I thought the movie did not need to be about three hours long. However that first act was needed to be in the film so I can understand why. If that first act of the film did not happen, the middle and final act would've been weak. But as I said before, nitpicks never hurt movies and this movie is no exception.
Overall, King Kong is a really enjoyable film that delivers a great message. It has action, drama, some humor, and a unique romance. I think King Kong is a masterpiece film and I'm going to rate the film five out of five stars. This is one of Peter Jackson's best movies and this movie proved why he is such a great director. I cannot wait to revuew the Hobbit and Lord of the Rings films eventually. If you haven't seen the 2005 King Kong film, then I highly reccomend you to see it. You won't be disappointed!
My Social Media Accounts:
As always if you want to follow me on my social media accounts, you can follow me on Instagram and on Twitter. Here are my links.
I hope you guys enjoyed reading my review of King Kong and stay tuned for another film related or film review post! 🙂
Tagged film, film review, movie, Movie Review
Previous postBlade Runner 2049 (2017) – Movie Review
Next postThe Terminator (1984) – Movie Review


text:
LETTERS-TO-THE-EDITOR
Iowa City, University of Iowa impress 'outsiders'
Rod Lehnertz
Last month, the University of Iowa hosted a national conference of the Association of University Architects, representing more than 100 campuses from across North America. We were concerned that East and West Coast members might not choose to attend, and though most did, we did indeed hear from many who'd had some reservations. "Why travel to Iowa?"
(Insert any of the typical assumptions about our state here.)
Instead, what they found surpassed their expectations. Many checked into the Hotel Vetro or the Sheraton on Saturday afternoon just as the downtown was transformed by our first-ever Block Party. According to published reports, 30,000 of us welcomed the architects to our little town that likes to act like a big city. Over the course of four days, the attendees learned the story of our community's perseverance in the wake of the flood of 2008 and the resulting transformation of our campus, which many found inspiring. But more than that, the people, the place and the treatment of our guests were recurring themes in the feedback we received.
Renowned and generous UI faculty gave of their personal time to showcase our excellence in the arts; every day, a new storyteller or performer had our guests saying, "Who knew all this was in Iowa?" Though we tend to be humble about this sort of thing, as the conference went on, it became harder and harder to avoid bragging about Iowa City. Sometimes, it takes comments from "outsiders" to help us appreciate just what we have.
Our downtown seemed to be buzzing all week, and our guests had trouble deciding which wonderful restaurant would be next — each was anxious to share their rave review with me so I could recommend it to the others. I was repeatedly told that we were doing damage to their pocketbooks because they couldn't resist our unique and charming shops and clothiers. And again the refrain, "Who would think you could have all of this in the middle of Iowa?"
But two remarks I heard on the final day stuck with me the most.
First, a longtime member said she had participated in more than 30 AUA conferences and that most people in her cohort had "considered the 1997 Princeton conference the best one ever held — until now."
And, second, prior to giving a closing presentation, the architect representing UC San Diego confided to all the members that the conference was not just meaningful, but in fact emotional for him, sharing that he'd never expected anything as special as our campus community he'd found here. He said that, though our buildings and our downtown are beautiful, "it was the people — the way they cared for the buildings and the campus, and the way they cared for all of us — that I will always remember."
Thank you, Iowa City and the University of Iowa!
Rod Lehnertz is senior vice president of Finance and Operations at the University of Iowa and a UI/AUA University Architect.


text:
from config import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, BUCKET_NAME, AWS_ROOT_URL
from PIL import Image, ImageDraw, ImageFont
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from hashlib import sha1
from random import random

class Capytcha(object):
    def __init__(self, sha, path, url=None):
        self.sha = sha
        self.path = path
        self.url = url

    @classmethod
    def generate(cls):
        private_key = sha1(str(random())).hexdigest()[:8]
        public_key  = sha1(private_key).hexdigest()

        captcha = cls.create_captcha(public_key, private_key)
        return cls(public_key, captcha)

    @staticmethod
    def create_captcha(public_key, private_key):
        font = ImageFont.truetype(filename="app/static/css/fonts/CaviarDreams.ttf", size=20)
        image = Image.new('RGB', (100, 25), (255, 255, 255))
        text = ImageDraw.Draw(image)
        output = "app/static/captcha/{}.jpeg".format(public_key)

        text.text((0, 0), private_key, font=font, fill=(0, 0, 0))
        image.save(output)
        return output

    def save(self):
        conn = S3Connection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
        bucket = conn.get_bucket(BUCKET_NAME)
        key = Key(bucket)

        key.key = self.sha + ".jpeg"
        if key.set_contents_from_filename(self.path) > 0:
            self.url = AWS_ROOT_URL + self.sha + ".jpeg"


text:
In Rails apps, it is possible that a model might want another state above 'valid' or 'invalid'. Unreliable inputs may put you in a situation where you can not guarantee the integrity of every entry in your database, but strict validations might cause you to lose fuzzy data.

This gem gives another 'state' about validity, "completeness". A model can require certain attributes or methods to be present in order to be 'complete', giving you another powerful tool when solidfying the integrity of your data.

## Installation

Add this line to your application's Gemfile:

    gem 'godel'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install godel

## Usage

include Godel in any model you'd like to measure completeness in.

    include Godel

You can define attributes required for completeness with the 'completes' command. you can also use
"incomplete_without".

    completes :foo, :bar, :baz

You can also define methods required for completeness. In these methods, create a warning (analagous to 'errors' in validations) should it be incomplete.

    completes_method :must_have_name_or_email

    ...

    private

    def must_have_name_or_email
      if name.blank? && email.blank?
        warnings.add(:name_or_email, "Needs either Name or Email")
      end

    end

You can query the completeness of a method with the #complete? or #incomplete? method, and you can see the relevant warnings with the #warnings method.

    class ReadmeClass
      completes :foo
      completes_method :must_have_bar_over_five

      private

      def must_have_bar_over_five
        if bar < 5
          warnings.add(:bar_over_five, "Bar must be > 5")
        end
      end
    end

    readme = ReadmeClass.create
    readme.incomplete?
      # => true
    readme.warnings
      # => #<Godel::Warnings::0x007efc7f7b11a0 @messages={:foo => "ReademeClass is incomplete without foo", :bar_over_five => "Bar must be > 5"}

    readme.update_attributes(foo: "Foo")

    readme.incomplete?
      # => true
    readme.warnings
      # => #<Godel::Warnings::0x007efc7f7b11a0 @messages={:bar_over_five => "Bar must be > 5"}

    readme.update_attributes(bar: 6)

    readme.incomplete?
      # => false
    readme.warnings
      # => #<Godel::Warnings::0x007efc7f7b11a0 @messages={}

    readme.complete?
      #=> true

## Development Goals

  - api matching rails validation syntax
  - decouple from rails (allow completeness on PORO's)

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

## License
[MIT](http://opensource.org/licenses/MIT)

## Special Thanks
Special thanks to [Terrible Labs](http://www.terriblelabs.com) and [The District Management Council](http://www.dmcouncil.org/), for providing solutions and problems, respectively.


People have been using Essential Oils for over 5,000 years, and scientist, researchers and physicians are just now discovering their potential power. Records show they were use in Egypt, China, Rome, Greece, and other regions in their religious ceremonies, cosmetics. and for medicinal purposes.


text:
Browse: Home / Buchanan Rides Alone: Jacob Thomas Klemmer on Budd Boetticher's Existential Hangout Western
Buchanan Rides Alone: Jacob Thomas Klemmer on Budd Boetticher's Existential Hangout Western
Posted By Sam "Burgundy Suit" Scott on April 25, 2019 in Features | Leave a response
The issue with writing about westerns is that there's just so many of them: John Ford made over 100 films in his day, sometimes three a year, and there is thus a nameless sea of unnamed obscure men who made their short, sturdy westerns that rode through poverty row and turned a profit solely by virtue of their cheapness. There are the traditional auteurs of the western genre like Ford and Leone, then there are those famous filmmakers who made a couple westerns in their day–Fuller, Hawks, Walsh, Peckinpah–and then there are the myriad nameless journeymen who, like their heroes, show up to the desert one morning, do their job for a couple weeks or less, and then ride outta town with their pay.
Thank goodness that some film writers have done their part to rescue Budd Boetticher from the same obscurity as these other sand pebbles – the six or seven westerns he made from '56 to '60, starring Randolph Scott and produced by Harry Joe Brown, represent one of the most wonderful strides of the classical era, more remarkable for how little they have been remarked upon. What's present in these films is a significant signature, a worldview wrapped up in a formal approach, and a particular thematic fixation. Buchanan Rides Alone is the middle film of the Boetticher/Scott stride, and very much the middle child. It lacks the mysterious endings of The Tall T and Ride Lonesome, doesn't possess the virtuoso sentimentality of Seven Men From Now nor the creeping despair of Decision At Sundown. It is, in a word, typical, in that both what it has and what it lacks make it the perfect test case for the Boetticher brand.
First thing's first: filmmaking is defined by its limitations. In the case of Boetticher, that limitation is time, both in the sense that his films were sometimes shot in just ten days, and that not a one of these westerns runs longer than 80 minutes–in fact, Buchanan Rides Alone is one of the longest ones at 78. This brevity wasn't uncommon to B-films, but Boetticher combines it with a deliberate and creeping pace, allowing for lots of silence and waiting, looking, and bluffing. What's cut out of his films is not dead air but rather dead weight – there are no subplots, no extraneous characters, and no time wasted on anything but the main character and his conflict. Buchanan Rides Alone is one of Boetticher's only filmswith a consistent and coherently-sketched setting, the town of Agry, afforded perhaps by those extra five minutes (one can imagine an early scene, where Buchanan strolls through the centre of town and gazes at the signs of all the businesses, being cut in an even less "loose" film). But even then, every detail has a payoff, however surprising. When Buchanan asks "ain't there anybody in this town that ain't an Agry?" it can be taken as a meta-commentary of the script's raw efficiency.
But the Boetticher filmmaking style isn't just found in relentless pacing. His filmmaking is not organized around dialogue or action or even setting, but around gesture (indeed, the gesture of both the camera and the performers). The way he lingers on Randolph Scott's every turn of the head and move of the hand is what distinguishes him from every other B-Western journeyman. Every movement of an actor is a new piece of insight to either their inner world (for example, the hint of confidence with which Buchanan pushes Roy Agry's finger away in the early bar fight, our first hint that Buchanan's easygoing attitude is not a naïve one) or the outer world (in an early scene, the hotel clerk ducks down to the register to make change, revealing an AGRY FOR SENATOR sign, the first sign that something is truly amiss). All that we need to know about a character is conveyed in how they walk through a wide shot, Buchanan's strolling straight ahead most frequently juxtaposed with Amos' unsteady and awkward running, back and forth (as critic Fernando F. Croce notes, Amos' indecision becomes a literal running joke). When your sets are all backlots or deserts, and you've only got so many shots for one day, the gestures have to do as much talking as possible. Instinct is everything.
Can the cowboys of Randolph Scott be amalgamated into an archetype, the Boetticherian Protagonist, driven by a unifying virtue? Unlike Ford's heroes, who were driven by tradition, and Hawks', who were driven by professionalism, Boetticher's men are driven more by instinct and reflex than anything abstract. This is perhaps why his films feel so minimalist and tactile, and perhaps why the Boetticher men have such a high degree of elasticity. Buchanan is completely unlike the pitiable heroes of Seven Men From Now, Ride Lonesome, much less pathetic than the hero of Decision at Sundown, but not quite as capable as the protagonists of The Tall T and Comanche Station, none of which are as easygoing as Buchanan. But here are two things that all these men have in common: they're simple, and they're lonely. Boetticher's villains are ultimately more complex than his heroes, again, all in different ways: Lee Marvin in Seven Men From Now and Richard Boone in The Tall T are themselves two of the greatest villains in Western history, and the villains of this film are in another class altogether, even for Boetticher.
Usually, there is the big bad and his league of cronies, all fodder for an ending gunfight. This time, there is a network of power, a hereditary autocracy smack on the border of the land of the free. The Agrys control their town like monarchs of a medieval fief, who have a stranglehold on the economics, the laws, and their enforcement–and therefore basically all the power. Their rule is so entrenched that Buchanan's status as both an individual and an outsider is sufficient to topple the whole house of cards. We see the machinery of the Agry legal system work when Buchanan pays for both his ten dollar steak and ten dollar hotel room too conspicuously, and once Amos clocks his stash of cash, his death sentence is certain before they can pin anything on him. It's one man (and later a group of Mexican revolutionary allies) against the Agry machine. And lest you confuse this anti-authoritarianism for populism, look at the baying mob of bloodthirsty Agrians clamoring to see a hanging outside the sheriff's office.
The opening scene of dialogue between Buchanan and the sheriff of Agry is a particularly wonderful microcosm of Boetticher's banter-bargaining-bluffing standoff, so nonchalant that it first goes unnoticed. After introductory shots of Buchanan riding from the border into town, we get a view of Agry's main street from the porch of the sheriff's office, and a door made of iron bars swings over our field of view. Then, on the left and right of the frame, the sheriff and Lou stand, further trapping Buchanan in the background, overwhelming the frame with silhouetted entrapment. Despite this, the conversation carries on, with the sheriff stubbornly demanding that Buchanan descend from his horse, and Buchanan refusing until it becomes clear that he must come down. Even when being threatened with being shot, Buchanan's cheery demeanor doesn't flinch, and he descends from his horse going behind one of the men in the frame, out of view, finishing the composition. In this one scene, which changes from an establishing shot to an over-the-shoulder to a conversation without ever cutting, we've been told every single thing we need to know about this film–a once free town has been imprisoned by the corrupt law enforcement, and one figure in the centre of this imprisonment, through sheer force of his easygoing nature, is a threat to it. The entire film blossoms from this initially cheerful standoff, from "I can hear you fine from where I'm sitting" to "I don't wanna shoot you off that horse" and finally to "I wouldn't want you to!" Boetticher is a filmmaker of impulses and reflexes and pregnant glances, which is what makes his standoffs so palpable and intense.
I've mostly spoken about the ways that this film is typical of the Boetticher style, so I'll end by talking briefly about the ways that it's different. Most Boetticher films are not this relaxed, and most aren't this absurdly repetitive. Buchanan always seems to be getting sprung and then captured again, funny at first, then tiring, then borderline existential. Most Boetticher films are funny, but most don't have such a gregarious hero and none have such a flair for banter – this is the closest he ever got to Rio Bravo. Finally, most Boetticher films have at least some place for the other half of the population, but the only woman in this film exists to get slapped in a saloon by Lou Agry in the first ten minutes of the film, and then never be seen again. In Boetticher's universe of gestures and impulses, women represent sensitivity and vulnerability, they offer the fleeting possibility of another life for our lonesome riders. Without women, Buchanan Rides Alone has no chance of measuring up to Boetticher's masterpieces and has no chance of making the viewer feel anything beyond suspense, laughter, and gut satisfaction at the perfect timing of a move.
Still, though, those pleasures are present in spades, and this film serves as a strong baseline for Randolph Scott's cowboy persona and Boetticher's formal approach. Watch this film to be primed for this style of western, and then wade deeper into Boetticher's westerns. Every one of them is at least this good, many of them are far, far better, and they all point to a filmmaker who found a way to make identifyiable, personal films under the constraints of time, money, genre and audience. Budd, like his cowboys, did his job without thinking too hard about it, relying on quick thinking under the clock, with only his instincts to guide him. Boetticher rides alone.
Posted in Features | Tagged 1958, Budd Boetticher, Jacob Thomas Klemmer, Randolph Scott, western, year of the month


text:
Селанова (, ) — муніципалітет в Іспанії, у складі автономної спільноти Галісія, у провінції Оренсе. Населення —  осіб (2009).

Муніципалітет розташований на відстані близько 410 км на північний захід від Мадрида, 21 км на південь від Оренсе.

Муніципалітет складається з таких паррокій: Асеведо-до-Ріо, Алькасар-де-Мільманда, Аморосе, Ансеміль, Барша, Бобадела, Каньйон, Кастромао, Селанова, Фечас, Фрейшо, Мільманда, Моурільйос, Орга, Рабаль, А-Вейга, Віланова-дос-Інфантес, Вівейро.

Демографія

Галерея зображень

Посилання

 Муніципальна рада

Примітки

Муніципалітети провінції Оренсе


View cart "Busy Raising My Tribe Mug" has been added to your cart.
Designed to feature your family's handprints overlaid on top of each other from biggest to smallest this makes a truly lovely gift. Each keepsake handprint overlay mug can display up to four prints and a personalised message of your choice.
From £12.00. We can supply specialised handprint kits as required.
Designed to feature your family's handprints overlaid on top of each other from biggest to smallest this makes a truly lovely gift. Each keepsake handprint overlay mug can display up to four prints and a personalised message of your choice. Please note, the actual size of prints may need to be reduced to fit for this design.
This mug can be ordered with more than 4 prints. If you wish to order with more than 4 prints please email us first.


text:
class CreatePosts < ActiveRecord::Migration[5.1]
  def change
    create_table :posts do |t|
      t.string :subject
      t.text :body
      t.string :user
      t.date :release

      t.timestamps
    end
  end
end


Highbury Media (Pty) Ltd is SA's largest independent magazine and digital publishing company responsible for some of the country's best-performing titles. We are currently looking for a Editorial and Digital Intern for our Editorial department.
-Proficiency in Photoshop, WordPress CMS, trending social media platforms (Facebook, Twitter, Instagram, YouTube, Pinterest) and a Mac operating system.


text:
// @flow

/**
 * @private
 */
export default function insertValues(
  strings: Array<string>,
  ...values: Array<mixed>
): string {
  if (values.length) {
    return strings.reduce((result, part, idx): string => {
      let value = values[idx];

      if (value && typeof value.toString === 'function') {
        value = value.toString();
      } else {
        value = '';
      }

      return result + part + value;
    }, '');
  } else {
    return strings.join('');
  }
}


text:
Everything You Need to Know About Purple Bud
Share this article via:
Whether you're a newby or are seasoned to the world of cannabis, you've probably come across some purple buds and wondered to yourself what makes these nugs exhibit such a striking hue. Cannabis flower buds are typically green with some tufts of red, brown, or orange pistils scattered throughout its leaves. Some buds, however, have a propensity to produce purple pigmentation. There are several factors that can affect the intensity of the bud colors, such as temperatures and nutrient intake.
While colors can be a definite selling point for many marijuana shoppers, there are many myths surrounding these purple strains. Purple buds, unfortunately, aren't more potent than their green, yellow, pink, or blue counterparts. Instead, purple buds are only a sign of a maturing cannabis plant, similar to when tree leaves turn red, orange, and yellow during fall.
What Makes it Purple?
So What Does Purple Mean?
Origins of Purple Bud
Is Purple Bud Stronger?
Purple Bud Strains To Try
Many of today's purple bud strains have been crossbred for color and potency. In order to understand how purple buds are grown, it's important to understand the role of anthocyanins, which are water-soluble pigment molecules found in all plants. Anthocyanins belong to a group of molecules called flavonoids. Flavonoids are responsible for providing color to a host of plants and fruits, including blackberries, raspberries, and blueberries.
Anthocyanins do more than just turn bud leaves into different colors. Anthocyanins act as a plant's defense against UV light exposure and plant-eating predators. A plant's change of colors deters predators that would normally eat plants with green leaves. For this reason, anthocyanins are normally found on a plant's flowers or fruits. Anthocyanin-rich buds can vary in color, ranging from red to blue to purple, depending on the pH level. Anthocyanins can change colors in a plant's leaves, stems, and roots as well.
Temperature plays a big part in anthocyanin production. Cooler temperatures reduce the amount of chlorophyll a plant produces, and chlorophyll is a vital component in facilitating photosynthesis and turning the leaves green. As a cannabis plant matures, the chlorophyll breaks down into sugars for the development of cannabinoids. When plants have reduced chlorophyll production, it actually increases the anthocyanins' visibility.
Nutrients are also key in determining the levels of anthocyanins present in cannabis plants. Nutrient deficiencies during the flowering cycle can cause leaves and stems to exhibit a purple hue. For example, a phosphorus or nitrogen deficiency can cause stems to turn violet. A sulfur deficiency can also manifest itself as purple stripes.
Cannabis growers can choose known anthocyanin-rich strains to grow purple buds, but genetics isn't the only factor that affects the intensity of flower color. For example, some seeds of well-known purple buds such as Purple Urkle may not exhibit purple hues, while other varieties of Purple Urkle may. Unstable genetics in some purple strains is largely affected by growing conditions including temperature and nutrients.
One of the most pervasive myths surrounding purple buds is that they are much more potent than the traditional green bud, but that actually couldn't be farther from the truth! In reality, purple buds don't have more cannabinoids or terpenes. Purple buds just look slightly more intriguing.
While purple buds may not get you higher, there has been some research suggesting that the anthocyanins have antioxidant, anti-inflammatory, neuroprotective, and analgesic properties. Depending on the type of anthocyanin, they have also been found to interact with the endocannabinoid system.
So, is purple bud stronger? No. But, further research may show that anthocyanins can take part in what's known as the synergistic "entourage effect."
Now that you've got a better handle on what the purple buds are all about, you can try out some different purple bud strains! Purple Urkle is a popular Indica strain with mysterious origins. It's rumored to be California-bred with Mendocino Purps genetics. Purple Urkle has a terpene-rich, skunky and tropical aroma. Expect to smell scents of berries, grapes, and plenty of musky aromas. Its THC levels can range between 17 to 22 percent.
Grandaddy Purple (GDP) was bred by Ken Estes in Northern California. GDP has won first place in the Medical Cup 2004 as well as multiple Green Cup awards. This purple bud strain is a cross between Purple Urkle and Big Bud and then backcrossed with GDP. GDP is known as a hardy plant that develops purple, red, or blue hues and tons of resin and terpenes. Hopeful growers can score some GDP seeds from Dark Heart Nursery.
Purple Haze is another famed purple bud strain with unknown origins. Purple Haze first became popular during the time that an LSD variety with the same name was being sold in the 1960s and 70s. Purple Haze is a Sativa strain with around 20 percent THC, has fruity and musky scents, and is rumored to be grown with Colombian strain genetics.
Purple buds are rare, but a treat to consume — even if it's just for their bag appeal. While purple buds won't get you any higher, they are a welcome variety of buds to the common green flower. If you're interested in finding some purple buds near your town, check out our strain and dispensary directory to find purple strains for you to enjoy!
FOR THE BEST CANNABIS DEALS, CHECK OUT THE LEAFBUYER DEALS PAGE!
marijuana history
Previous articleHow to Conserve Your Weed
Next articleFinding Targeted Effects with CBD Disposable Vape Pens
Fred Hernandez is a comedy and cannabis writer from San Diego, CA. He has helped agencies, businesses, and publications craft clever, concise, and captivating copy geared for their target audiences. As a cannabis content writer, he hopes to educate and entertain people with content about the cannabis industry. When he's not writing cannabis articles, he's reading novels, planning his next trip abroad, and writing music.
List of Colorado Marijuana Delivery Services – What's Legal and What's Not
Leafbuyer's List of TOP CANNABIS JOURNALISTS
5 Best Strains Anticipated in 2021


We thank the Petco Foundation for a generous donation from its 2012 Holiday Tree of Hope program. We are honored to be partners with the Petco Foundation. Tree of Hope is the Petco Foundation's annual holiday fundraising campaign and continues to be the largest source of revenue for the Foundation and the many local groups it assists. Donations collected in stores during Tree of Hope go directly to animal welfare groups so they may continue their work in making better lives for animals through adoption, spay/neuter, and training. Last year the Petco Foundation raised more than $4 million during Tree of Hope, to support over 8,000 agencies, both large and small.


Full sun to part shade. [22-26" tall] USDA Hardiness Zones 6-10. Blooms Summer to early Fall.
A BREAKTHROUGH IN GAILLARDIA COLOR!
Gaillardia aristata 'Oranges & Lemons' PP#17092 opens the door to new colors with Blanket Flowers. The petals are peachy colored with yellow tips. The blue-green foliage grows in an improved upright form. It has been described by leading perennial growers as "simply fantastic!".
Gaillardia are hardy perennials that are drought tolerant once they are established. They endure heat better than many other plants so they are often used in the South, to Zone 10. Sometimes referred to as Blanket Flowers, they thrive best in well draining, poor soil. A native to North America, it gets its common name from the fact that it would 'blanket'the countryside prairies when in bloom. Generally considered deer-resistant they make great cut flowers, both fresh and dried. Butterflies love them.


text:
A C & T Co Inc
0 Experts
Your dream job…could be 1 update away
A C & T Co Inc High Paying Jobs, Compensation Information and Expert Network Connections
What are the highest paying jobs at A C & T Co Inc?
AT&T Inc. is an American multinational conglomerate holding company that is Delaware-registered but headquartered at Whitacre Tower in Downtown Dallas, Texas. It is the world's largest telecommunications company and the largest provider of mobile telephone services in the U.S. As of 2020, AT&T was ranked 9th on the Fortune 500 rankings of the largest United States corporations, with revenues of $181 billion.
During most of the 20th century, AT&T had a monopoly on phone service in the United States. The company began its history as the American District Telegraph Company, formed in St. Louis in 1878. After expanding services to Arkansas, Kansas, Oklahoma and Texas, through a series of mergers, it became Southwestern Bell Telephone Company in 1920, which was then a subsidiary of American Telephone and Telegraph Company. The latter was a successor of the original Bell Telephone Company founded by Alexander Graham Bell in 1877. The American Bell Telephone Company formed the American Telephone and Telegraph Company subsidiary in 1885. In 1899, AT&T became the parent company after the American Bell Telephone Company sold its assets to its subsidiary. The company was rebranded as AT&T Corp. in 1994. The 1982 United States v. AT&T antitrust lawsuit resulted in the divestiture of AT&T's local operating subsidiaries which were grouped into seven Regional Bell Operating Companies, commonly referred to as "Baby Bells", resulting in seven independent companies, including Southwestern Bell Corporation. The latter changed its name to SBC Communications Inc. in 1995.
Southern Maryland Electric Cooperative, Inc
Ladders / Company / A C & T Co Inc