Skip to content

Commit

Permalink
Allow downloading PDFs instead of opening them in Brave.
Browse files Browse the repository at this point in the history
Fixes brave/brave-browser#1531

The fix does the following:

1. Makes the initial decision on whether to load PDFJS extension based
on the value of kPluginsAlwaysOpenPdfExternally profile preference in
addition to the command line switch.

2. Watches profile preference value kPluginsAlwaysOpenPdfExternally and
adds/removes PDFJS component when the value changes.

3. Modifies js behind the chrome://settings/content/pdfDocuments so that
if the PDFJS extension is disabled from the command line the option to
download PDF files instead of opening them in Brave is set to ON and the
toggle is disabled.

4. Adds an alternative call for whitelisted extensions in
extensions/common/manifest_handlers/mime_types_handler.h that removes
Chrome's PDF Extension ID from whitelisted IDs and patches
chrome/browser/plugins/plugin_utils.cc to use the alternative call. This
is done because on Linux that extension is not removed from profile
enabled extensions (because there is no extensions install verification)
and it ends up being picked as a handler for PDFs. If our PDFJS extension
is disabled via command line, this causes a PDF to be neither displayed
nor downloaded.

Note, that this fix doesn't address being able to turn off opening PDFs
in Brave in Guest/Tor profiles. The web ui setting to do so is not
available in these profiles.

The command line switch to not load PDFJS already applies to all profile
types.

Adds browser tests to check that Chromium's PDF extension is not
considered for handling PDFs and if the PDFJS extension is not loaded or
disabled from command line a download is initiated when navigating to a
PDF URL. Also adds test to verify that when PDF download preference is
toggled the component loader will take an appropriate action (add or
remove PDFJS extension).
  • Loading branch information
mkarolin committed Dec 6, 2018
1 parent 20172c4 commit 06c2c83
Show file tree
Hide file tree
Showing 10 changed files with 434 additions and 4 deletions.
53 changes: 50 additions & 3 deletions browser/extensions/brave_component_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,30 @@
#include "brave/components/brave_rewards/browser/buildflags/buildflags.h"
#include "brave/components/brave_rewards/resources/extension/grit/brave_rewards_extension_resources.h"
#include "brave/components/brave_webtorrent/grit/brave_webtorrent_resources.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/grit/brave_components_resources.h"
#include "extensions/browser/extension_prefs.h"

namespace extensions {

//static
bool BraveComponentLoader::IsPdfjsDisabled() {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
return command_line.HasSwitch(switches::kDisablePDFJSExtension);
}

BraveComponentLoader::BraveComponentLoader(
ExtensionServiceInterface* extension_service,
PrefService* profile_prefs,
PrefService* local_state,
Profile* profile)
: ComponentLoader(extension_service, profile_prefs, local_state, profile),
profile_(profile) {
profile_(profile),
profile_prefs_(profile_prefs),
testing_callbacks_(nullptr) {
ObserveOpenPdfExternallySetting();
}

BraveComponentLoader::~BraveComponentLoader() {
Expand Down Expand Up @@ -73,8 +85,10 @@ void BraveComponentLoader::AddDefaultComponentExtensions(
Add(IDR_BRAVE_EXTENSON, brave_extension_path);
}

if (!command_line.HasSwitch(switches::kDisablePDFJSExtension)) {
AddExtension(pdfjs_extension_id, pdfjs_extension_name, pdfjs_extension_public_key);
if (!profile_prefs_->GetBoolean(prefs::kPluginsAlwaysOpenPdfExternally) &&
!command_line.HasSwitch(switches::kDisablePDFJSExtension)) {
AddExtension(pdfjs_extension_id, pdfjs_extension_name,
pdfjs_extension_public_key);
}

#if BUILDFLAG(BRAVE_REWARDS_ENABLED)
Expand All @@ -94,4 +108,37 @@ void BraveComponentLoader::AddDefaultComponentExtensions(
}
}

void BraveComponentLoader::ObserveOpenPdfExternallySetting() {
// Observe the setting change only in regular profiles since the PDF settings
// page is not available in Guest/Tor profiles.
DCHECK(profile_ && profile_prefs_);
if (!profile_->IsGuestSession()) {
registrar_.Init(profile_prefs_);
registrar_.Add(prefs::kPluginsAlwaysOpenPdfExternally,
base::Bind(&BraveComponentLoader::UpdatePdfExtension,
base::Unretained(this)));
}
}

void BraveComponentLoader::UpdatePdfExtension(const std::string& pref_name) {
DCHECK(pref_name == prefs::kPluginsAlwaysOpenPdfExternally);
DCHECK(profile_prefs_);
if (profile_prefs_->GetBoolean(prefs::kPluginsAlwaysOpenPdfExternally) ||
IsPdfjsDisabled()) {
if (testing_callbacks_)
testing_callbacks_->OnPdfExtensionAction(TestingCallbacks::WILL_REMOVE);
Remove(pdfjs_extension_id);
} else if (!Exists(pdfjs_extension_id)) {
if (testing_callbacks_)
testing_callbacks_->OnPdfExtensionAction(TestingCallbacks::WILL_ADD);
AddExtension(pdfjs_extension_id, pdfjs_extension_name,
pdfjs_extension_public_key);
}
}

void BraveComponentLoader::set_testing_callbacks(
TestingCallbacks* testing_callbacks) {
testing_callbacks_ = testing_callbacks;
}

} // namespace extensions
24 changes: 24 additions & 0 deletions browser/extensions/brave_component_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

#include "base/files/file_path.h"
#include "chrome/browser/extensions/component_loader.h"
#include "components/prefs/pref_change_registrar.h"

class BravePDFExtensionTest;

namespace extensions {

Expand All @@ -32,8 +35,29 @@ class BraveComponentLoader : public ComponentLoader {
void AddExtension(const std::string& id,
const std::string& name, const std::string& public_key);

static bool IsPdfjsDisabled();

private:
friend class ::BravePDFExtensionTest;
void ObserveOpenPdfExternallySetting();
// Callback for changes to the AlwaysOpenPdfExternally setting.
void UpdatePdfExtension(const std::string& pref_name);

struct TestingCallbacks {
enum PdfExtensionAction {
NONE,
WILL_ADD,
WILL_REMOVE,
};
virtual void OnPdfExtensionAction(PdfExtensionAction action) = 0;
};

void set_testing_callbacks(TestingCallbacks* testing_callbacks);

Profile* profile_;
PrefService* profile_prefs_;
PrefChangeRegistrar registrar_;
TestingCallbacks* testing_callbacks_;
DISALLOW_COPY_AND_ASSIGN(BraveComponentLoader);
};

Expand Down
84 changes: 84 additions & 0 deletions browser/extensions/brave_component_loader_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "brave/browser/extensions/brave_component_loader.h"
#include "brave/browser/extensions/brave_extension_functional_test.h"
#include "brave/common/brave_switches.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

using extensions::BraveComponentLoader;

class BravePDFExtensionTest : public extensions::ExtensionFunctionalTest,
public BraveComponentLoader::TestingCallbacks {
public:
BravePDFExtensionTest() : pdf_extension_action_(TestingCallbacks::NONE) {}
~BravePDFExtensionTest() override = default;

protected:
void SetUpOnMainThread() override {
extensions::ExtensionService* service =
extensions::ExtensionSystem::Get(profile())->extension_service();
DCHECK(service);
(static_cast<BraveComponentLoader*>(service->component_loader()))
->set_testing_callbacks(this);
}

// BraveComponentLoader::TestingCallbacks
void OnPdfExtensionAction(
TestingCallbacks::PdfExtensionAction action) override {
pdf_extension_action_ = action;
}

void SetDownloadPDFs(bool value) {
DCHECK(browser());
profile()->GetPrefs()->SetBoolean(prefs::kPluginsAlwaysOpenPdfExternally,
value);
}

TestingCallbacks::PdfExtensionAction pdf_extension_action() {
return pdf_extension_action_;
}

private:
TestingCallbacks::PdfExtensionAction pdf_extension_action_;
};

IN_PROC_BROWSER_TEST_F(BravePDFExtensionTest, ToggleDownloadPDFs) {
// Set preference to always download PDFs.
SetDownloadPDFs(true);
EXPECT_EQ(TestingCallbacks::WILL_REMOVE, pdf_extension_action());

// Toggle the preference to view PDFs in the browser.
SetDownloadPDFs(false);
EXPECT_EQ(TestingCallbacks::WILL_ADD, pdf_extension_action());
}

class BravePDFExtensionDisabledTest : public BravePDFExtensionTest {
public:
BravePDFExtensionDisabledTest() = default;
~BravePDFExtensionDisabledTest() override = default;

protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
ExtensionFunctionalTest::SetUpCommandLine(command_line);
// Disable loading of our PDF extension.
command_line->AppendSwitch(switches::kDisablePDFJSExtension);
}
};

IN_PROC_BROWSER_TEST_F(BravePDFExtensionDisabledTest, ToggleDownloadPDFs) {
// Set preference to always download PDFs.
SetDownloadPDFs(true);
EXPECT_EQ(TestingCallbacks::WILL_REMOVE, pdf_extension_action());

// Toggle the preference to view PDFs in the browser.
SetDownloadPDFs(false);
EXPECT_EQ(TestingCallbacks::WILL_REMOVE, pdf_extension_action());
}
6 changes: 5 additions & 1 deletion browser/ui/webui/brave_md_settings_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "brave/browser/ui/webui/brave_md_settings_ui.h"

#include "brave/browser/extensions/brave_component_loader.h"
#include "brave/browser/resources/grit/brave_settings_resources.h"
#include "brave/browser/resources/grit/brave_settings_resources_map.h"
#include "brave/browser/ui/webui/settings/brave_privacy_handler.h"
Expand All @@ -26,8 +27,11 @@ BraveMdSettingsUI::~BraveMdSettingsUI() {
// static
void BraveMdSettingsUI::AddResources(content::WebUIDataSource* html_source,
Profile* profile) {
for (size_t i = 0; i < kBraveSettingsResourcesSize; ++i) {
for (size_t i = 0; i < kBraveSettingsResourcesSize; ++i) {
html_source->AddResourcePath(kBraveSettingsResources[i].name,
kBraveSettingsResources[i].value);
}

html_source->AddBoolean("isPdfjsDisabled",
extensions::BraveComponentLoader::IsPdfjsDisabled());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "../../../../extensions/common/manifest_handlers/mime_types_handler.cc"

// static
std::vector<std::string> MimeTypesHandler::BraveGetMIMETypeWhitelist() {
std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
auto pos = std::find(whitelist.begin(), whitelist.end(),
extension_misc::kPdfExtensionId);
if (pos != whitelist.end())
whitelist.erase(pos);
return whitelist;
}

Loading

0 comments on commit 06c2c83

Please sign in to comment.