diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/app_controller_mac.mm | 13 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_cocoa.mm | 10 | ||||
-rw-r--r-- | chrome/browser/cocoa/bug_report_window_controller.h | 88 | ||||
-rw-r--r-- | chrome/browser/cocoa/bug_report_window_controller.mm | 157 | ||||
-rw-r--r-- | chrome/browser/cocoa/bug_report_window_controller_unittest.mm | 71 |
5 files changed, 338 insertions, 1 deletions
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index d9c4082..c173740 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm @@ -21,6 +21,7 @@ #import "chrome/browser/cocoa/bookmark_menu_bridge.h" #import "chrome/browser/cocoa/browser_window_cocoa.h" #import "chrome/browser/cocoa/browser_window_controller.h" +#import "chrome/browser/cocoa/bug_report_window_controller.h" #import "chrome/browser/cocoa/history_menu_bridge.h" #import "chrome/browser/cocoa/clear_browsing_data_controller.h" #import "chrome/browser/cocoa/encoding_menu_controller_delegate_mac.h" @@ -528,6 +529,17 @@ static bool g_is_opening_new_window = false; case IDC_HELP_PAGE: Browser::OpenHelpWindow(defaultProfile); break; + case IDC_REPORT_BUG: { + Browser* browser = BrowserList::GetLastActive(); + TabContents* current_tab = (browser != NULL) ? + browser->GetSelectedTabContents() : NULL; + BugReportWindowController* controller = + [[BugReportWindowController alloc] + initWithTabContents:current_tab + profile:[self defaultProfile]]; + [controller runModalDialog]; + break; + } }; } @@ -563,6 +575,7 @@ static bool g_is_opening_new_window = false; menuState_->UpdateCommandEnabled(IDC_SHOW_HISTORY, true); menuState_->UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true); menuState_->UpdateCommandEnabled(IDC_HELP_PAGE, true); + menuState_->UpdateCommandEnabled(IDC_REPORT_BUG, true); // TODO(pinkerton): ...more to come... } diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 398948e..9eee4c7 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -9,6 +9,7 @@ #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/cocoa/browser_window_cocoa.h" #import "chrome/browser/cocoa/browser_window_controller.h" +#import "chrome/browser/cocoa/bug_report_window_controller.h" #import "chrome/browser/cocoa/clear_browsing_data_controller.h" #import "chrome/browser/cocoa/download_shelf_controller.h" #import "chrome/browser/cocoa/html_dialog_window_controller.h" @@ -246,7 +247,14 @@ DownloadShelf* BrowserWindowCocoa::GetDownloadShelf() { } void BrowserWindowCocoa::ShowReportBugDialog() { - NOTIMPLEMENTED(); + TabContents* current_tab = browser_->GetSelectedTabContents(); + if (current_tab && current_tab->controller().GetActiveEntry()) { + BugReportWindowController* controller = + [[BugReportWindowController alloc] + initWithTabContents:current_tab + profile:browser_->profile()]; + [controller runModalDialog]; + } } void BrowserWindowCocoa::ShowClearBrowsingDataDialog() { diff --git a/chrome/browser/cocoa/bug_report_window_controller.h b/chrome/browser/cocoa/bug_report_window_controller.h new file mode 100644 index 0000000..93eea0a --- /dev/null +++ b/chrome/browser/cocoa/bug_report_window_controller.h @@ -0,0 +1,88 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_BUG_REPORT_WINDOW_CONTROLLER_H_ +#define CHROME_BROWSER_COCOA_BUG_REPORT_WINDOW_CONTROLLER_H_ + +#import <Cocoa/Cocoa.h> + +#include <vector> + +#include "base/scoped_ptr.h" + +class Profile; +class TabContents; + +// A window controller for managing the "Report Bug" feature. Modally +// presents a dialog that allows the user to either file a bug report on +// a broken page, or go directly to Google's "Report Phishing" page and +// file a report there. +@interface BugReportWindowController : NSWindowController { + @private + TabContents* currentTab_; // Weak, owned by browser. + Profile* profile_; // Weak, owned by browser. + + // Holds screenshot of current tab. + std::vector<unsigned char> pngData_; + + // Values bound to data in the dialog box. These values cannot be boxed in + // scoped_nsobjects because we use them for bindings. + NSString* bugDescription_; // Strong. + NSUInteger bugType_; + NSString* pageTitle_; // Strong. + NSString* pageURL_; // Strong. + + // We keep a pointer to this button so we can change its title. + NSButton* sendReportButton_; // Weak. + + BOOL sendScreenshot_; + + // Disable screenshot if no browser window is open. + BOOL disableScreenshot_; + + // Menu for the bug type popup button. We create it here instead of in + // IB so that we can nicely check whether the phishing page is selected, + // and so that we can create a menu without "page" options when no browser + // window is open. + NSArray* bugTypeList_; // Strong. +} + +// Initialize with the contents of the tab to be reported as buggy / wrong. +// If dialog is called without an open window, currentTab may be null; in +// that case, a dialog is opened with options for reporting a bugs not +// related to a specific page. Profile is passed to BugReportUtil, who +// will not send a report if the value is null. +- (id)initWithTabContents:(TabContents*)currentTab profile:(Profile*)profile; + +// Run the dialog with an application-modal event loop. If the user accepts, +// send the report of the bug or broken web site. +- (void)runModalDialog; + +// IBActions for the dialog buttons. +- (IBAction)sendReport:(id)sender; +- (IBAction)cancel:(id)sender; + +// YES if the user has selected the phishing report option. +- (BOOL)isPhishingReport; + +// The "send report" button may need to change its title to reflect that it's +// bouncing to the phish report page instead of sending a report directly +// from the dialog box (or vice versa). Observe the menu of bug types +// and change the button title along with the selected bug. +- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item; + +// Properties for bindings. +@property (copy, nonatomic) NSString* bugDescription; +@property NSUInteger bugType; +@property (copy, nonatomic) NSString* pageTitle; +@property (copy, nonatomic) NSString* pageURL; +@property (assign, nonatomic) IBOutlet NSButton* sendReportButton; +@property BOOL sendScreenshot; +@property BOOL disableScreenshot; +@property (readonly, nonatomic) NSArray* bugTypeList; + +@end + +#endif // CHROME_BROWSER_COCOA_BUG_REPORT_WINDOW_CONTROLLER_H_ + diff --git a/chrome/browser/cocoa/bug_report_window_controller.mm b/chrome/browser/cocoa/bug_report_window_controller.mm new file mode 100644 index 0000000..6fd7e5d --- /dev/null +++ b/chrome/browser/cocoa/bug_report_window_controller.mm @@ -0,0 +1,157 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/bug_report_window_controller.h" + +#include "app/l10n_util_mac.h" +#include "base/mac_util.h" +#include "base/sys_string_conversions.h" +#include "chrome/browser/bug_report_util.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" + +@implementation BugReportWindowController + +@synthesize bugDescription = bugDescription_; +@synthesize bugType = bugType_; +@synthesize pageURL = pageURL_; +@synthesize pageTitle = pageTitle_; +@synthesize sendReportButton = sendReportButton_; +@synthesize sendScreenshot = sendScreenshot_; +@synthesize disableScreenshot = disableScreenshot_; +@synthesize bugTypeList = bugTypeList_; + +- (id)initWithTabContents:(TabContents*)currentTab + profile:(Profile*)profile { + NSString* nibpath = [mac_util::MainAppBundle() pathForResource:@"ReportBug" + ofType:@"nib"]; + if ((self = [super initWithWindowNibPath:nibpath owner:self])) { + currentTab_ = currentTab; + profile_ = profile; + [self setBugDescription:@""]; + + if (currentTab_ != NULL) { + // Get data from current tab, if one exists. This dialog could be called + // from the main menu with no tab contents, so currentTab_ is not + // guaranteed to be non-NULL. + // TODO(mirandac): This dialog should be a tab-modal sheet if a browser + // window exists. + [self setSendScreenshot:YES]; + [self setDisableScreenshot:NO]; + bugTypeList_ = [[NSArray alloc] initWithObjects: + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_PAGE_WONT_LOAD), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_PAGE_LOOKS_ODD), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_PHISHING_PAGE), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_CANT_SIGN_IN), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_CHROME_MISBEHAVES), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_SOMETHING_MISSING), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_BROWSER_CRASH), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_OTHER_PROBLEM), + nil]; + [self setPageURL:base::SysUTF8ToNSString( + currentTab_->controller().GetActiveEntry()->url().spec())]; + [self setPageTitle:base::SysUTF16ToNSString(currentTab_->GetTitle())]; + mac_util::GrabWindowSnapshot( + currentTab_->view()->GetTopLevelNativeWindow(), &pngData_); + } else { + // If no current tab exists, create a menu without the "broken page" + // options, with page URL and title empty, and screenshot disabled. + [self setSendScreenshot:NO]; + [self setDisableScreenshot:YES]; + bugTypeList_ = [[NSArray alloc] initWithObjects: + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_CHROME_MISBEHAVES), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_SOMETHING_MISSING), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_BROWSER_CRASH), + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_OTHER_PROBLEM), + nil]; + // Because "Report Bug" is being called with no browser open in this + // case, make URL and title empty. + [self setPageURL:@""]; + [self setPageTitle:@""]; + } + } + return self; +} + +- (void)dealloc { + [pageURL_ release]; + [pageTitle_ release]; + [bugDescription_ release]; + [bugTypeList_ release]; + [super dealloc]; +} + +// Delegate callback so that closing the window deletes the controller. +- (void)windowWillClose:(NSNotification*)notification { + [self autorelease]; +} + +- (void)closeDialog { + [NSApp stopModal]; + [[self window] close]; +} + +- (void)runModalDialog { + [NSApp runModalForWindow:[self window]]; +} + +- (IBAction)sendReport:(id)sender { + if ([self isPhishingReport]) { + BugReportUtil::ReportPhishing(currentTab_, + base::SysNSStringToUTF8(pageURL_)); + } else { + BugReportUtil::SendReport( + profile_, + base::SysNSStringToUTF8(pageTitle_), + bugType_, + base::SysNSStringToUTF8(pageURL_), + base::SysNSStringToUTF8(bugDescription_), + sendScreenshot_ && !pngData_.empty() ? + reinterpret_cast<const char *>(&(pngData_[0])) : NULL, + pngData_.size()); + } + [self closeDialog]; +} + +- (IBAction)cancel:(id)sender { + [self closeDialog]; +} + +- (BOOL)isPhishingReport { + return bugType_ == [bugTypeList_ indexOfObject: + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_PHISHING_PAGE)]; +} + +- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item { + NSString* buttonTitle = [[item title] isEqualToString: + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_PHISHING_PAGE)] ? + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_SEND_PHISHING_REPORT) : + l10n_util::GetNSStringWithFixup(IDS_BUGREPORT_SEND_REPORT); + if (![buttonTitle isEqualToString:[sendReportButton_ title]]) { + [sendReportButton_ setTitle:buttonTitle]; + CGFloat deltaWidth = + [GTMUILocalizerAndLayoutTweaker sizeToFitView:sendReportButton_].width; + NSRect newButtonFrame = [sendReportButton_ frame]; + newButtonFrame.origin.x -= deltaWidth; + [sendReportButton_ setFrame:newButtonFrame]; + } +} + +// BugReportWindowController needs to change the title of the Send Report +// button when the user chooses the phishing bug type, so we need to bind +// the function that changes the button title to the bug type key. ++ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString*)key { + NSSet* paths = [super keyPathsForValuesAffectingValueForKey:key]; + if ([key isEqualToString:@"isPhishingReport"]) { + paths = [paths setByAddingObject:@"bugType"]; + } + return paths; +} + +@end + + diff --git a/chrome/browser/cocoa/bug_report_window_controller_unittest.mm b/chrome/browser/cocoa/bug_report_window_controller_unittest.mm new file mode 100644 index 0000000..6b15c4a --- /dev/null +++ b/chrome/browser/cocoa/bug_report_window_controller_unittest.mm @@ -0,0 +1,71 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> + +#include "base/ref_counted.h" +#import "chrome/browser/cocoa/bug_report_window_controller.h" +#include "chrome/browser/renderer_host/site_instance.h" +#include "chrome/browser/renderer_host/test/test_render_view_host.h" +#include "chrome/browser/tab_contents/test_tab_contents.h" +#include "chrome/browser/profile.h" + +namespace { + +class BugReportWindowControllerUnittest : public RenderViewHostTestHarness { +}; + +TEST_F(BugReportWindowControllerUnittest, ReportBugWithNewTabPageOpen) { + // Create a "chrome://newtab" test tab. SiteInstance will be deleted when + // tabContents is deleted. + SiteInstance* instance = + SiteInstance::CreateSiteInstance(profile_.get()); + TestTabContents* tabContents = new TestTabContents(profile_.get(), + instance); + tabContents->controller().LoadURL(GURL("chrome://newtab"), + GURL(), PageTransition::START_PAGE); + + BugReportWindowController* controller = [[BugReportWindowController alloc] + initWithTabContents:tabContents + profile:profile_.get()]; + + // The phishing report bug is stored at index 2 in the Report Bug dialog. + [controller setBugType:2]; + EXPECT_TRUE([controller isPhishingReport]); + [controller setBugType:1]; + EXPECT_FALSE([controller isPhishingReport]); + + // Make sure that the tab was correctly recorded. + EXPECT_TRUE([[controller pageURL] isEqualToString:@"chrome://newtab/"]); + EXPECT_TRUE([[controller pageTitle] isEqualToString:@"New Tab"]); + + // When we call "report bug" with non-empty tab contents, all menu options + // should be available, and we should send screenshot by default. + EXPECT_EQ([[controller bugTypeList] count], 8U); + EXPECT_TRUE([controller sendScreenshot]); + + delete tabContents; + [controller release]; +} + +TEST_F(BugReportWindowControllerUnittest, ReportBugWithNoWindowOpen) { + BugReportWindowController* controller = [[BugReportWindowController alloc] + initWithTabContents:NULL + profile:profile_.get()]; + + // Make sure that no page title or URL are recorded. + EXPECT_TRUE([[controller pageURL] isEqualToString:@""]); + EXPECT_TRUE([[controller pageTitle] isEqualToString:@""]); + + // When we call "report bug" with empty tab contents, only menu options + // that don't refer to a specific page should be available, and the send + // screenshot option should be turned off. + EXPECT_EQ([[controller bugTypeList] count], 4U); + EXPECT_FALSE([controller sendScreenshot]); + + [controller release]; +} + +} // namespace + |