зеркало из https://github.com/mozilla/pjs.git
Backing out bug 178607 because I forgot to test before committing, and I'm seeing peristent crashes and hangs locally.
This commit is contained in:
Родитель
408fb87bd4
Коммит
7cd758b8f6
|
@ -1,83 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Camino code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Bryan Atwood
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bryan Atwood <bryan.h.atwood@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
// AutoCompleteResults
|
||||
//
|
||||
// Container object for generic auto complete.
|
||||
// Holds the search string, array of matched objects and the default item.
|
||||
//
|
||||
@interface AutoCompleteResults : NSObject
|
||||
{
|
||||
NSString* mSearchString; // strong
|
||||
NSArray* mMatches; // strong
|
||||
int mDefaultIndex;
|
||||
}
|
||||
- (NSString*)searchString;
|
||||
- (void)setSearchString:(NSString*)string;
|
||||
|
||||
- (NSArray*)matches;
|
||||
- (void)setMatches:(NSArray*)matches;
|
||||
|
||||
- (int)defaultIndex;
|
||||
- (void)setDefaultIndex:(int)defaultIndex;
|
||||
|
||||
@end
|
||||
|
||||
// AutoCompleteListener
|
||||
//
|
||||
// This defines the protocol methods for the object that listens for auto complete
|
||||
// results. |onAutoComplete| is called by the object that searches the data and
|
||||
// the results are returned to the originating caller as AutoCompleteResults.
|
||||
//
|
||||
@protocol AutoCompleteListener
|
||||
- (void)autoCompleteFoundResults:(AutoCompleteResults*)results;
|
||||
@end
|
||||
|
||||
// AutoCompleteSession
|
||||
//
|
||||
// An AutoCompleteSession object listens for search requests and searches a set of data
|
||||
// |startAutoCompleteWithSearch| initiates the process. Previous results are passed in
|
||||
// as well as the listener object for when the search is complete.
|
||||
//
|
||||
@protocol AutoCompleteSession
|
||||
- (void)startAutoCompleteWithSearch:(NSString*)searchString
|
||||
previousResults:(AutoCompleteResults*)previousSearchResults
|
||||
listener:(id<AutoCompleteListener>)listener;
|
||||
@end
|
|
@ -1,87 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Camino code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Bryan Atwood
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bryan Atwood <bryan.h.atwood@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "AutoCompleteUtils.h"
|
||||
|
||||
@implementation AutoCompleteResults
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[mSearchString release];
|
||||
[mMatches release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString*)searchString
|
||||
{
|
||||
return mSearchString;
|
||||
}
|
||||
|
||||
- (void)setSearchString:(NSString*)string
|
||||
{
|
||||
[mSearchString release];
|
||||
|
||||
// The caller might change the string, so keep a copy.
|
||||
mSearchString = [string copy];
|
||||
}
|
||||
|
||||
- (NSArray*)matches
|
||||
{
|
||||
return mMatches;
|
||||
}
|
||||
|
||||
- (void)setMatches:(NSArray*)matches
|
||||
{
|
||||
if (mMatches != matches) {
|
||||
[mMatches release];
|
||||
mMatches = [matches retain];
|
||||
}
|
||||
}
|
||||
|
||||
- (int)defaultIndex
|
||||
{
|
||||
return mDefaultIndex;
|
||||
}
|
||||
|
||||
- (void)setDefaultIndex:(int)index
|
||||
{
|
||||
mDefaultIndex = index;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,100 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Camino code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Bryan Atwood
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bryan Atwood <bryan.h.atwood@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "AutoCompleteUtils.h"
|
||||
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
extern const int kFormFillMaxRows;
|
||||
|
||||
@class KeychainAutoCompleteSession;
|
||||
@class CHBrowserView;
|
||||
@class FormFillPopup;
|
||||
@class FormFillController;
|
||||
|
||||
class nsIDOMHTMLInputElement;
|
||||
|
||||
// FormFillListener
|
||||
//
|
||||
// The FormFillListener object listens for DOM events and the corresponding
|
||||
// methods in the FormFillController are called for handling.
|
||||
//
|
||||
class FormFillListener : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
FormFillListener(FormFillController* aController);
|
||||
|
||||
protected:
|
||||
FormFillController* mController; // weak
|
||||
};
|
||||
|
||||
// FormFillController
|
||||
//
|
||||
// Manages the FormFillPopup windows that contain search results
|
||||
// as well as sending search requests to the KeychainAutoCompleteSession
|
||||
// and listening for search results. This can be extended to send
|
||||
// search requests to a form history session as well.
|
||||
@interface FormFillController : NSObject <AutoCompleteListener>
|
||||
{
|
||||
KeychainAutoCompleteSession* mKeychainSession; // strong
|
||||
AutoCompleteResults* mResults; // strong
|
||||
FormFillListener* mListener; // strong
|
||||
FormFillPopup* mPopupWindow; // strong
|
||||
|
||||
CHBrowserView* mBrowserView; // weak
|
||||
nsIDOMHTMLInputElement* mFocusedInputElement; // weak
|
||||
|
||||
// mCompleteResult determines if the current search should complete the default
|
||||
// result when ready. This prevents backspace/delete from autocompleting.
|
||||
BOOL mCompleteResult;
|
||||
|
||||
// mUsernameFillEnabled determines whether we send searches to the Keychain
|
||||
// Service. Form fill history value can be added here as well.
|
||||
BOOL mUsernameFillEnabled;
|
||||
}
|
||||
|
||||
- (void)attachToBrowser:(CHBrowserView*)browser;
|
||||
|
||||
// Callback function for when a row in the focused popup window is clicked.
|
||||
- (void)popupSelected;
|
||||
|
||||
@end
|
|
@ -1,748 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Camino code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Bryan Atwood
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bryan Atwood <bryan.h.atwood@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "FormFillController.h"
|
||||
#import "CHBrowserView.h"
|
||||
#import "FormFillPopup.h"
|
||||
#import "KeychainAutoCompleteSession.h"
|
||||
#import "PreferenceManager.h"
|
||||
|
||||
#import "NSString+Gecko.h"
|
||||
#import "NSArray+Utils.h"
|
||||
|
||||
#include "GeckoUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMDocumentEvent.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMNSHTMLInputElement.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
|
||||
const int kFormFillMaxRows = 10;
|
||||
|
||||
@interface FormFillController(Private)
|
||||
|
||||
// Listener and autocomplete initialization and cleanup
|
||||
- (void)browserResized:(NSNotification*)notification;
|
||||
- (void)addResizeObserver:(NSWindow*)browserWindow;
|
||||
- (void)removeResizeObserver:(NSWindow*)browserWindow;
|
||||
- (void)addWindowListeners:(nsIDOMWindow*)aWindow;
|
||||
- (void)removeWindowListeners:(nsIDOMWindow*)aWindow;
|
||||
- (void)startControllingInputElement:(nsIDOMHTMLInputElement*)aInputElement;
|
||||
- (void)stopControllingInputElement;
|
||||
|
||||
// Popup window management
|
||||
- (BOOL)isPopupOpen;
|
||||
- (void)openPopup;
|
||||
- (void)closePopup;
|
||||
- (void)shiftRowSelectionBy:(int)aRows;
|
||||
|
||||
// Autocomplete methods
|
||||
- (void)startSearch:(NSString*)searchString;
|
||||
- (void)dataReady;
|
||||
- (void)autoCompleteFieldText;
|
||||
- (void)filledAutoCompleteFieldText;
|
||||
|
||||
// Event handlers
|
||||
- (void)focus:(nsIDOMEvent*)aEvent;
|
||||
- (void)blur:(nsIDOMEvent*)aEvent;
|
||||
- (void)unload:(nsIDOMEvent*)aEvent;
|
||||
- (void)submit:(nsIDOMEvent*)aEvent;
|
||||
- (void)input:(nsIDOMEvent*)aEvent;
|
||||
- (void)keyPress:(nsIDOMEvent*)aEvent;
|
||||
- (BOOL)handleKeyNavigation:(int)aKey;
|
||||
|
||||
// Utility methods
|
||||
- (BOOL)IsCaretAtEndOfLine;
|
||||
|
||||
@end
|
||||
|
||||
NS_IMPL_ISUPPORTS1(FormFillListener, nsIDOMEventListener)
|
||||
|
||||
FormFillListener::FormFillListener(FormFillController* aController)
|
||||
: mController(aController)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP FormFillListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString type;
|
||||
aEvent->GetType(type);
|
||||
|
||||
if (type.Equals(NS_LITERAL_STRING("focus")))
|
||||
[mController focus:aEvent];
|
||||
else if (type.Equals(NS_LITERAL_STRING("blur")))
|
||||
[mController blur:aEvent];
|
||||
else if (type.Equals(NS_LITERAL_STRING("unload")))
|
||||
[mController unload:aEvent];
|
||||
else if (type.Equals(NS_LITERAL_STRING("submit")))
|
||||
[mController submit:aEvent];
|
||||
else if (type.Equals(NS_LITERAL_STRING("input")))
|
||||
[mController input:aEvent];
|
||||
else if (type.Equals(NS_LITERAL_STRING("keypress")))
|
||||
[mController keyPress:aEvent];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@implementation FormFillController
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
// mListener captures DOM and auto complete events.
|
||||
mListener = new FormFillListener(self);
|
||||
NS_ADDREF(mListener);
|
||||
|
||||
// Initialize the password fill session.
|
||||
// History form fill session can also be added when someone writes it.
|
||||
mKeychainSession = [[KeychainAutoCompleteSession alloc] init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// Remove ourselves as a focus listener from cached view.
|
||||
nsCOMPtr<nsIDOMWindow> domWindow = [mBrowserView contentWindow];
|
||||
if (domWindow)
|
||||
[self removeWindowListeners:domWindow];
|
||||
|
||||
[self removeResizeObserver:[mBrowserView nativeWindow]];
|
||||
|
||||
[mResults release];
|
||||
[mKeychainSession release];
|
||||
[mPopupWindow release];
|
||||
NS_IF_RELEASE(mListener);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)attachToBrowser:(CHBrowserView*)browser
|
||||
{
|
||||
if (!browser)
|
||||
return;
|
||||
|
||||
mBrowserView = browser;
|
||||
|
||||
// Listen for focus events on the domWindow of the browser view.
|
||||
nsCOMPtr<nsIDOMWindow> domWindow = [mBrowserView contentWindow];
|
||||
if (domWindow)
|
||||
[self addWindowListeners:domWindow];
|
||||
}
|
||||
|
||||
- (void)browserResized:(NSNotification*)notification
|
||||
{
|
||||
[self closePopup];
|
||||
}
|
||||
|
||||
- (void)addResizeObserver:(NSWindow*)browserWindow
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(browserResized:)
|
||||
name:NSWindowDidResizeNotification
|
||||
object:browserWindow];
|
||||
}
|
||||
|
||||
- (void)removeResizeObserver:(NSWindow*)browserWindow
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:NSWindowDidResizeNotification
|
||||
object:browserWindow];
|
||||
}
|
||||
|
||||
- (void)addWindowListeners:(nsIDOMWindow*)aWindow
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> privateDOMWindow = do_QueryInterface(aWindow);
|
||||
if (!privateDOMWindow)
|
||||
return;
|
||||
|
||||
nsPIDOMEventTarget* chromeEventHandler = privateDOMWindow->GetChromeEventHandler();
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(chromeEventHandler);
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("focus"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("blur"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("unload"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("submit"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("input"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("keypress"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
- (void)removeWindowListeners:(nsIDOMWindow*)aWindow
|
||||
{
|
||||
[self stopControllingInputElement];
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> privateDOMWindow = do_QueryInterface(aWindow);
|
||||
if (!privateDOMWindow)
|
||||
return;
|
||||
|
||||
nsPIDOMEventTarget* chromeEventHandler = privateDOMWindow->GetChromeEventHandler();
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(chromeEventHandler);
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("focus"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("blur"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("unload"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("submit"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("input"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("keypress"),
|
||||
static_cast<nsIDOMEventListener*>(mListener),
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
- (void)startControllingInputElement:(nsIDOMHTMLInputElement*)aInputElement
|
||||
{
|
||||
// Make sure we're not still attached to an input element.
|
||||
[self stopControllingInputElement];
|
||||
|
||||
// Set the autocomplete session for this input. Currently, only password autocomplete
|
||||
// but other sessions like form fill history can be added here.
|
||||
mUsernameFillEnabled = [mKeychainSession attachToInput:aInputElement];
|
||||
|
||||
// If this is not a valid auto-complete input, we can return now.
|
||||
if (!mUsernameFillEnabled)
|
||||
return;
|
||||
|
||||
// Cache the input element.
|
||||
mFocusedInputElement = aInputElement;
|
||||
|
||||
// Create the popup window if it doesn't exist.
|
||||
if (!mPopupWindow) {
|
||||
mPopupWindow = [[FormFillPopup alloc] init];
|
||||
[mPopupWindow attachToController:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopControllingInputElement
|
||||
{
|
||||
if (mPopupWindow) {
|
||||
[self closePopup];
|
||||
[mPopupWindow setItems:nil];
|
||||
}
|
||||
|
||||
mFocusedInputElement = nsnull;
|
||||
|
||||
// Stop sending search requests to auto-form fill.
|
||||
mUsernameFillEnabled = NO;
|
||||
|
||||
[mResults release];
|
||||
mResults = nil;
|
||||
}
|
||||
|
||||
-(void)autoCompleteFoundResults:(AutoCompleteResults*)results
|
||||
{
|
||||
[mResults release];
|
||||
mResults = nil;
|
||||
|
||||
if ([[results matches] count] > 0) {
|
||||
mResults = [results retain];
|
||||
[self dataReady];
|
||||
}
|
||||
else {
|
||||
[mPopupWindow setItems:nil];
|
||||
[self closePopup];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isPopupOpen
|
||||
{
|
||||
return mPopupWindow ? [mPopupWindow isPopupOpen] : NO;
|
||||
}
|
||||
|
||||
- (void)openPopup
|
||||
{
|
||||
// Only open popup if it's not already open.
|
||||
if ([self isPopupOpen])
|
||||
return;
|
||||
|
||||
// Make sure input field is visible before showing popup.
|
||||
GeckoUtils::ScrollElementIntoView(mFocusedInputElement);
|
||||
|
||||
nsIntRect inputIntRect;
|
||||
if (!(GeckoUtils::GetFrameInScreenCoordinates(mFocusedInputElement, &inputIntRect)))
|
||||
return;
|
||||
|
||||
NSRect inputElementFrame = NSMakeRect(inputIntRect.x, inputIntRect.y, inputIntRect.width, inputIntRect.height);
|
||||
|
||||
NSScreen* mainScreen = [[NSScreen screens] firstObject]; // NSArray category method
|
||||
if (!mainScreen)
|
||||
return;
|
||||
|
||||
NSPoint origin = inputElementFrame.origin;
|
||||
float width = NSWidth(inputElementFrame);
|
||||
|
||||
// y-flip and subtract the control height to convert to cocoa coords
|
||||
origin.y = NSMaxY([mainScreen frame]) - inputElementFrame.origin.y - inputElementFrame.size.height;
|
||||
|
||||
// To account for the text box border, shift rectangle position to the right by 2 pixels
|
||||
// and reduce the width by 3 pixels.
|
||||
// TODO: check shift here, still not aligned sometimes.
|
||||
origin.x += 2.0;
|
||||
width -= 3.0;
|
||||
|
||||
[mPopupWindow openPopup:[mBrowserView nativeWindow] withOrigin:origin width:width];
|
||||
|
||||
// Listen for resize events to close the popup.
|
||||
[self addResizeObserver:[mBrowserView nativeWindow]];
|
||||
}
|
||||
|
||||
- (void)closePopup
|
||||
{
|
||||
if (mPopupWindow) {
|
||||
// Deselecting the row prevents a flash when popup is opened and default is selected.
|
||||
[mPopupWindow selectRow:-1];
|
||||
[mPopupWindow closePopup];
|
||||
[self removeResizeObserver:[mBrowserView nativeWindow]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)shiftRowSelectionBy:(int)aRows
|
||||
{
|
||||
int row = [mPopupWindow selectedRow] + aRows;
|
||||
|
||||
// pin result at top row
|
||||
if (row < 0)
|
||||
row = 0;
|
||||
|
||||
// pin result at bottom row
|
||||
int numRows = [mPopupWindow rowCount];
|
||||
if (row >= numRows)
|
||||
row = numRows - 1;
|
||||
|
||||
[mPopupWindow selectRow:row];
|
||||
}
|
||||
|
||||
//
|
||||
// popupSelected
|
||||
//
|
||||
// Called when a new item in the popup window is selected, either by mouse click
|
||||
// or keyboard movement. The form field is set to the value of the selected item
|
||||
// and an autocomplete event is sent for any listeners
|
||||
- (void)popupSelected
|
||||
{
|
||||
if (![self isPopupOpen] || !mResults)
|
||||
return;
|
||||
|
||||
int row = [mPopupWindow selectedRow];
|
||||
if (row < 0)
|
||||
return;
|
||||
|
||||
nsAutoString value;
|
||||
[[mPopupWindow resultForRow:row] assignTo_nsAString:value];
|
||||
mFocusedInputElement->SetValue(value);
|
||||
|
||||
// Auto-fill the input so that untyped letters are selected.
|
||||
nsCOMPtr<nsIDOMNSHTMLInputElement> nsInput = do_QueryInterface(mFocusedInputElement);
|
||||
if (nsInput) {
|
||||
int searchLength = [[mResults searchString] length];
|
||||
nsInput->SetSelectionStart((PRInt32)searchLength);
|
||||
}
|
||||
|
||||
// Send an autocomplete DOM event any time auto fill is done.
|
||||
[self filledAutoCompleteFieldText];
|
||||
}
|
||||
|
||||
- (void)startSearch:(NSString*)searchString;
|
||||
{
|
||||
// Check if password autocomplete is enabled.
|
||||
// Form history autocomplete can be added here.
|
||||
if (mUsernameFillEnabled) {
|
||||
[mKeychainSession startAutoCompleteWithSearch:searchString
|
||||
previousResults:mResults
|
||||
listener:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dataReady
|
||||
{
|
||||
[mPopupWindow setItems:[mResults matches]];
|
||||
|
||||
// Open the popup if more than one result is returned.
|
||||
// Also require mCompleteResult since it prevents a backspace from opening popup
|
||||
// even though we want to search on a backspace to get the larger result set.
|
||||
if ([mPopupWindow rowCount] > 1 && mCompleteResult)
|
||||
[self openPopup];
|
||||
else
|
||||
[self closePopup];
|
||||
|
||||
// Prevents backspace from auto-completing the result we just erased.
|
||||
if (mCompleteResult)
|
||||
[self autoCompleteFieldText];
|
||||
}
|
||||
|
||||
//
|
||||
// autoCompleteFieldText
|
||||
//
|
||||
// Called when FormFillController should fill the text field with the default
|
||||
// autocomplete result.
|
||||
- (void)autoCompleteFieldText
|
||||
{
|
||||
if (!mResults)
|
||||
return;
|
||||
|
||||
NSArray* matches = [mResults matches];
|
||||
|
||||
// Select the default if it's available.
|
||||
// Otherwise, select the first username in the list.
|
||||
int defaultIndex = [mResults defaultIndex];
|
||||
|
||||
nsAutoString value;
|
||||
[[matches objectAtIndex:defaultIndex] assignTo_nsAString:value];
|
||||
mFocusedInputElement->SetValue(value);
|
||||
|
||||
// Auto-fill the input such that untyped letters are selected.
|
||||
nsCOMPtr<nsIDOMNSHTMLInputElement> nsInput = do_QueryInterface(mFocusedInputElement);
|
||||
if (nsInput) {
|
||||
int searchLength = [[mResults searchString] length];
|
||||
nsInput->SetSelectionStart((PRInt32)searchLength);
|
||||
}
|
||||
|
||||
// Select the default entry in the popup.
|
||||
if ([self isPopupOpen])
|
||||
[mPopupWindow selectRow:defaultIndex];
|
||||
|
||||
// Send a DOM event any time auto fill is done.
|
||||
[self filledAutoCompleteFieldText];
|
||||
}
|
||||
|
||||
//
|
||||
// filledAutoCompleteFieldText
|
||||
//
|
||||
// Called whenever the form element is filled. It sends a DOM event
|
||||
// "DOMAutoComplete" that can be listened for, e.g., to fill a password
|
||||
// when a username element is completed.
|
||||
//
|
||||
- (void)filledAutoCompleteFieldText
|
||||
{
|
||||
if (!mFocusedInputElement)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mFocusedInputElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentEvent> doc = do_QueryInterface(domDoc);
|
||||
if (!doc)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
|
||||
if (!privateEvent)
|
||||
return;
|
||||
|
||||
event->InitEvent(NS_LITERAL_STRING("DOMAutoComplete"), PR_TRUE, PR_TRUE);
|
||||
|
||||
privateEvent->SetTrusted(PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mFocusedInputElement);
|
||||
|
||||
PRBool defaultActionEnabled;
|
||||
target->DispatchEvent(event, &defaultActionEnabled);
|
||||
}
|
||||
|
||||
//
|
||||
// focus
|
||||
//
|
||||
// When a new element is selected, check whether we allow autocomplete.
|
||||
// If autocomplete is allowed, start controlling the input to that element.
|
||||
//
|
||||
- (void)focus:(nsIDOMEvent*)aEvent
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(target);
|
||||
if (!inputElement)
|
||||
return;
|
||||
|
||||
nsAutoString type;
|
||||
inputElement->GetType(type);
|
||||
if (!type.LowerCaseEqualsLiteral("text"))
|
||||
return;
|
||||
|
||||
PRBool isReadOnly = PR_FALSE;
|
||||
if (NS_FAILED(inputElement->GetReadOnly(&isReadOnly)) || isReadOnly)
|
||||
return;
|
||||
|
||||
PRBool autoCompleteOverride = [[PreferenceManager sharedInstance] getBooleanPref:"wallet.crypto.autocompleteoverride" withSuccess:NULL];
|
||||
|
||||
if (!autoCompleteOverride) {
|
||||
nsAutoString autocomplete;
|
||||
inputElement->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
|
||||
|
||||
if (autocomplete.EqualsIgnoreCase("off"))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form;
|
||||
inputElement->GetForm(getter_AddRefs(form));
|
||||
if (form) {
|
||||
form->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
|
||||
if (autocomplete.EqualsIgnoreCase("off"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[self startControllingInputElement:inputElement];
|
||||
}
|
||||
|
||||
//
|
||||
// blur
|
||||
//
|
||||
// Anytime focus moves from an element, stop autocompleting it until next
|
||||
// input element is focused.
|
||||
//
|
||||
- (void)blur:(nsIDOMEvent*)aEvent
|
||||
{
|
||||
if (mFocusedInputElement)
|
||||
[self stopControllingInputElement];
|
||||
}
|
||||
|
||||
//
|
||||
// unload
|
||||
//
|
||||
// Stop autocompleting on a page if it is unloaded.
|
||||
//
|
||||
- (void)unload:(nsIDOMEvent*)aEvent
|
||||
{
|
||||
if (mFocusedInputElement) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> eventDoc = do_QueryInterface(target);
|
||||
nsCOMPtr<nsIDOMDocument> inputDoc;
|
||||
mFocusedInputElement->GetOwnerDocument(getter_AddRefs(inputDoc));
|
||||
|
||||
if (eventDoc == inputDoc)
|
||||
[self stopControllingInputElement];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// submit
|
||||
//
|
||||
// If a form is submitted, stop autocompleting.
|
||||
//
|
||||
- (void)submit:(nsIDOMEvent*)aEvent
|
||||
{
|
||||
if (mFocusedInputElement)
|
||||
[self stopControllingInputElement];
|
||||
}
|
||||
|
||||
//
|
||||
// input
|
||||
//
|
||||
// If an HTML input box is being controlled, do a search when input occurs.
|
||||
//
|
||||
- (void)input:(nsIDOMEvent*)aEvent
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(target);
|
||||
|
||||
if (input && mFocusedInputElement == input) {
|
||||
nsAutoString value;
|
||||
mFocusedInputElement->GetValue(value);
|
||||
[self startSearch:[NSString stringWith_nsAString:value]];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// keyPress
|
||||
//
|
||||
// This is triggered when a key is pressed but before an 'input' is triggered.
|
||||
// It also handles non-input keys like arrow keys.
|
||||
//
|
||||
- (void)keyPress:(nsIDOMEvent*)aEvent
|
||||
{
|
||||
if (!mFocusedInputElement)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
|
||||
if (!keyEvent)
|
||||
return;
|
||||
|
||||
// By default, allow keystroke to continue to the next listener.
|
||||
BOOL cancel = NO;
|
||||
|
||||
// By default, autocomplete on keystrokes that later trigger 'input' events.
|
||||
mCompleteResult = YES;
|
||||
|
||||
PRUint32 k;
|
||||
keyEvent->GetKeyCode(&k);
|
||||
switch (k) {
|
||||
case nsIDOMKeyEvent::DOM_VK_UP:
|
||||
case nsIDOMKeyEvent::DOM_VK_DOWN:
|
||||
case nsIDOMKeyEvent::DOM_VK_PAGE_UP:
|
||||
case nsIDOMKeyEvent::DOM_VK_PAGE_DOWN:
|
||||
cancel = [self handleKeyNavigation:k];
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_ESCAPE:
|
||||
case nsIDOMKeyEvent::DOM_VK_RETURN:
|
||||
cancel = [self isPopupOpen];
|
||||
[self closePopup];
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
|
||||
case nsIDOMKeyEvent::DOM_VK_DELETE:
|
||||
// Don't allow autocomplete of 'input' event if it's due to a back space or
|
||||
// delete.
|
||||
mCompleteResult = NO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cancel) {
|
||||
aEvent->StopPropagation();
|
||||
aEvent->PreventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// handleKeyNavigation
|
||||
//
|
||||
// Handles key events that are for navigation of the popup window.
|
||||
// Should return YES if the event should be cancelled and not propagated.
|
||||
//
|
||||
- (BOOL)handleKeyNavigation:(int)aKey
|
||||
{
|
||||
switch (aKey) {
|
||||
case nsIDOMKeyEvent::DOM_VK_UP:
|
||||
if ([self isPopupOpen]) {
|
||||
[self shiftRowSelectionBy:-1];
|
||||
[self popupSelected];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_DOWN:
|
||||
if ([self isPopupOpen]) {
|
||||
[self shiftRowSelectionBy:1];
|
||||
[self popupSelected];
|
||||
return YES;
|
||||
}
|
||||
else if ([self IsCaretAtEndOfLine]) {
|
||||
nsAutoString value;
|
||||
mFocusedInputElement->GetValue(value);
|
||||
[self startSearch:[NSString stringWith_nsAString:value]];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_PAGE_UP:
|
||||
if ([self isPopupOpen]) {
|
||||
[self shiftRowSelectionBy:-kFormFillMaxRows];
|
||||
[self popupSelected];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_PAGE_DOWN:
|
||||
if ([self isPopupOpen]) {
|
||||
[self shiftRowSelectionBy:kFormFillMaxRows];
|
||||
[self popupSelected];
|
||||
return YES;
|
||||
}
|
||||
else {
|
||||
nsAutoString value;
|
||||
mFocusedInputElement->GetValue(value);
|
||||
[self startSearch:[NSString stringWith_nsAString:value]];
|
||||
return YES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)IsCaretAtEndOfLine
|
||||
{
|
||||
if (!mFocusedInputElement)
|
||||
return NO;
|
||||
|
||||
nsCOMPtr<nsIDOMNSHTMLInputElement> nsInput = do_QueryInterface(mFocusedInputElement);
|
||||
if (!nsInput)
|
||||
return NO;
|
||||
|
||||
PRInt32 selectStart;
|
||||
nsInput->GetSelectionStart(&selectStart);
|
||||
|
||||
PRInt32 textLength;
|
||||
nsInput->GetTextLength(&textLength);
|
||||
|
||||
return (selectStart == textLength);
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,83 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Camino code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Bryan Atwood
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bryan Atwood <bryan.h.atwood@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class FormFillController;
|
||||
|
||||
//
|
||||
// FormFillPopupWindow
|
||||
//
|
||||
// The popup window needs to look like a "key" (activated) window even thought it's
|
||||
// a child window. This subclass overrides |isKeyWindow| to return YES so that it is
|
||||
// able to be a key window (and have activated scrollbars, etc) but not steal focus.
|
||||
//
|
||||
@interface FormFillPopupWindow : NSPanel
|
||||
@end
|
||||
|
||||
// FormFillPopup
|
||||
//
|
||||
// Manages the display of the popup window and receives data from the FormFillController.
|
||||
//
|
||||
@interface FormFillPopup : NSObject
|
||||
{
|
||||
FormFillPopupWindow* mPopupWin; // strong
|
||||
NSArray* mItems; // strong
|
||||
|
||||
NSTableView* mTableView; // weak
|
||||
FormFillController* mController; // weak
|
||||
}
|
||||
|
||||
- (void)attachToController:(FormFillController*)controller;
|
||||
|
||||
// openPopup expects an origin point in Cocoa coordinates and a width that
|
||||
// should be equal to the text box.
|
||||
- (void)openPopup:(NSWindow*)browserWindow withOrigin:(NSPoint)origin width:(float)width;
|
||||
- (void)resizePopup;
|
||||
- (void)closePopup;
|
||||
- (BOOL)isPopupOpen;
|
||||
|
||||
- (int)visibleRows;
|
||||
- (int)rowCount;
|
||||
- (void)selectRow:(int)index;
|
||||
- (int)selectedRow;
|
||||
|
||||
- (void)setItems:(NSArray*)items;
|
||||
- (NSString*)resultForRow:(int)index;
|
||||
|
||||
@end
|
|
@ -1,230 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Camino code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Bryan Atwood
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bryan Atwood <bryan.h.atwood@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "FormFillPopup.h"
|
||||
#import "FormFillController.h"
|
||||
|
||||
@implementation FormFillPopupWindow
|
||||
|
||||
- (BOOL)isKeyWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FormFillPopup(Private)
|
||||
|
||||
- (void)onRowClicked:(NSNotification *)aNote;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FormFillPopup
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
// Construct and configure the popup window.
|
||||
mPopupWin = [[FormFillPopupWindow alloc] initWithContentRect:NSMakeRect(0,0,0,0)
|
||||
styleMask:NSNonactivatingPanelMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
|
||||
[mPopupWin setReleasedWhenClosed:NO];
|
||||
[mPopupWin setHasShadow:YES];
|
||||
[mPopupWin setAlphaValue:0.9];
|
||||
|
||||
// Construct and configure the view.
|
||||
mTableView = [[[NSTableView alloc] initWithFrame:NSMakeRect(0,0,0,0)] autorelease];
|
||||
[mTableView setIntercellSpacing:NSMakeSize(1, 2)];
|
||||
[mTableView setTarget:self];
|
||||
[mTableView setAction:@selector(onRowClicked:)];
|
||||
|
||||
// Create the text column (only one).
|
||||
NSTableColumn* column = [[[NSTableColumn alloc] initWithIdentifier:@"usernames"] autorelease];
|
||||
[mTableView addTableColumn:column];
|
||||
|
||||
// Hide the table header.
|
||||
[mTableView setHeaderView:nil];
|
||||
|
||||
[mTableView setDataSource:self];
|
||||
|
||||
NSScrollView *scrollView = [[[NSScrollView alloc] initWithFrame:NSMakeRect(0,0,0,0)] autorelease];
|
||||
[scrollView setHasVerticalScroller:YES];
|
||||
[scrollView setAutohidesScrollers:YES];
|
||||
[[scrollView verticalScroller] setControlSize:NSSmallControlSize];
|
||||
|
||||
[scrollView setDocumentView:mTableView];
|
||||
|
||||
[mPopupWin setContentView:scrollView];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[mPopupWin release];
|
||||
[mItems release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)attachToController:(FormFillController*)controller
|
||||
{
|
||||
mController = controller;
|
||||
}
|
||||
|
||||
- (BOOL)isPopupOpen
|
||||
{
|
||||
return [mPopupWin isVisible];
|
||||
}
|
||||
|
||||
- (void)openPopup:(NSWindow*)browserWindow withOrigin:(NSPoint)origin width:(float)width
|
||||
{
|
||||
// Set the size of the popup window.
|
||||
NSRect tableViewFrame = [mTableView frame];
|
||||
tableViewFrame.size.width = width;
|
||||
[mTableView setFrame:tableViewFrame];
|
||||
|
||||
// Size the panel correctly.
|
||||
tableViewFrame.size.height = (int)([mTableView rowHeight] + [mTableView intercellSpacing].height) * [self visibleRows];
|
||||
[mPopupWin setContentSize:tableViewFrame.size];
|
||||
[mPopupWin setFrameTopLeftPoint:origin];
|
||||
|
||||
// Show the popup.
|
||||
if (![mPopupWin isVisible]) {
|
||||
[browserWindow addChildWindow:mPopupWin ordered:NSWindowAbove];
|
||||
[mPopupWin orderFront:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resizePopup
|
||||
{
|
||||
// Don't resize if popup isn't visible.
|
||||
if (![mPopupWin isVisible])
|
||||
return;
|
||||
|
||||
if ([self visibleRows] == 0) {
|
||||
[self closePopup];
|
||||
return;
|
||||
}
|
||||
|
||||
NSRect popupWinFrame = [mPopupWin frame];
|
||||
int tableHeight = (int)([mTableView rowHeight] + [mTableView intercellSpacing].height) * [self visibleRows];
|
||||
|
||||
popupWinFrame.origin.y += NSHeight(popupWinFrame) - tableHeight;
|
||||
popupWinFrame.size.height = tableHeight;
|
||||
|
||||
[mPopupWin setFrame:popupWinFrame display:YES];
|
||||
}
|
||||
|
||||
- (void)closePopup
|
||||
{
|
||||
// We can get -closePopup even if we didn't show it.
|
||||
if ([mPopupWin isVisible]) {
|
||||
[[mPopupWin parentWindow] removeChildWindow:mPopupWin];
|
||||
[mPopupWin orderOut:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onRowClicked:(NSNotification *)aNote
|
||||
{
|
||||
[mController popupSelected];
|
||||
[self closePopup];
|
||||
}
|
||||
|
||||
- (int)visibleRows
|
||||
{
|
||||
int minRows = [self rowCount];
|
||||
return (minRows < kFormFillMaxRows) ? minRows : kFormFillMaxRows;
|
||||
}
|
||||
|
||||
- (int)rowCount
|
||||
{
|
||||
if (!mItems)
|
||||
return 0;
|
||||
|
||||
return [mItems count];
|
||||
}
|
||||
|
||||
- (void)selectRow:(int)index
|
||||
{
|
||||
if (index == -1)
|
||||
[mTableView deselectAll:self];
|
||||
else {
|
||||
[mTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
|
||||
[mTableView scrollRowToVisible:index];
|
||||
}
|
||||
}
|
||||
|
||||
- (int)selectedRow
|
||||
{
|
||||
return [mTableView selectedRow];
|
||||
}
|
||||
|
||||
- (NSString*)resultForRow:(int)index
|
||||
{
|
||||
return [mItems objectAtIndex:index];
|
||||
}
|
||||
|
||||
- (void)setItems:(NSArray*)items
|
||||
{
|
||||
if (items != mItems) {
|
||||
[mItems release];
|
||||
mItems = [items retain];
|
||||
}
|
||||
|
||||
// Update the view any time we get new data
|
||||
[mTableView noteNumberOfRowsChanged];
|
||||
[self resizePopup];
|
||||
}
|
||||
|
||||
// methods for table view interaction
|
||||
-(int)numberOfRowsInTableView:(NSTableView*)aTableView
|
||||
{
|
||||
return [self rowCount];
|
||||
}
|
||||
|
||||
-(id)tableView:(NSTableView*)aTableView objectValueForTableColumn:(NSTableColumn*)aTableColumn row:(int)aRowIndex
|
||||
{
|
||||
return [self resultForRow:aRowIndex];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,85 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Camino code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Bryan Atwood
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bryan Atwood <bryan.h.atwood@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "AutoCompleteUtils.h"
|
||||
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIDOMHTMLInputElement;
|
||||
|
||||
//
|
||||
// KeychainAutoCompleteDOMListener
|
||||
//
|
||||
// Listens for password fill requests from the FormFillController when a
|
||||
// username is entered.
|
||||
class KeychainAutoCompleteDOMListener : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
void SetElements(nsIDOMHTMLInputElement* usernameElement,
|
||||
nsIDOMHTMLInputElement* passwordElement);
|
||||
|
||||
protected:
|
||||
// Fills the password with the keychain data from the cached username input
|
||||
// element.
|
||||
void FillPassword();
|
||||
|
||||
// Pointers to the login input elements so that the form doesn't need to
|
||||
// be searched when the same input element is attached again.
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> mUsernameElement; // strong
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> mPasswordElement; // strong
|
||||
};
|
||||
|
||||
@interface KeychainAutoCompleteSession : NSObject<AutoCompleteSession>
|
||||
{
|
||||
KeychainAutoCompleteDOMListener* mDOMListener; // strong
|
||||
NSMutableArray* mUsernames; // strong
|
||||
NSString* mDefaultUser; // strong
|
||||
|
||||
// Cache the username input element so that we don't reread the keychain for
|
||||
// the same element.
|
||||
nsIDOMHTMLInputElement* mUsernameElement; // weak
|
||||
}
|
||||
|
||||
- (BOOL)attachToInput:(nsIDOMHTMLInputElement*)usernameElement;
|
||||
|
||||
@end
|
Загрузка…
Ссылка в новой задаче