Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: src/engine/Main.cpp

Issue 5447868882092032: Issue 1793 - check whether the frame is whitelisted before injecting CSS (Closed)
Left Patch Set: rebase and address comments Created April 13, 2015, 7:31 a.m.
Right Patch Set: rebase and rename webBrowser to parentBrowser Created Nov. 30, 2015, 3:27 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/plugin/AdblockPlusClient.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #pragma comment(linker,"\"/manifestdependency:type='win32' \
19 name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
20 processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
21
18 #include <AdblockPlus.h> 22 #include <AdblockPlus.h>
19 #include <functional> 23 #include <functional>
20 #include <vector> 24 #include <vector>
25 #include <deque>
21 #include <thread> 26 #include <thread>
27 #include <mutex>
28 #include <condition_variable>
22 #include <Windows.h> 29 #include <Windows.h>
23 30
24 #include "../shared/AutoHandle.h" 31 #include "../shared/AutoHandle.h"
25 #include "../shared/Communication.h" 32 #include "../shared/Communication.h"
26 #include "../shared/Dictionary.h" 33 #include "../shared/Dictionary.h"
27 #include "../shared/Utils.h" 34 #include "../shared/Utils.h"
28 #include "../shared/Version.h" 35 #include "../shared/Version.h"
29 #include "../shared/CriticalSection.h" 36 #include "../shared/CriticalSection.h"
30 #include "../shared/IE_version.h" 37 #include "IeVersion.h"
31 #include "AdblockPlus.h" 38 #include "AdblockPlus.h"
32 #include "Debug.h" 39 #include "Debug.h"
33 #include "Updater.h" 40 #include "Updater.h"
41 #include "Registry.h"
42 #include "NotificationWindow.h"
34 43
35 namespace 44 namespace
36 { 45 {
46 struct ScopedAtlAxInitializer
47 {
48 ScopedAtlAxInitializer()
49 {
50 ATL::AtlAxWinInit();
51 }
52 ~ScopedAtlAxInitializer()
53 {
54 ATL::AtlAxWinTerm();
55 }
56 };
57
58 class ABPAtlModule : public ATL::CAtlExeModuleT<ABPAtlModule>
59 {
60 enum CustomMessages
61 {
62 TASK_POSTED = WM_USER + 1
63 };
64
65 public:
66 ABPAtlModule() : m_msgHWnd(nullptr)
67 {
68 }
69 void Finalize();
70 HRESULT PreMessageLoop(int showCmd) throw();
71 void RunMessageLoop() throw();
72 static HRESULT InitializeCom() throw()
73 {
74 // The default implementation initializes multithreaded version but
75 // in this case hosted ActiveX does not properly work.
76 return CoInitialize(nullptr);
77 }
78 private:
79 void onNewNotification(const AdblockPlus::NotificationPtr& notification);
80 void DispatchTask(std::function<void()>&& task);
81 void ProcessTasks();
82
83 ScopedAtlAxInitializer m_scopedAtlAxInit;
84 HWND m_msgHWnd;
85 std::recursive_mutex m_tasksMutex;
86 std::deque<std::function<void()>> m_tasks;
87 std::unique_ptr<NotificationBorderWindow> m_notificationWindow;
88 } _AtlModule;
89
37 std::auto_ptr<AdblockPlus::FilterEngine> filterEngine; 90 std::auto_ptr<AdblockPlus::FilterEngine> filterEngine;
38 std::auto_ptr<Updater> updater; 91 std::auto_ptr<Updater> updater;
39 int activeConnections = 0; 92 int activeConnections = 0;
40 CriticalSection activeConnectionsLock; 93 CriticalSection activeConnectionsLock;
41 HWND callbackWindow; 94 HWND callbackWindow;
42 95
96 // it's a helper for the function below.
97 std::string GetWhitelistingFilter(const std::string& url, const std::string& p arent, AdblockPlus::FilterEngine::ContentType type)
98 {
99 AdblockPlus::FilterPtr match = filterEngine->Matches(url, type, parent);
100 if (match && match->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION)
101 {
102 return match->GetProperty("text")->AsString();
103 }
104 return "";
105 };
106
43 std::string GetWhitelistingFilter(const std::string& urlArg, 107 std::string GetWhitelistingFilter(const std::string& urlArg,
44 const std::vector<std::string>& frameHierarchy, AdblockPlus::FilterEngine::C ontentType type) 108 const std::vector<std::string>& frameHierarchy, AdblockPlus::FilterEngine::C ontentType type)
45 { 109 {
46 auto GetWhitelistingFilter = [&type](const std::string& url, const std::stri ng& parent)->std::string
Eric 2015/05/14 17:07:26 Code style comment. It's not a good idea to use t
sergei 2015/05/15 11:55:55 extracted as a separate function.
47 {
48 AdblockPlus::FilterPtr match = filterEngine->Matches(url, type, parent);
49 if (match && match->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION)
50 {
51 return match->GetProperty("text")->AsString();
52 }
53 return "";
54 };
Eric 2015/05/14 17:07:26 The whole loop below would be clearer if implement
sergei 2015/05/15 11:55:55 It seems such overhead will only complicate it.
55 if (frameHierarchy.empty()) 110 if (frameHierarchy.empty())
56 { 111 {
57 return GetWhitelistingFilter(urlArg, ""); 112 return GetWhitelistingFilter(urlArg, "", type);
58 } 113 }
59 auto frameIterator = frameHierarchy.begin(); 114 auto frameIterator = frameHierarchy.begin();
60 std::string parentUrl;
61 std::string url = urlArg; 115 std::string url = urlArg;
62 while (frameIterator != frameHierarchy.end()) 116 do
63 { 117 {
64 parentUrl = *frameIterator; 118 std::string parentUrl = *frameIterator++;
65 auto filterText = GetWhitelistingFilter(url, parentUrl); 119 auto filterText = GetWhitelistingFilter(url, parentUrl, type);
66 if (!filterText.empty()) 120 if (!filterText.empty())
67 { 121 {
68 return filterText; 122 return filterText;
69 } 123 }
70 url = parentUrl; 124 url = parentUrl;
71 ++frameIterator; 125 }
72 } 126 while (frameIterator != frameHierarchy.end());
73 return ""; 127 return "";
74 } 128 }
75 129
76 void WriteSubscriptions(Communication::OutputBuffer& response, 130 void WriteSubscriptions(Communication::OutputBuffer& response,
77 const std::vector<AdblockPlus::SubscriptionPtr>& subscriptions) 131 const std::vector<AdblockPlus::SubscriptionPtr>& subscriptions)
78 { 132 {
79 int32_t count = static_cast<int32_t>(subscriptions.size()); 133 int32_t count = static_cast<int32_t>(subscriptions.size());
80 response << count; 134 response << count;
81 for (int32_t i = 0; i < count; i++) 135 for (int32_t i = 0; i < count; i++)
82 { 136 {
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 486
433 Debug("Client disconnected " + threadString); 487 Debug("Client disconnected " + threadString);
434 488
435 { 489 {
436 CriticalSection::Lock lock(activeConnectionsLock); 490 CriticalSection::Lock lock(activeConnectionsLock);
437 activeConnections--; 491 activeConnections--;
438 if (activeConnections < 1) 492 if (activeConnections < 1)
439 { 493 {
440 Debug("No connections left, shutting down the engine"); 494 Debug("No connections left, shutting down the engine");
441 activeConnections = 0; 495 activeConnections = 0;
496
497 // The following exit(0) calls the destructor of _AtlModule from the
498 // current thread which results in the disaster because there is a
499 // running message loop as well as there can be alive notification
500 // window which holds v8::Value as well as m_tasks can hold v8::Value
501 // but JS Engine is destroyed before _AtlModule. BTW, various free
502 // running threads like Timeout also cause the crash because the engine
503 // is already destroyed.
504 _AtlModule.Finalize();
442 exit(0); 505 exit(0);
443 } 506 }
444 } 507 }
445 508
446 } 509 }
447 510
448 void OnUpdateAvailable(AdblockPlus::JsValueList& params) 511 void OnUpdateAvailable(AdblockPlus::JsValueList& params)
449 { 512 {
450 if (params.size() < 1) 513 if (params.size() < 1)
451 { 514 {
452 Debug("updateAvailable event missing URL"); 515 Debug("updateAvailable event missing URL");
453 return; 516 return;
454 } 517 }
455 updateAvailable = true; 518 updateAvailable = true;
456 519
457 updater->Update(params[0]->AsString()); 520 updater->Update(params[0]->AsString());
458 } 521 }
459 } 522
523 std::wstring PreconfigurationValueFromRegistry(const std::wstring& preconfigNa me)
524 {
525 try
526 {
527 AdblockPlus::RegistryKey regKey(HKEY_CURRENT_USER, L"Software\\AdblockPlus ");
528 return regKey.value_wstring(preconfigName);
529 }
530 catch (const std::runtime_error&)
531 {
532 return L"";
533 }
534 }
460 535
461 std::auto_ptr<AdblockPlus::FilterEngine> CreateFilterEngine(const std::wstring& locale) 536 std::auto_ptr<AdblockPlus::FilterEngine> CreateFilterEngine(const std::wstring& locale)
462 { 537 {
463 AdblockPlus::AppInfo appInfo; 538 AdblockPlus::AppInfo appInfo;
464 appInfo.version = ToUtf8String(IEPLUGIN_VERSION); 539 appInfo.version = ToUtf8String(IEPLUGIN_VERSION);
465 appInfo.name = "adblockplusie"; 540 appInfo.name = "adblockplusie";
466 #ifdef _WIN64 541 #ifdef _WIN64
467 appInfo.application = "msie64"; 542 appInfo.application = "msie64";
468 #else 543 #else
469 appInfo.application = "msie32"; 544 appInfo.application = "msie32";
470 #endif 545 #endif
471 appInfo.applicationVersion = ToUtf8String(AdblockPlus::IE::InstalledVersionStr ing()); 546 appInfo.applicationVersion = ToUtf8String(AdblockPlus::IE::InstalledVersionStr ing());
472 appInfo.locale = ToUtf8String(locale); 547 appInfo.locale = ToUtf8String(locale);
473 #ifdef ADBLOCK_PLUS_TEST_MODE 548 #ifdef ADBLOCK_PLUS_TEST_MODE
474 appInfo.developmentBuild = true; 549 appInfo.developmentBuild = true;
475 #else 550 #else
476 appInfo.developmentBuild = false; 551 appInfo.developmentBuild = false;
477 #endif 552 #endif
478 553
479 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::New(appInfo); 554 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::New(appInfo);
480 jsEngine->SetEventCallback("updateAvailable", &OnUpdateAvailable); 555 jsEngine->SetEventCallback("updateAvailable", &OnUpdateAvailable);
481 556
482 std::string dataPath = ToUtf8String(GetAppDataPath()); 557 std::string dataPath = ToUtf8String(GetAppDataPath());
483 dynamic_cast<AdblockPlus::DefaultFileSystem*>(jsEngine->GetFileSystem().get()) ->SetBasePath(dataPath); 558 dynamic_cast<AdblockPlus::DefaultFileSystem*>(jsEngine->GetFileSystem().get()) ->SetBasePath(dataPath);
484 std::auto_ptr<AdblockPlus::FilterEngine> filterEngine(new AdblockPlus::FilterE ngine(jsEngine)); 559 std::map<std::string, AdblockPlus::JsValuePtr> preconfig;
560 preconfig["disable_auto_updates"] = jsEngine->NewValue(
561 PreconfigurationValueFromRegistry(L"disable_auto_updates") == L"true");
562 preconfig["suppress_first_run_page"] = jsEngine->NewValue(
563 PreconfigurationValueFromRegistry(L"suppress_first_run_page") == L"true");
564 std::auto_ptr<AdblockPlus::FilterEngine> filterEngine(new AdblockPlus::FilterE ngine(jsEngine, preconfig));
485 return filterEngine; 565 return filterEngine;
486 } 566 }
487 567
488 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) 568 void ABPAtlModule::Finalize()
569 {
570 std::condition_variable cv;
571 std::mutex cvMutex;
572 std::unique_lock<std::mutex> lock(cvMutex);
573 DispatchTask([&cvMutex, &cv, this]
574 {
575 if (m_notificationWindow)
576 {
577 m_notificationWindow->SendMessage(WM_CLOSE);
578 }
579 SendMessage(m_msgHWnd, WM_QUIT, 0, 0);
580 {
581 std::lock_guard<std::recursive_mutex> lock(m_tasksMutex);
582 m_tasks.clear();
583 }
584 std::unique_lock<std::mutex> lock(cvMutex);
585 cv.notify_one();
586 });
587 cv.wait(lock);
588 }
589
590 HRESULT ABPAtlModule::PreMessageLoop(int showCmd) throw()
591 {
592 const std::wstring className = L"ABPEngineMessageWindow";
593 WNDCLASS wc;
594 wc.style = 0;
595 wc.lpfnWndProc = DefWindowProcW;
596 wc.cbClsExtra = 0;
597 wc.cbWndExtra = 0;
598 wc.hInstance = ATL::_AtlBaseModule.GetModuleInstance();
599 wc.hIcon = nullptr;
600 wc.hCursor = nullptr;
601 wc.hbrBackground = nullptr;
602 wc.lpszMenuName = nullptr;
603 wc.lpszClassName = className.c_str();
604 ATOM atom = RegisterClass(&wc);
605 if (!atom)
606 {
607 DebugLastError("Cannot register class for message only window");
608 return E_FAIL;
609 }
610 m_msgHWnd = CreateWindowW(className.c_str(),
611 nullptr, // window name
612 0, // style
613 0, 0, 0, 0, // geometry (x, y, w, h)
614 HWND_MESSAGE, // parent
615 nullptr, // menu handle
616 wc.hInstance,
617 0); // windows creation data.
618 if (!m_msgHWnd)
619 {
620 DebugLastError("Cannot create message only window");
621 return E_FAIL;
622 }
623
624 filterEngine->SetShowNotificationCallback([this](const AdblockPlus::Notificati onPtr& notification)
625 {
626 if (!notification)
627 {
628 return;
629 }
630 DispatchTask([notification, this]
631 {
632 onNewNotification(notification);
633 });
634 });
635
636 HRESULT retValue = __super::PreMessageLoop(showCmd);
637 // __super::PreMessageLoop returns S_FALSE because there is nothing to
638 // register but S_OK is required to run message loop.
639 return FAILED(retValue) ? retValue : S_OK;
640 }
641
642 void ABPAtlModule::RunMessageLoop() throw()
643 {
644 MSG msg = {};
645 while (GetMessage(&msg, /*hwnd*/nullptr, /*msgFilterMin*/0, /*msgFilterMax*/0) )
646 {
647 if (msg.hwnd == m_msgHWnd && msg.message == CustomMessages::TASK_POSTED)
648 {
649 ProcessTasks();
650 }
651 TranslateMessage(&msg);
652 DispatchMessage(&msg);
653 }
654 }
655
656 void ABPAtlModule::onNewNotification(const AdblockPlus::NotificationPtr& notific ation)
657 {
658 m_notificationWindow.reset(new NotificationBorderWindow(*notification, GetExeD ir() + L"html\\templates\\"));
659 m_notificationWindow->SetOnDestroyed([notification, this]
660 {
661 notification->MarkAsShown();
662 m_notificationWindow.reset();
663 });
664 m_notificationWindow->SetOnLinkClicked([](const std::wstring& url)
665 {
666 ATL::CComPtr<IWebBrowser2> webBrowser;
667 if (SUCCEEDED(webBrowser.CoCreateInstance(__uuidof(InternetExplorer))) && we bBrowser)
668 {
669 ATL::CComVariant emptyVariant;
670 webBrowser->Navigate(ATL::CComBSTR(url.c_str()), &emptyVariant, &emptyVari ant, &emptyVariant, &emptyVariant);
671 webBrowser->put_Visible(VARIANT_TRUE);
672 }
673 });
674 m_notificationWindow->Create(/*parent window*/nullptr);
675 if (m_notificationWindow->operator HWND() != nullptr)
676 {
677 m_notificationWindow->ShowWindow(SW_SHOWNOACTIVATE);
678 m_notificationWindow->UpdateWindow();
679 }
680 }
681
682 void ABPAtlModule::DispatchTask(std::function<void()>&& task)
683 {
684 {
685 std::lock_guard<std::recursive_mutex> lock(m_tasksMutex);
686 m_tasks.emplace_back(std::move(task));
687 }
688 PostMessageW(m_msgHWnd, CustomMessages::TASK_POSTED, 0, 0);
689 }
690
691 void ABPAtlModule::ProcessTasks()
692 {
693 std::lock_guard<std::recursive_mutex> lock(m_tasksMutex);
694 while(!m_tasks.empty())
695 {
696 auto task = *m_tasks.begin();
697 m_tasks.pop_front();
698 if (task)
699 task();
700 }
701 }
702
703 } // namespace {
704
705 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int cmdShow)
489 { 706 {
490 AutoHandle mutex(CreateMutexW(0, false, L"AdblockPlusEngine")); 707 AutoHandle mutex(CreateMutexW(0, false, L"AdblockPlusEngine"));
491 if (!mutex) 708 if (!mutex)
492 { 709 {
493 DebugLastError("CreateMutex failed"); 710 DebugLastError("CreateMutex failed");
494 return 1; 711 return 1;
495 } 712 }
496 713
497 if (GetLastError() == ERROR_ALREADY_EXISTS) 714 if (GetLastError() == ERROR_ALREADY_EXISTS)
498 { 715 {
499 DebugLastError("Named pipe exists, another engine instance appears to be run ning"); 716 DebugLastError("Named pipe exists, another engine instance appears to be run ning");
500 return 1; 717 return 1;
501 } 718 }
502 719
503 int argc; 720 int argc;
504 LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); 721 LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
505 std::wstring locale(argc >= 2 ? argv[1] : L""); 722 std::wstring locale(argc >= 2 ? argv[1] : L"");
506 LocalFree(argv); 723 LocalFree(argv);
507 Dictionary::Create(locale); 724 Dictionary::Create(locale);
508 filterEngine = CreateFilterEngine(locale); 725 filterEngine = CreateFilterEngine(locale);
509 updater.reset(new Updater(filterEngine->GetJsEngine())); 726 updater.reset(new Updater(filterEngine->GetJsEngine()));
510 727
511 for (;;) 728 std::thread communicationThread([]
512 { 729 {
513 try 730 for (;;)
514 { 731 {
515 auto pipe = std::make_shared<Communication::Pipe>(Communication::pipeName, Communication::Pipe::MODE_CREATE); 732 try
516 733 {
517 // TODO: we should wait for the finishing of the thread before exiting fro m this function. 734 auto pipe = std::make_shared<Communication::Pipe>(Communication::pipeNam e, Communication::Pipe::MODE_CREATE);
518 // It works now in most cases because the browser waits for the response i n the pipe, and the 735
519 // thread has time to finish while this response is being processed and th e browser is 736 // TODO: we should wait for the finishing of the thread before exiting f rom this function.
520 // disposing all its stuff. 737 // It works now in most cases because the browser waits for the response in the pipe, and the
521 std::thread([pipe]() 738 // thread has time to finish while this response is being processed and the browser is
522 { 739 // disposing all its stuff.
523 ClientThread(pipe.get()); 740 std::thread([pipe]()
524 }).detach(); 741 {
525 } 742 ClientThread(pipe.get());
526 catch(const std::system_error& ex) 743 }).detach();
527 { 744 }
528 DebugException(ex); 745 catch(const std::system_error& ex)
529 return 1; 746 {
530 } 747 DebugException(ex);
531 catch (const std::runtime_error& e) 748 return 1;
532 { 749 }
533 DebugException(e); 750 catch (const std::runtime_error& e)
534 return 1; 751 {
535 } 752 DebugException(e);
536 } 753 return 1;
537 754 }
538 return 0; 755 }
756 });
757
758 int retValue = _AtlModule.WinMain(cmdShow);
759 if (communicationThread.joinable())
760 {
761 communicationThread.join();
762 }
763
764 return retValue;
539 } 765 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld