OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/enumerate_modules_model_win.h" | 5 #include "chrome/browser/enumerate_modules_model_win.h" |
6 | 6 |
7 #include <Tlhelp32.h> | 7 #include <Tlhelp32.h> |
8 #include <wintrust.h> | 8 #include <wintrust.h> |
9 | 9 |
10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
11 #include "app/win/win_util.h" | 11 #include "app/win/win_util.h" |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 | 119 |
120 // idmmbc.dll (IDM), "%systemroot%\\system32\\". See: http://crbug.com/26892/. | 120 // idmmbc.dll (IDM), "%systemroot%\\system32\\". See: http://crbug.com/26892/. |
121 { "b8dce5c3", "23d01d5b", "", "", "6.03", | 121 { "b8dce5c3", "23d01d5b", "", "", "6.03", |
122 static_cast<RecommendedAction>(UPDATE | DISABLE) }, | 122 static_cast<RecommendedAction>(UPDATE | DISABLE) }, |
123 | 123 |
124 // imon.dll (NOD32), "%systemroot%\\system32\\". See: http://crbug.com/21715. | 124 // imon.dll (NOD32), "%systemroot%\\system32\\". See: http://crbug.com/21715. |
125 { "8f42f22e", "23d01d5b", "", "", "4.0", | 125 { "8f42f22e", "23d01d5b", "", "", "4.0", |
126 static_cast<RecommendedAction>(UPDATE | DISABLE) }, | 126 static_cast<RecommendedAction>(UPDATE | DISABLE) }, |
127 | 127 |
128 // is3lsp.dll, "%commonprogramfiles%\\is3\\anti-spyware\\". | 128 // is3lsp.dll, "%commonprogramfiles%\\is3\\anti-spyware\\". |
129 { "7ffbdce9", "bc5673f2", "", "", "", INVESTIGATING }, | 129 { "7ffbdce9", "bc5673f2", "", "", "", |
| 130 static_cast<RecommendedAction>(UPDATE | DISABLE | SEE_LINK) }, |
130 | 131 |
131 // jsi.dll, "%programfiles%\\profilecraze\\". | 132 // jsi.dll, "%programfiles%\\profilecraze\\". |
132 { "f9555eea", "e3548061", "", "", "", kUninstallLink }, | 133 { "f9555eea", "e3548061", "", "", "", kUninstallLink }, |
133 | 134 |
134 // kernel.dll, "%programfiles%\\contentwatch\\internet protection\\modules\\". | 135 // kernel.dll, "%programfiles%\\contentwatch\\internet protection\\modules\\". |
135 { "ead2768e", "4e61ce60", "", "", "", INVESTIGATING }, | 136 { "ead2768e", "4e61ce60", "", "", "", INVESTIGATING }, |
136 | 137 |
137 // mgking0.dll, "%systemroot%\\system32\\". | 138 // mgking0.dll, "%systemroot%\\system32\\". |
138 { "d0893e38", "23d01d5b", "", "", "", kUninstallLink }, | 139 { "d0893e38", "23d01d5b", "", "", "", kUninstallLink }, |
139 | 140 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 | 285 |
285 if (version_ok) { | 286 if (version_ok) { |
286 // At this point, the names match and there is no version specified | 287 // At this point, the names match and there is no version specified |
287 // or the versions also match. | 288 // or the versions also match. |
288 | 289 |
289 std::string desc_or_signer(blacklisted.desc_or_signer); | 290 std::string desc_or_signer(blacklisted.desc_or_signer); |
290 std::string signer_hash, description_hash; | 291 std::string signer_hash, description_hash; |
291 GenerateHash(WideToUTF8(module.digital_signer), &signer_hash); | 292 GenerateHash(WideToUTF8(module.digital_signer), &signer_hash); |
292 GenerateHash(WideToUTF8(module.description), &description_hash); | 293 GenerateHash(WideToUTF8(module.description), &description_hash); |
293 | 294 |
294 // If signatures match, we have a winner. | 295 // If signatures match (or both are empty), then we have a winner. |
295 if (!desc_or_signer.empty() && signer_hash == desc_or_signer) | 296 if (signer_hash == desc_or_signer) |
296 return CONFIRMED_BAD; | 297 return CONFIRMED_BAD; |
297 | 298 |
298 // If description matches and location, then we also have a match. | 299 // If descriptions match (or both are empty) and the locations match, then |
299 if (!desc_or_signer.empty() && description_hash == desc_or_signer && | 300 // we also have a confirmed match. |
| 301 if (description_hash == desc_or_signer && |
300 !location_hash.empty() && location_hash == blacklisted.location) { | 302 !location_hash.empty() && location_hash == blacklisted.location) { |
301 return CONFIRMED_BAD; | 303 return CONFIRMED_BAD; |
302 } | 304 } |
303 | 305 |
304 // We are not sure, but it is likely bad. | 306 // We are not sure, but it is likely bad. |
305 return SUSPECTED_BAD; | 307 return SUSPECTED_BAD; |
306 } | 308 } |
307 } | 309 } |
308 | 310 |
309 return NOT_MATCHED; | 311 return NOT_MATCHED; |
310 } | 312 } |
311 | 313 |
312 ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer) | 314 ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer) |
313 : observer_(observer), | 315 : observer_(observer), |
| 316 limited_mode_(false), |
314 callback_thread_id_(BrowserThread::ID_COUNT) { | 317 callback_thread_id_(BrowserThread::ID_COUNT) { |
315 } | 318 } |
316 | 319 |
317 ModuleEnumerator::~ModuleEnumerator() { | 320 ModuleEnumerator::~ModuleEnumerator() { |
318 } | 321 } |
319 | 322 |
320 void ModuleEnumerator::ScanNow(ModulesVector* list) { | 323 void ModuleEnumerator::ScanNow(ModulesVector* list, bool limited_mode) { |
321 CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_)); | |
322 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
323 enumerated_modules_ = list; | 324 enumerated_modules_ = list; |
324 BrowserThread::PostTask( | 325 |
325 BrowserThread::FILE, FROM_HERE, | 326 limited_mode_ = limited_mode; |
326 NewRunnableMethod(this, &ModuleEnumerator::ScanOnFileThread)); | 327 |
| 328 if (!limited_mode_) { |
| 329 CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_)); |
| 330 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 331 BrowserThread::PostTask( |
| 332 BrowserThread::FILE, FROM_HERE, |
| 333 NewRunnableMethod(this, &ModuleEnumerator::ScanImpl)); |
| 334 } else { |
| 335 // Run it synchronously. |
| 336 ScanImpl(); |
| 337 } |
327 } | 338 } |
328 | 339 |
329 void ModuleEnumerator::ScanOnFileThread() { | 340 void ModuleEnumerator::ScanImpl() { |
330 base::TimeTicks start_time = base::TimeTicks::Now(); | 341 base::TimeTicks start_time = base::TimeTicks::Now(); |
331 | 342 |
332 enumerated_modules_->clear(); | 343 enumerated_modules_->clear(); |
333 | 344 |
334 // Make sure the path mapping vector is setup so we can collapse paths. | 345 // Make sure the path mapping vector is setup so we can collapse paths. |
335 PreparePathMappings(); | 346 PreparePathMappings(); |
336 | 347 |
337 base::TimeTicks checkpoint = base::TimeTicks::Now(); | 348 base::TimeTicks checkpoint = base::TimeTicks::Now(); |
338 | 349 |
339 // Enumerating loaded modules must happen first since the other types of | 350 // Enumerating loaded modules must happen first since the other types of |
(...skipping 10 matching lines...) Expand all Loading... |
350 checkpoint = base::TimeTicks::Now(); | 361 checkpoint = base::TimeTicks::Now(); |
351 EnumerateWinsockModules(); | 362 EnumerateWinsockModules(); |
352 HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules", | 363 HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules", |
353 base::TimeTicks::Now() - checkpoint); | 364 base::TimeTicks::Now() - checkpoint); |
354 | 365 |
355 MatchAgainstBlacklist(); | 366 MatchAgainstBlacklist(); |
356 | 367 |
357 std::sort(enumerated_modules_->begin(), | 368 std::sort(enumerated_modules_->begin(), |
358 enumerated_modules_->end(), ModuleSort); | 369 enumerated_modules_->end(), ModuleSort); |
359 | 370 |
360 // Send a reply back on the UI thread. | 371 if (!limited_mode_) { |
361 BrowserThread::PostTask( | 372 // Send a reply back on the UI thread. |
362 callback_thread_id_, FROM_HERE, | 373 BrowserThread::PostTask( |
363 NewRunnableMethod(this, &ModuleEnumerator::ReportBack)); | 374 callback_thread_id_, FROM_HERE, |
| 375 NewRunnableMethod(this, &ModuleEnumerator::ReportBack)); |
| 376 } else { |
| 377 // We are on the main thread already. |
| 378 ReportBack(); |
| 379 } |
364 | 380 |
365 HISTOGRAM_TIMES("Conflicts.EnumerationTotalTime", | 381 HISTOGRAM_TIMES("Conflicts.EnumerationTotalTime", |
366 base::TimeTicks::Now() - start_time); | 382 base::TimeTicks::Now() - start_time); |
367 } | 383 } |
368 | 384 |
369 void ModuleEnumerator::EnumerateLoadedModules() { | 385 void ModuleEnumerator::EnumerateLoadedModules() { |
370 // Get all modules in the current process. | 386 // Get all modules in the current process. |
371 ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, | 387 ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, |
372 ::GetCurrentProcessId())); | 388 ::GetCurrentProcessId())); |
373 if (!snap.Get()) | 389 if (!snap.Get()) |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 if (module->status == NOT_MATCHED || module->status == GOOD) { | 593 if (module->status == NOT_MATCHED || module->status == GOOD) { |
578 if (StartsWith(module->location, L"%temp%", false) || | 594 if (StartsWith(module->location, L"%temp%", false) || |
579 StartsWith(module->location, L"%tmp%", false)) { | 595 StartsWith(module->location, L"%tmp%", false)) { |
580 module->status = SUSPECTED_BAD; | 596 module->status = SUSPECTED_BAD; |
581 } | 597 } |
582 } | 598 } |
583 } | 599 } |
584 } | 600 } |
585 | 601 |
586 void ModuleEnumerator::ReportBack() { | 602 void ModuleEnumerator::ReportBack() { |
587 DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_)); | 603 if (!limited_mode_) |
| 604 DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_)); |
588 observer_->DoneScanning(); | 605 observer_->DoneScanning(); |
589 } | 606 } |
590 | 607 |
591 string16 ModuleEnumerator::GetSubjectNameFromDigitalSignature( | 608 string16 ModuleEnumerator::GetSubjectNameFromDigitalSignature( |
592 const FilePath& filename) { | 609 const FilePath& filename) { |
593 HCERTSTORE store = NULL; | 610 HCERTSTORE store = NULL; |
594 HCRYPTMSG message = NULL; | 611 HCRYPTMSG message = NULL; |
595 | 612 |
596 // Find the crypto message for this filename. | 613 // Find the crypto message for this filename. |
597 bool result = !!CryptQueryObject(CERT_QUERY_OBJECT_FILE, | 614 bool result = !!CryptQueryObject(CERT_QUERY_OBJECT_FILE, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 return; // A scan is already in progress. | 704 return; // A scan is already in progress. |
688 | 705 |
689 lock->Acquire(); // Balanced in DoneScanning(); | 706 lock->Acquire(); // Balanced in DoneScanning(); |
690 | 707 |
691 scanning_ = true; | 708 scanning_ = true; |
692 | 709 |
693 // Instruct the ModuleEnumerator class to load this on the File thread. | 710 // Instruct the ModuleEnumerator class to load this on the File thread. |
694 // ScanNow does not block. | 711 // ScanNow does not block. |
695 if (!module_enumerator_) | 712 if (!module_enumerator_) |
696 module_enumerator_ = new ModuleEnumerator(this); | 713 module_enumerator_ = new ModuleEnumerator(this); |
697 module_enumerator_->ScanNow(&enumerated_modules_); | 714 module_enumerator_->ScanNow(&enumerated_modules_, limited_mode_); |
698 } | 715 } |
699 | 716 |
700 ListValue* EnumerateModulesModel::GetModuleList() { | 717 ListValue* EnumerateModulesModel::GetModuleList() { |
701 if (scanning_) | 718 if (scanning_) |
702 return NULL; | 719 return NULL; |
703 | 720 |
704 lock->Acquire(); | 721 lock->Acquire(); |
705 | 722 |
706 if (enumerated_modules_.empty()) { | 723 if (enumerated_modules_.empty()) { |
707 lock->Release(); | 724 lock->Release(); |
(...skipping 12 matching lines...) Expand all Loading... |
720 // Module is not loaded, denote type of module. | 737 // Module is not loaded, denote type of module. |
721 if (module->type & ModuleEnumerator::SHELL_EXTENSION) | 738 if (module->type & ModuleEnumerator::SHELL_EXTENSION) |
722 type_string = ASCIIToWide("Shell Extension"); | 739 type_string = ASCIIToWide("Shell Extension"); |
723 if (module->type & ModuleEnumerator::WINSOCK_MODULE_REGISTRATION) { | 740 if (module->type & ModuleEnumerator::WINSOCK_MODULE_REGISTRATION) { |
724 if (!type_string.empty()) | 741 if (!type_string.empty()) |
725 type_string += ASCIIToWide(", "); | 742 type_string += ASCIIToWide(", "); |
726 type_string += ASCIIToWide("Winsock"); | 743 type_string += ASCIIToWide("Winsock"); |
727 } | 744 } |
728 // Must be one of the above type. | 745 // Must be one of the above type. |
729 DCHECK(!type_string.empty()); | 746 DCHECK(!type_string.empty()); |
730 type_string += ASCIIToWide(" -- "); | 747 if (!limited_mode_) { |
731 type_string += l10n_util::GetStringUTF16(IDS_CONFLICTS_NOT_LOADED_YET); | 748 type_string += ASCIIToWide(" -- "); |
| 749 type_string += l10n_util::GetStringUTF16(IDS_CONFLICTS_NOT_LOADED_YET); |
| 750 } |
732 } | 751 } |
733 data->SetString("type_description", type_string); | 752 data->SetString("type_description", type_string); |
734 data->SetInteger("status", module->status); | 753 data->SetInteger("status", module->status); |
735 data->SetString("location", module->location); | 754 data->SetString("location", module->location); |
736 data->SetString("name", module->name); | 755 data->SetString("name", module->name); |
737 data->SetString("product_name", module->product_name); | 756 data->SetString("product_name", module->product_name); |
738 data->SetString("description", module->description); | 757 data->SetString("description", module->description); |
739 data->SetString("version", module->version); | 758 data->SetString("version", module->version); |
740 data->SetString("digital_signer", module->digital_signer); | 759 data->SetString("digital_signer", module->digital_signer); |
741 | 760 |
742 // Figure out the possible resolution help string. | 761 if (!limited_mode_) { |
743 string16 actions; | 762 // Figure out the possible resolution help string. |
744 string16 separator = ASCIIToWide(" ") + l10n_util::GetStringUTF16( | 763 string16 actions; |
745 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_SEPERATOR) + | 764 string16 separator = ASCIIToWide(" ") + l10n_util::GetStringUTF16( |
746 ASCIIToWide(" "); | 765 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_SEPERATOR) + |
| 766 ASCIIToWide(" "); |
747 | 767 |
748 if (module->recommended_action & ModuleEnumerator::NONE) { | 768 if (module->recommended_action & ModuleEnumerator::NONE) { |
749 actions = l10n_util::GetStringUTF16( | 769 actions = l10n_util::GetStringUTF16( |
750 IDS_CONFLICTS_CHECK_INVESTIGATING); | 770 IDS_CONFLICTS_CHECK_INVESTIGATING); |
| 771 } |
| 772 if (module->recommended_action & ModuleEnumerator::UNINSTALL) { |
| 773 if (!actions.empty()) |
| 774 actions += separator; |
| 775 actions = l10n_util::GetStringUTF16( |
| 776 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UNINSTALL); |
| 777 } |
| 778 if (module->recommended_action & ModuleEnumerator::UPDATE) { |
| 779 if (!actions.empty()) |
| 780 actions += separator; |
| 781 actions += l10n_util::GetStringUTF16( |
| 782 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UPDATE); |
| 783 } |
| 784 if (module->recommended_action & ModuleEnumerator::DISABLE) { |
| 785 if (!actions.empty()) |
| 786 actions += separator; |
| 787 actions += l10n_util::GetStringUTF16( |
| 788 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_DISABLE); |
| 789 } |
| 790 string16 possible_resolution = actions.empty() ? ASCIIToWide("") : |
| 791 l10n_util::GetStringUTF16(IDS_CONFLICTS_CHECK_POSSIBLE_ACTIONS) + |
| 792 ASCIIToWide(" ") + |
| 793 actions; |
| 794 data->SetString("possibleResolution", possible_resolution); |
| 795 data->SetString("help_url", |
| 796 ConstructHelpCenterUrl(*module).spec().c_str()); |
751 } | 797 } |
752 if (module->recommended_action & ModuleEnumerator::UNINSTALL) { | |
753 if (!actions.empty()) | |
754 actions += separator; | |
755 actions = l10n_util::GetStringUTF16( | |
756 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UNINSTALL); | |
757 } | |
758 if (module->recommended_action & ModuleEnumerator::UPDATE) { | |
759 if (!actions.empty()) | |
760 actions += separator; | |
761 actions += l10n_util::GetStringUTF16( | |
762 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UPDATE); | |
763 } | |
764 if (module->recommended_action & ModuleEnumerator::DISABLE) { | |
765 if (!actions.empty()) | |
766 actions += separator; | |
767 actions += l10n_util::GetStringUTF16( | |
768 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_DISABLE); | |
769 } | |
770 string16 possible_resolution = actions.empty() ? ASCIIToWide("") : | |
771 l10n_util::GetStringUTF16(IDS_CONFLICTS_CHECK_POSSIBLE_ACTIONS) + | |
772 ASCIIToWide(" ") + | |
773 actions; | |
774 data->SetString("possibleResolution", possible_resolution); | |
775 data->SetString("help_url", ConstructHelpCenterUrl(*module).spec().c_str()); | |
776 | 798 |
777 list->Append(data); | 799 list->Append(data); |
778 } | 800 } |
779 | 801 |
780 lock->Release(); | 802 lock->Release(); |
781 return list; | 803 return list; |
782 } | 804 } |
783 | 805 |
784 EnumerateModulesModel::EnumerateModulesModel() | 806 EnumerateModulesModel::EnumerateModulesModel() |
785 : scanning_(false), | 807 : scanning_(false), |
| 808 limited_mode_(false), |
786 confirmed_bad_modules_detected_(0), | 809 confirmed_bad_modules_detected_(0), |
787 suspected_bad_modules_detected_(0) { | 810 suspected_bad_modules_detected_(0) { |
788 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); | 811 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); |
789 if (cmd_line.HasSwitch(switches::kConflictingModulesCheck)) { | 812 if (cmd_line.HasSwitch(switches::kConflictingModulesCheck)) { |
790 check_modules_timer_.Start( | 813 check_modules_timer_.Start( |
791 base::TimeDelta::FromMilliseconds(kModuleCheckDelayMs), | 814 base::TimeDelta::FromMilliseconds(kModuleCheckDelayMs), |
792 this, &EnumerateModulesModel::ScanNow); | 815 this, &EnumerateModulesModel::ScanNow); |
793 } | 816 } |
794 | 817 |
795 lock = new Lock(); | 818 lock = new Lock(); |
(...skipping 16 matching lines...) Expand all Loading... |
812 } | 835 } |
813 | 836 |
814 scanning_ = false; | 837 scanning_ = false; |
815 lock->Release(); | 838 lock->Release(); |
816 | 839 |
817 HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules", | 840 HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules", |
818 suspected_bad_modules_detected_); | 841 suspected_bad_modules_detected_); |
819 HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules", | 842 HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules", |
820 confirmed_bad_modules_detected_); | 843 confirmed_bad_modules_detected_); |
821 | 844 |
822 NotificationService::current()->Notify( | 845 if (!limited_mode_) { |
823 NotificationType::MODULE_LIST_ENUMERATED, | 846 NotificationService::current()->Notify( |
824 Source<EnumerateModulesModel>(this), | 847 NotificationType::MODULE_LIST_ENUMERATED, |
825 NotificationService::NoDetails()); | 848 Source<EnumerateModulesModel>(this), |
| 849 NotificationService::NoDetails()); |
826 | 850 |
827 if (suspected_bad_modules_detected_ || confirmed_bad_modules_detected_) { | 851 if (suspected_bad_modules_detected_ || confirmed_bad_modules_detected_) { |
828 bool found_confirmed_bad_modules = confirmed_bad_modules_detected_ > 0; | 852 bool found_confirmed_bad_modules = confirmed_bad_modules_detected_ > 0; |
829 NotificationService::current()->Notify( | 853 NotificationService::current()->Notify( |
830 NotificationType::MODULE_INCOMPATIBILITY_DETECTED, | 854 NotificationType::MODULE_INCOMPATIBILITY_DETECTED, |
831 Source<EnumerateModulesModel>(this), | 855 Source<EnumerateModulesModel>(this), |
832 Details<bool>(&found_confirmed_bad_modules)); | 856 Details<bool>(&found_confirmed_bad_modules)); |
| 857 } |
833 } | 858 } |
834 } | 859 } |
835 | 860 |
836 GURL EnumerateModulesModel::ConstructHelpCenterUrl( | 861 GURL EnumerateModulesModel::ConstructHelpCenterUrl( |
837 const ModuleEnumerator::Module& module) { | 862 const ModuleEnumerator::Module& module) { |
838 if (!(module.recommended_action & ModuleEnumerator::SEE_LINK)) | 863 if (!(module.recommended_action & ModuleEnumerator::SEE_LINK)) |
839 return GURL(); | 864 return GURL(); |
840 | 865 |
841 // Construct the needed hashes. | 866 // Construct the needed hashes. |
842 std::string filename, location, description, signer; | 867 std::string filename, location, description, signer; |
843 GenerateHash(WideToUTF8(module.name), &filename); | 868 GenerateHash(WideToUTF8(module.name), &filename); |
844 GenerateHash(WideToUTF8(module.location), &location); | 869 GenerateHash(WideToUTF8(module.location), &location); |
845 GenerateHash(WideToUTF8(module.description), &description); | 870 GenerateHash(WideToUTF8(module.description), &description); |
846 GenerateHash(WideToUTF8(module.digital_signer), &signer); | 871 GenerateHash(WideToUTF8(module.digital_signer), &signer); |
847 | 872 |
848 string16 url = l10n_util::GetStringF(IDS_HELP_CENTER_VIEW_CONFLICTS, | 873 string16 url = l10n_util::GetStringF(IDS_HELP_CENTER_VIEW_CONFLICTS, |
849 ASCIIToWide(filename), ASCIIToWide(location), | 874 ASCIIToWide(filename), ASCIIToWide(location), |
850 ASCIIToWide(description), ASCIIToWide(signer)); | 875 ASCIIToWide(description), ASCIIToWide(signer)); |
851 return GURL(WideToUTF8(url)); | 876 return GURL(WideToUTF8(url)); |
852 } | 877 } |
OLD | NEW |