Merge pull request #2727 from vnagel/ageRestrictedContent

Restricted mode setting for youtube
This commit is contained in:
wb9688 2020-05-04 15:05:11 +02:00 committed by GitHub
commit 40b1cd82b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 125 additions and 14 deletions

View File

@ -136,7 +136,8 @@ public class App extends Application {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
getApplicationContext());
final String key = getApplicationContext().getString(R.string.recaptcha_cookies_key);
downloader.setCookies(prefs.getString(key, ""));
downloader.setCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY, prefs.getString(key, ""));
downloader.updateYoutubeRestrictedModeCookies(getApplicationContext());
}
private void configureRxJavaErrorHandler() {

View File

@ -1,7 +1,8 @@
package org.schabi.newpipe;
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
import android.preference.PreferenceManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -10,6 +11,8 @@ import org.schabi.newpipe.extractor.downloader.Downloader;
import org.schabi.newpipe.extractor.downloader.Request;
import org.schabi.newpipe.extractor.downloader.Response;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.util.CookieUtils;
import org.schabi.newpipe.util.InfoCache;
import org.schabi.newpipe.util.TLSSocketFactoryCompat;
import java.io.IOException;
@ -20,6 +23,7 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -40,9 +44,13 @@ import static org.schabi.newpipe.MainActivity.DEBUG;
public final class DownloaderImpl extends Downloader {
public static final String USER_AGENT
= "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0";
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE_KEY
= "youtube_restricted_mode_key";
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE = "PREF=f2=8000000";
public static final String YOUTUBE_DOMAIN = "youtube.com";
private static DownloaderImpl instance;
private String mCookies;
private Map<String, String> mCookies;
private OkHttpClient client;
private DownloaderImpl(final OkHttpClient.Builder builder) {
@ -54,6 +62,7 @@ public final class DownloaderImpl extends Downloader {
// .cache(new Cache(new File(context.getExternalCacheDir(), "okhttp"),
// 16 * 1024 * 1024))
.build();
this.mCookies = new HashMap<>();
}
/**
@ -121,12 +130,50 @@ public final class DownloaderImpl extends Downloader {
}
}
public String getCookies() {
return mCookies;
public String getCookies(final String url) {
List<String> resultCookies = new ArrayList<>();
if (url.contains(YOUTUBE_DOMAIN)) {
String youtubeCookie = getCookie(YOUTUBE_RESTRICTED_MODE_COOKIE_KEY);
if (youtubeCookie != null) {
resultCookies.add(youtubeCookie);
}
}
// Recaptcha cookie is always added TODO: not sure if this is necessary
String recaptchaCookie = getCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY);
if (recaptchaCookie != null) {
resultCookies.add(recaptchaCookie);
}
return CookieUtils.concatCookies(resultCookies);
}
public void setCookies(final String cookies) {
mCookies = cookies;
public String getCookie(final String key) {
return mCookies.get(key);
}
public void setCookie(final String key, final String cookie) {
mCookies.put(key, cookie);
}
public void removeCookie(final String key) {
mCookies.remove(key);
}
public void updateYoutubeRestrictedModeCookies(final Context context) {
String restrictedModeEnabledKey =
context.getString(R.string.youtube_restricted_mode_enabled);
boolean restrictedModeEnabled = PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(restrictedModeEnabledKey, false);
updateYoutubeRestrictedModeCookies(restrictedModeEnabled);
}
public void updateYoutubeRestrictedModeCookies(final boolean youtubeRestrictedModeEnabled) {
if (youtubeRestrictedModeEnabled) {
setCookie(YOUTUBE_RESTRICTED_MODE_COOKIE_KEY,
YOUTUBE_RESTRICTED_MODE_COOKIE);
} else {
removeCookie(YOUTUBE_RESTRICTED_MODE_COOKIE_KEY);
}
InfoCache.getInstance().clearCache();
}
/**
@ -152,8 +199,9 @@ public final class DownloaderImpl extends Downloader {
.method("GET", null).url(siteUrl)
.addHeader("User-Agent", USER_AGENT);
if (!TextUtils.isEmpty(mCookies)) {
requestBuilder.addHeader("Cookie", mCookies);
String cookies = getCookies(siteUrl);
if (!cookies.isEmpty()) {
requestBuilder.addHeader("Cookie", cookies);
}
final okhttp3.Request request = requestBuilder.build();
@ -192,8 +240,9 @@ public final class DownloaderImpl extends Downloader {
.method(httpMethod, requestBody).url(url)
.addHeader("User-Agent", USER_AGENT);
if (!TextUtils.isEmpty(mCookies)) {
requestBuilder.addHeader("Cookie", mCookies);
String cookies = getCookies(url);
if (!cookies.isEmpty()) {
requestBuilder.addHeader("Cookie", cookies);
}
for (Map.Entry<String, List<String>> pair : headers.entrySet()) {

View File

@ -51,6 +51,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
public static final String RECAPTCHA_URL_EXTRA = "recaptcha_url_extra";
public static final String TAG = ReCaptchaActivity.class.toString();
public static final String YT_URL = "https://www.youtube.com";
public static final String RECAPTCHA_COOKIES_KEY = "recaptcha_cookies";
private WebView webView;
private String foundCookies = "";
@ -168,7 +169,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
prefs.edit().putString(key, foundCookies).apply();
// give cookies to Downloader class
DownloaderImpl.getInstance().setCookies(foundCookies);
DownloaderImpl.getInstance().setCookie(RECAPTCHA_COOKIES_KEY, foundCookies);
setResult(RESULT_OK);
}

View File

@ -2,6 +2,7 @@ package org.schabi.newpipe.fragments;
import android.content.Context;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@ -45,6 +46,9 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
private boolean hasTabsChanged = false;
private boolean previousYoutubeRestrictedModeEnabled;
private String youtubeRestrictedModeEnabledKey;
/*//////////////////////////////////////////////////////////////////////////
// Fragment's LifeCycle
//////////////////////////////////////////////////////////////////////////*/
@ -53,7 +57,6 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
tabsManager = TabsManager.getManager(activity);
tabsManager.setSavedTabsListener(() -> {
if (DEBUG) {
@ -66,6 +69,11 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
hasTabsChanged = true;
}
});
youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled);
previousYoutubeRestrictedModeEnabled =
PreferenceManager.getDefaultSharedPreferences(getContext())
.getBoolean(youtubeRestrictedModeEnabledKey, false);
}
@Override
@ -92,7 +100,13 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
public void onResume() {
super.onResume();
if (hasTabsChanged) {
boolean youtubeRestrictedModeEnabled =
PreferenceManager.getDefaultSharedPreferences(getContext())
.getBoolean(youtubeRestrictedModeEnabledKey, false);
if (previousYoutubeRestrictedModeEnabled != youtubeRestrictedModeEnabled) {
previousYoutubeRestrictedModeEnabled = youtubeRestrictedModeEnabled;
setupTabs();
} else if (hasTabsChanged) {
setupTabs();
}
}

View File

@ -2,6 +2,7 @@ package org.schabi.newpipe.settings;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@ -17,6 +18,7 @@ import androidx.preference.Preference;
import com.nononsenseapps.filepicker.Utils;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe;
@ -56,6 +58,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
private File newpipeSettings;
private String thumbnailLoadToggleKey;
private String youtubeRestrictedModeEnabledKey;
private Localization initialSelectedLocalization;
private ContentCountry initialSelectedContentCountry;
@ -65,6 +68,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
thumbnailLoadToggleKey = getString(R.string.download_thumbnail_key);
youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled);
initialSelectedLocalization = org.schabi.newpipe.util.Localization
.getPreferredLocalization(requireContext());
@ -86,6 +90,15 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
Toast.LENGTH_SHORT).show();
}
if (preference.getKey().equals(youtubeRestrictedModeEnabledKey)) {
Context context = getContext();
if (context != null) {
DownloaderImpl.getInstance().updateYoutubeRestrictedModeCookies(context);
} else {
Log.w(TAG, "onPreferenceTreeClick: null context");
}
}
return super.onPreferenceTreeClick(preference);
}

View File

@ -0,0 +1,25 @@
package org.schabi.newpipe.util;
import org.jsoup.helper.StringUtil;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public final class CookieUtils {
private CookieUtils() {
}
public static String concatCookies(final Collection<String> cookieStrings) {
Set<String> cookieSet = new HashSet<>();
for (String cookies : cookieStrings) {
cookieSet.addAll(splitCookies(cookies));
}
return StringUtil.join(cookieSet, "; ").trim();
}
public static Set<String> splitCookies(final String cookies) {
return new HashSet<>(Arrays.asList(cookies.split("; *")));
}
}

View File

@ -170,6 +170,7 @@
<string name="peertube_instance_list_key" translatable="false">peertube_instance_list</string>
<string name="content_country_key" translatable="false">content_country</string>
<string name="show_age_restricted_content" translatable="false">show_age_restricted_content</string>
<string name="youtube_restricted_mode_enabled" translatable="false">youtube_restricted_mode_enabled</string>
<string name="use_tor_key" translatable="false">use_tor</string>
<string name="enable_search_history_key" translatable="false">enable_search_history</string>
<string name="enable_watch_history_key" translatable="false">enable_watch_history</string>

View File

@ -137,6 +137,7 @@
<string name="content">Content</string>
<string name="show_age_restricted_content_title">Age restricted content</string>
<string name="video_is_age_restricted">Show age restricted video. Future changes are possible from the settings.</string>
<string name="youtube_restricted_mode_enabled_title">YouTube restricted mode</string>
<string name="restricted_video">This video is age restricted.\n\nIf you want to view it, enable \"Age restricted content\" in the settings.</string>
<string name="duration_live">Live</string>
<string name="downloads">Downloads</string>

View File

@ -51,6 +51,12 @@
android:key="@string/show_age_restricted_content"
android:title="@string/show_age_restricted_content_title"/>
<SwitchPreference
app:iconSpaceReserved="false"
android:defaultValue="false"
android:key="@string/youtube_restricted_mode_enabled"
android:title="@string/youtube_restricted_mode_enabled_title"/>
<SwitchPreference
app:iconSpaceReserved="false"
android:defaultValue="true"