Merge pull request #2727 from vnagel/ageRestrictedContent
Restricted mode setting for youtube
This commit is contained in:
commit
40b1cd82b1
9 changed files with 125 additions and 14 deletions
|
@ -136,7 +136,8 @@ public class App extends Application {
|
||||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
|
||||||
getApplicationContext());
|
getApplicationContext());
|
||||||
final String key = getApplicationContext().getString(R.string.recaptcha_cookies_key);
|
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() {
|
private void configureRxJavaErrorHandler() {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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.Request;
|
||||||
import org.schabi.newpipe.extractor.downloader.Response;
|
import org.schabi.newpipe.extractor.downloader.Response;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
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 org.schabi.newpipe.util.TLSSocketFactoryCompat;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -20,6 +23,7 @@ import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -40,9 +44,13 @@ import static org.schabi.newpipe.MainActivity.DEBUG;
|
||||||
public final class DownloaderImpl extends Downloader {
|
public final class DownloaderImpl extends Downloader {
|
||||||
public static final String USER_AGENT
|
public static final String USER_AGENT
|
||||||
= "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0";
|
= "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 static DownloaderImpl instance;
|
||||||
private String mCookies;
|
private Map<String, String> mCookies;
|
||||||
private OkHttpClient client;
|
private OkHttpClient client;
|
||||||
|
|
||||||
private DownloaderImpl(final OkHttpClient.Builder builder) {
|
private DownloaderImpl(final OkHttpClient.Builder builder) {
|
||||||
|
@ -54,6 +62,7 @@ public final class DownloaderImpl extends Downloader {
|
||||||
// .cache(new Cache(new File(context.getExternalCacheDir(), "okhttp"),
|
// .cache(new Cache(new File(context.getExternalCacheDir(), "okhttp"),
|
||||||
// 16 * 1024 * 1024))
|
// 16 * 1024 * 1024))
|
||||||
.build();
|
.build();
|
||||||
|
this.mCookies = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,12 +130,50 @@ public final class DownloaderImpl extends Downloader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCookies() {
|
public String getCookies(final String url) {
|
||||||
return mCookies;
|
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) {
|
public String getCookie(final String key) {
|
||||||
mCookies = cookies;
|
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)
|
.method("GET", null).url(siteUrl)
|
||||||
.addHeader("User-Agent", USER_AGENT);
|
.addHeader("User-Agent", USER_AGENT);
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(mCookies)) {
|
String cookies = getCookies(siteUrl);
|
||||||
requestBuilder.addHeader("Cookie", mCookies);
|
if (!cookies.isEmpty()) {
|
||||||
|
requestBuilder.addHeader("Cookie", cookies);
|
||||||
}
|
}
|
||||||
|
|
||||||
final okhttp3.Request request = requestBuilder.build();
|
final okhttp3.Request request = requestBuilder.build();
|
||||||
|
@ -192,8 +240,9 @@ public final class DownloaderImpl extends Downloader {
|
||||||
.method(httpMethod, requestBody).url(url)
|
.method(httpMethod, requestBody).url(url)
|
||||||
.addHeader("User-Agent", USER_AGENT);
|
.addHeader("User-Agent", USER_AGENT);
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(mCookies)) {
|
String cookies = getCookies(url);
|
||||||
requestBuilder.addHeader("Cookie", mCookies);
|
if (!cookies.isEmpty()) {
|
||||||
|
requestBuilder.addHeader("Cookie", cookies);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, List<String>> pair : headers.entrySet()) {
|
for (Map.Entry<String, List<String>> pair : headers.entrySet()) {
|
||||||
|
|
|
@ -51,6 +51,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
public static final String RECAPTCHA_URL_EXTRA = "recaptcha_url_extra";
|
public static final String RECAPTCHA_URL_EXTRA = "recaptcha_url_extra";
|
||||||
public static final String TAG = ReCaptchaActivity.class.toString();
|
public static final String TAG = ReCaptchaActivity.class.toString();
|
||||||
public static final String YT_URL = "https://www.youtube.com";
|
public static final String YT_URL = "https://www.youtube.com";
|
||||||
|
public static final String RECAPTCHA_COOKIES_KEY = "recaptcha_cookies";
|
||||||
|
|
||||||
private WebView webView;
|
private WebView webView;
|
||||||
private String foundCookies = "";
|
private String foundCookies = "";
|
||||||
|
@ -168,7 +169,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
||||||
prefs.edit().putString(key, foundCookies).apply();
|
prefs.edit().putString(key, foundCookies).apply();
|
||||||
|
|
||||||
// give cookies to Downloader class
|
// give cookies to Downloader class
|
||||||
DownloaderImpl.getInstance().setCookies(foundCookies);
|
DownloaderImpl.getInstance().setCookie(RECAPTCHA_COOKIES_KEY, foundCookies);
|
||||||
setResult(RESULT_OK);
|
setResult(RESULT_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.fragments;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
@ -45,6 +46,9 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
|
|
||||||
private boolean hasTabsChanged = false;
|
private boolean hasTabsChanged = false;
|
||||||
|
|
||||||
|
private boolean previousYoutubeRestrictedModeEnabled;
|
||||||
|
private String youtubeRestrictedModeEnabledKey;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Fragment's LifeCycle
|
// Fragment's LifeCycle
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -53,7 +57,6 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
public void onCreate(final Bundle savedInstanceState) {
|
public void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
tabsManager = TabsManager.getManager(activity);
|
tabsManager = TabsManager.getManager(activity);
|
||||||
tabsManager.setSavedTabsListener(() -> {
|
tabsManager.setSavedTabsListener(() -> {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -66,6 +69,11 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
hasTabsChanged = true;
|
hasTabsChanged = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled);
|
||||||
|
previousYoutubeRestrictedModeEnabled =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||||
|
.getBoolean(youtubeRestrictedModeEnabledKey, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -92,7 +100,13 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
if (hasTabsChanged) {
|
boolean youtubeRestrictedModeEnabled =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||||
|
.getBoolean(youtubeRestrictedModeEnabledKey, false);
|
||||||
|
if (previousYoutubeRestrictedModeEnabled != youtubeRestrictedModeEnabled) {
|
||||||
|
previousYoutubeRestrictedModeEnabled = youtubeRestrictedModeEnabled;
|
||||||
|
setupTabs();
|
||||||
|
} else if (hasTabsChanged) {
|
||||||
setupTabs();
|
setupTabs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.settings;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -17,6 +18,7 @@ import androidx.preference.Preference;
|
||||||
import com.nononsenseapps.filepicker.Utils;
|
import com.nononsenseapps.filepicker.Utils;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.DownloaderImpl;
|
||||||
import org.schabi.newpipe.NewPipeDatabase;
|
import org.schabi.newpipe.NewPipeDatabase;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
@ -56,6 +58,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
private File newpipeSettings;
|
private File newpipeSettings;
|
||||||
|
|
||||||
private String thumbnailLoadToggleKey;
|
private String thumbnailLoadToggleKey;
|
||||||
|
private String youtubeRestrictedModeEnabledKey;
|
||||||
|
|
||||||
private Localization initialSelectedLocalization;
|
private Localization initialSelectedLocalization;
|
||||||
private ContentCountry initialSelectedContentCountry;
|
private ContentCountry initialSelectedContentCountry;
|
||||||
|
@ -65,6 +68,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
thumbnailLoadToggleKey = getString(R.string.download_thumbnail_key);
|
thumbnailLoadToggleKey = getString(R.string.download_thumbnail_key);
|
||||||
|
youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled);
|
||||||
|
|
||||||
initialSelectedLocalization = org.schabi.newpipe.util.Localization
|
initialSelectedLocalization = org.schabi.newpipe.util.Localization
|
||||||
.getPreferredLocalization(requireContext());
|
.getPreferredLocalization(requireContext());
|
||||||
|
@ -86,6 +90,15 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||||
Toast.LENGTH_SHORT).show();
|
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);
|
return super.onPreferenceTreeClick(preference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
app/src/main/java/org/schabi/newpipe/util/CookieUtils.java
Normal file
25
app/src/main/java/org/schabi/newpipe/util/CookieUtils.java
Normal 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("; *")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -170,6 +170,7 @@
|
||||||
<string name="peertube_instance_list_key" translatable="false">peertube_instance_list</string>
|
<string name="peertube_instance_list_key" translatable="false">peertube_instance_list</string>
|
||||||
<string name="content_country_key" translatable="false">content_country</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="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="use_tor_key" translatable="false">use_tor</string>
|
||||||
<string name="enable_search_history_key" translatable="false">enable_search_history</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>
|
<string name="enable_watch_history_key" translatable="false">enable_watch_history</string>
|
||||||
|
|
|
@ -137,6 +137,7 @@
|
||||||
<string name="content">Content</string>
|
<string name="content">Content</string>
|
||||||
<string name="show_age_restricted_content_title">Age restricted 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="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="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="duration_live">Live</string>
|
||||||
<string name="downloads">Downloads</string>
|
<string name="downloads">Downloads</string>
|
||||||
|
|
|
@ -51,6 +51,12 @@
|
||||||
android:key="@string/show_age_restricted_content"
|
android:key="@string/show_age_restricted_content"
|
||||||
android:title="@string/show_age_restricted_content_title"/>
|
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
|
<SwitchPreference
|
||||||
app:iconSpaceReserved="false"
|
app:iconSpaceReserved="false"
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
|
Loading…
Reference in a new issue