Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/debug/java/org/schabi/newpipe/DebugApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class DebugApp : App() {
override fun getDownloader(): Downloader {
val downloader = DownloaderImpl.init(
OkHttpClient.Builder()
.addNetworkInterceptor(StethoInterceptor())
.addNetworkInterceptor(StethoInterceptor()),
this
)
setCookiesToDownloader(downloader)
return downloader
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/schabi/newpipe/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ open class App :
}.build()

protected open fun getDownloader(): Downloader {
val downloader = DownloaderImpl.init(null)
val downloader = DownloaderImpl.init(null, this)
setCookiesToDownloader(downloader)
return downloader
}
Expand Down
14 changes: 11 additions & 3 deletions app/src/main/java/org/schabi/newpipe/DownloaderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
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.ProxyManager;
import org.schabi.newpipe.util.InfoCache;

import java.io.IOException;
Expand Down Expand Up @@ -57,11 +58,18 @@ public OkHttpClient getClient() {
* It's recommended to call exactly once in the entire lifetime of the application.
*
* @param builder if null, default builder will be used
* @param context the context to use
* @return a new instance of {@link DownloaderImpl}
*/
public static DownloaderImpl init(@Nullable final OkHttpClient.Builder builder) {
instance = new DownloaderImpl(
builder != null ? builder : new OkHttpClient.Builder());
public static DownloaderImpl init(@Nullable final OkHttpClient.Builder builder,
final Context context) {
final OkHttpClient.Builder builderToUse = builder != null ? builder
: new OkHttpClient.Builder();
final ProxyManager proxyManager = new ProxyManager(context);
if (proxyManager.isProxyEnabled()) {
builderToUse.proxy(proxyManager.getProxy());
}
instance = new DownloaderImpl(builderToUse);
return instance;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebEmbeddedPlayerStreamingUrl;
import static java.lang.Math.min;

import android.content.Context;
import android.net.Uri;

import androidx.annotation.NonNull;
Expand All @@ -45,6 +46,7 @@
import com.google.common.net.HttpHeaders;

import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.util.ProxyManager;

import java.io.IOException;
import java.io.InputStream;
Expand All @@ -54,6 +56,7 @@
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.Proxy;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -84,6 +87,7 @@ public final class YoutubeHttpDataSource extends BaseDataSource implements HttpD
*/
public static final class Factory implements HttpDataSource.Factory {

private final Context context;
private final RequestProperties defaultRequestProperties;

@Nullable
Expand All @@ -100,8 +104,10 @@ public static final class Factory implements HttpDataSource.Factory {

/**
* Creates an instance.
* @param context the context to use
*/
public Factory() {
public Factory(final Context context) {
this.context = context;
defaultRequestProperties = new RequestProperties();
connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MILLIS;
readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLIS;
Expand Down Expand Up @@ -220,7 +226,6 @@ public Factory setContentTypePredicate(
* <p>The default is {@code null}.
*
* <p>See {@link DataSource#addTransferListener(TransferListener)}.
*
* @param transferListenerToUse The listener that will be used.
* @return This factory.
*/
Expand All @@ -247,6 +252,7 @@ public Factory setKeepPostFor302Redirects(final boolean keepPostFor302RedirectsV
@Override
public YoutubeHttpDataSource createDataSource() {
final YoutubeHttpDataSource dataSource = new YoutubeHttpDataSource(
context,
connectTimeoutMs,
readTimeoutMs,
allowCrossProtocolRedirects,
Expand All @@ -272,6 +278,7 @@ public YoutubeHttpDataSource createDataSource() {
private static final String YOUTUBE_BASE_URL = "https://www.youtube.com";
private static final byte[] POST_BODY = new byte[] {0x78, 0};

private final Context context;
private final boolean allowCrossProtocolRedirects;
private final boolean rangeParameterEnabled;
private final boolean rnParameterEnabled;
Expand Down Expand Up @@ -299,7 +306,8 @@ public YoutubeHttpDataSource createDataSource() {
private long requestNumber;

@SuppressWarnings("checkstyle:ParameterNumber")
private YoutubeHttpDataSource(final int connectTimeoutMillis,
private YoutubeHttpDataSource(final Context context,
final int connectTimeoutMillis,
final int readTimeoutMillis,
final boolean allowCrossProtocolRedirects,
final boolean rangeParameterEnabled,
Expand All @@ -308,6 +316,7 @@ private YoutubeHttpDataSource(final int connectTimeoutMillis,
@Nullable final Predicate<String> contentTypePredicate,
final boolean keepPostFor302Redirects) {
super(true);
this.context = context;
this.connectTimeoutMillis = connectTimeoutMillis;
this.readTimeoutMillis = readTimeoutMillis;
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
Expand Down Expand Up @@ -708,6 +717,11 @@ private HttpURLConnection makeConnection(
* @return an {@link HttpURLConnection} created with the {@code url}
*/
private HttpURLConnection openConnection(@NonNull final URL url) throws IOException {
final ProxyManager proxyManager = new ProxyManager(context);
final Proxy proxy = proxyManager.getProxy();
if (proxy != null) {
return (HttpURLConnection) url.openConnection(proxy);
}
return (HttpURLConnection) url.openConnection();
}

Expand Down Expand Up @@ -1006,4 +1020,3 @@ public int hashCode() {
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
import com.google.android.exoplayer2.upstream.cache.SimpleCache;

import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubeOtfDashManifestCreator;
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubePostLiveStreamDvrDashManifestCreator;
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubeProgressiveDashManifestCreator;
Expand Down Expand Up @@ -86,20 +84,22 @@ public PlayerDataSource(final Context context,
// make sure the static cache was created: needed by CacheFactories below
instantiateCacheIfNeeded(context);

// generic data source factories use DefaultHttpDataSource.Factory
// generic data source factories now use YoutubeHttpDataSource.Factory to support proxies
final YoutubeHttpDataSource.Factory youtubeHttpDataSourceFactory =
getYoutubeHttpDataSourceFactory(context, false, false);
cachelessDataSourceFactory = new DefaultDataSource.Factory(context,
new DefaultHttpDataSource.Factory().setUserAgent(DownloaderImpl.USER_AGENT))
youtubeHttpDataSourceFactory)
.setTransferListener(transferListener);
cacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
new DefaultHttpDataSource.Factory().setUserAgent(DownloaderImpl.USER_AGENT));
youtubeHttpDataSourceFactory);

// YouTube-specific data source factories use getYoutubeHttpDataSourceFactory()
ytHlsCacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
getYoutubeHttpDataSourceFactory(false, false));
getYoutubeHttpDataSourceFactory(context, false, false));
ytDashCacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
getYoutubeHttpDataSourceFactory(true, true));
getYoutubeHttpDataSourceFactory(context, true, true));
ytProgressiveDashCacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
getYoutubeHttpDataSourceFactory(false, true));
getYoutubeHttpDataSourceFactory(context, false, true));

// set the maximum size to manifest creators
YoutubeProgressiveDashManifestCreator.getCache().setMaximumSize(MAX_MANIFEST_CACHE_SIZE);
Expand Down Expand Up @@ -198,9 +198,10 @@ private static DefaultDashChunkSource.Factory getDefaultDashChunkSourceFactory(
}

private static YoutubeHttpDataSource.Factory getYoutubeHttpDataSourceFactory(
final Context context,
final boolean rangeParameterEnabled,
final boolean rnParameterEnabled) {
return new YoutubeHttpDataSource.Factory()
return new YoutubeHttpDataSource.Factory(context)
.setRangeParameterEnabled(rangeParameterEnabled)
.setRnParameterEnabled(rnParameterEnabled);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.schabi.newpipe.settings;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.annotation.Nullable;
import org.schabi.newpipe.R;
import org.schabi.newpipe.util.NavigationHelper;

/**
* A fragment that displays proxy settings.
*/
public class ProxySettingsFragment extends BasePreferenceFragment {

private boolean preferencesChanged = false;
private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener;

@Override
public void onCreatePreferences(@Nullable final Bundle savedInstanceState,
@Nullable final String rootKey) {
//addPreferencesFromResource(R.xml.proxy_settings);
addPreferencesFromResourceRegistry();
preferenceChangeListener = (sharedPreferences, key) -> {
preferencesChanged = true;
};
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
}

@Override
public void onStop() {
super.onStop();
if (preferencesChanged && getActivity() != null && !getActivity().isFinishing()) {
showRestartDialog();
}
}

private void showRestartDialog() {
// Show Alert Dialogue
final Activity activity = getActivity();
if (activity == null) {
return;
}
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setMessage(R.string.restart_app_message);
builder.setTitle(R.string.restart_app_title);
builder.setCancelable(true);
builder.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
// Restarts the app
if (activity == null) {
return;
}
NavigationHelper.restartApp(activity);
});
builder.setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
});
final android.app.AlertDialog alertDialog = builder.create();
alertDialog.show();
}

@Override
public void onDestroy() {
super.onDestroy();
if (preferenceChangeListener != null && getPreferenceScreen() != null) {
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ private SettingsResourceRegistry() {
add(VideoAudioSettingsFragment.class, R.xml.video_audio_settings);
add(ExoPlayerSettingsFragment.class, R.xml.exoplayer_settings);
add(BackupRestoreSettingsFragment.class, R.xml.backup_restore_settings);
add(ProxySettingsFragment.class, R.xml.proxy_settings);
}

private SettingRegistryEntry add(
Expand Down
79 changes: 79 additions & 0 deletions app/src/main/java/org/schabi/newpipe/util/ProxyManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.schabi.newpipe.util;

import android.content.Context;
import android.content.SharedPreferences;

import androidx.preference.PreferenceManager;

import java.net.InetSocketAddress;
import java.net.Proxy;

/**
* A class to manage proxy settings.
*/
public class ProxyManager {

private final SharedPreferences sharedPreferences;

/**
* Creates a new ProxyManager.
* @param context the context to use
*/
public ProxyManager(final Context context) {
this.sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
}

/**
* Checks if the proxy is enabled.
* @return true if the proxy is enabled, false otherwise
*/
public boolean isProxyEnabled() {
return sharedPreferences.getBoolean("use_proxy", false);
}

/**
* Gets the proxy host.
* @return the proxy host
*/
public String getProxyHost() {
return sharedPreferences.getString("proxy_host", "127.0.0.1");
}

/**
* Gets the proxy port.
* @return the proxy port
*/
public int getProxyPort() {
final String portString = sharedPreferences.getString("proxy_port", "1080");
try {
return Integer.parseInt(portString);
} catch (final NumberFormatException e) {
return 1080;
}
}

/**
* Gets the proxy type.
* @return the proxy type
*/
public Proxy.Type getProxyType() {
final String type = sharedPreferences.getString("proxy_type", "SOCKS");
if ("SOCKS".equals(type)) {
return Proxy.Type.SOCKS;
} else {
return Proxy.Type.HTTP;
}
}

/**
* Gets the proxy.
* @return the proxy, or null if the proxy is not enabled
*/
public Proxy getProxy() {
if (!isProxyEnabled()) {
return null;
}
return new Proxy(getProxyType(), new InetSocketAddress(getProxyHost(), getProxyPort()));
}
}
Loading
Loading